@@ -5648,7 +5648,8 @@ static void mds_peer_reset(struct ceph_connection *con)
struct ceph_mds_client *mdsc = s->s_mdsc;
pr_warn("mds%d closed our session\n", s->s_mds);
- send_mds_reconnect(mdsc, s);
+ if (!mdsc->no_reconnect)
+ send_mds_reconnect(mdsc, s);
}
static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
@@ -413,6 +413,7 @@ struct ceph_mds_client {
atomic_t num_sessions;
int max_sessions; /* len of sessions array */
int stopping; /* true if shutting down */
+ int no_reconnect; /* true if snap trace is corrupted */
atomic64_t quotarealms_count; /* # realms with quota */
/*
@@ -767,8 +767,10 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
struct ceph_snap_realm *realm;
struct ceph_snap_realm *first_realm = NULL;
struct ceph_snap_realm *realm_to_rebuild = NULL;
+ struct ceph_client *client = mdsc->fsc->client;
int rebuild_snapcs;
int err = -ENOMEM;
+ int ret;
LIST_HEAD(dirty_realms);
lockdep_assert_held_write(&mdsc->snap_rwsem);
@@ -885,6 +887,29 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
if (first_realm)
ceph_put_snap_realm(mdsc, first_realm);
pr_err("%s error %d\n", __func__, err);
+
+ /*
+ * When receiving a corrupted snap trace we don't know what
+ * exactly has happened in MDS side. And we shouldn't continue
+ * writing to OSD, which may corrupt the snapshot contents.
+ *
+ * Just try to blocklist this kclient and if it fails we need
+ * to crash the kclient instead of leaving it writeable.
+ *
+ * Then this kclient must be remounted to continue after the
+ * corrupted metadata fixed in the MDS side.
+ */
+ mdsc->no_reconnect = 1;
+ ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr);
+ if (ret) {
+ pr_err("%s blocklist of %s failed: %d", __func__,
+ ceph_pr_addr(&client->msgr.inst.addr), ret);
+ BUG();
+ }
+ WARN(1, "%s %s was blocklisted, do remount to continue%s",
+ __func__, ceph_pr_addr(&client->msgr.inst.addr),
+ err == -EIO ? " after corrupted snaptrace fixed": "");
+
return err;
}