ceph: do not release the global snaprealm until unmounting
authorXiubo Li <xiubli@redhat.com>
Wed, 23 Feb 2022 01:04:56 +0000 (09:04 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 1 Mar 2022 17:26:37 +0000 (18:26 +0100)
The global snaprealm would be created and then destroyed immediately
every time when updating it.

URL: https://tracker.ceph.com/issues/54362
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h
include/linux/ceph/ceph_fs.h

index ef91454..fa38c01 100644 (file)
@@ -4838,7 +4838,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        mutex_unlock(&mdsc->mutex);
 
        ceph_cleanup_snapid_map(mdsc);
-       ceph_cleanup_empty_realms(mdsc);
+       ceph_cleanup_global_and_empty_realms(mdsc);
 
        cancel_work_sync(&mdsc->cap_reclaim_work);
        cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
index 66a1a92..cc9097c 100644 (file)
@@ -121,7 +121,11 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
        if (!realm)
                return ERR_PTR(-ENOMEM);
 
-       atomic_set(&realm->nref, 1);    /* for caller */
+       /* Do not release the global dummy snaprealm until unmouting */
+       if (ino == CEPH_INO_GLOBAL_SNAPREALM)
+               atomic_set(&realm->nref, 2);
+       else
+               atomic_set(&realm->nref, 1);
        realm->ino = ino;
        INIT_LIST_HEAD(&realm->children);
        INIT_LIST_HEAD(&realm->child_item);
@@ -261,9 +265,14 @@ static void __cleanup_empty_realms(struct ceph_mds_client *mdsc)
        spin_unlock(&mdsc->snap_empty_lock);
 }
 
-void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc)
+void ceph_cleanup_global_and_empty_realms(struct ceph_mds_client *mdsc)
 {
+       struct ceph_snap_realm *global_realm;
+
        down_write(&mdsc->snap_rwsem);
+       global_realm = __lookup_snap_realm(mdsc, CEPH_INO_GLOBAL_SNAPREALM);
+       if (global_realm)
+               ceph_put_snap_realm(mdsc, global_realm);
        __cleanup_empty_realms(mdsc);
        up_write(&mdsc->snap_rwsem);
 }
index ef9f32e..0b4b519 100644 (file)
@@ -940,7 +940,7 @@ extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
                             struct ceph_msg *msg);
 extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
                                  struct ceph_cap_snap *capsnap);
-extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc);
+extern void ceph_cleanup_global_and_empty_realms(struct ceph_mds_client *mdsc);
 
 extern struct ceph_snapid_map *ceph_get_snapid_map(struct ceph_mds_client *mdsc,
                                                   u64 snap);
index f14f9bc..86bf82d 100644 (file)
@@ -28,7 +28,8 @@
 
 
 #define CEPH_INO_ROOT   1
-#define CEPH_INO_CEPH   2       /* hidden .ceph dir */
+#define CEPH_INO_CEPH   2            /* hidden .ceph dir */
+#define CEPH_INO_GLOBAL_SNAPREALM  3 /* global dummy snaprealm */
 
 /* arbitrary limit on max # of monitors (cluster of 3 is typical) */
 #define CEPH_MAX_MON   31