Blob Blame History Raw
From: Jeff Layton <jlayton@kernel.org>
Date: Thu, 30 Sep 2021 08:33:13 -0400
Subject: ceph: skip existing superblocks that are blocklisted or shut down
 when mounting
Git-commit: 98d0a6fb7303a6f4a120b8b8ed05b86ff5db53e8
Patch-mainline: v5.15-rc7
References: bsc#1192040

Currently when mounting, we may end up finding an existing superblock
that corresponds to a blocklisted MDS client. This means that the new
mount ends up being unusable.

If we've found an existing superblock with a client that is already
blocklisted, and the client is not configured to recover on its own,
fail the match. Ditto if the superblock has been forcibly unmounted.

While we're in here, also rename "other" to the more conventional "fsc".

Cc: stable@vger.kernel.org
URL: https://bugzilla.redhat.com/show_bug.cgi?id=1901499
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
[luis: use 'fsc->blacklist' instead of ->blocklist as we don't have commit
 0b98acd61883 ("libceph, rbd, ceph: "blacklist" -> "blocklist"")]
Acked-by: Luis Henriques <lhenriques@suse.com>
---
 fs/ceph/super.c |   17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -997,16 +997,16 @@ static int ceph_compare_super(struct sup
 	struct ceph_fs_client *new = fc->s_fs_info;
 	struct ceph_mount_options *fsopt = new->mount_options;
 	struct ceph_options *opt = new->client->options;
-	struct ceph_fs_client *other = ceph_sb_to_client(sb);
+	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
 
 	dout("ceph_compare_super %p\n", sb);
 
-	if (compare_mount_options(fsopt, opt, other)) {
+	if (compare_mount_options(fsopt, opt, fsc)) {
 		dout("monitor(s)/mount options don't match\n");
 		return 0;
 	}
 	if ((opt->flags & CEPH_OPT_FSID) &&
-	    ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
+	    ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) {
 		dout("fsid doesn't match\n");
 		return 0;
 	}
@@ -1014,6 +1014,17 @@ static int ceph_compare_super(struct sup
 		dout("flags differ\n");
 		return 0;
 	}
+
+	if (fsc->blacklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) {
+		dout("client is blocklisted (and CLEANRECOVER is not set)\n");
+		return 0;
+	}
+
+	if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
+		dout("client has been forcibly unmounted\n");
+		return 0;
+	}
+
 	return 1;
 }