ceph: add ceph_change_snap_realm() helper
authorJeff Layton <jlayton@kernel.org>
Mon, 2 Aug 2021 15:01:26 +0000 (11:01 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 2 Sep 2021 20:49:17 +0000 (22:49 +0200)
Consolidate some fiddly code for changing an inode's snap_realm
into a new helper function, and change the callers to use it.

While we're in here, nothing uses the i_snap_realm_counter field, so
remove that from the inode.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Luis Henriques <lhenriques@suse.de>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/snap.c
fs/ceph/super.h

index d5a4655..b75a9e1 100644 (file)
@@ -704,23 +704,7 @@ void ceph_add_cap(struct inode *inode,
                struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc,
                                                               realmino);
                if (realm) {
-                       struct ceph_snap_realm *oldrealm = ci->i_snap_realm;
-                       if (oldrealm) {
-                               spin_lock(&oldrealm->inodes_with_caps_lock);
-                               list_del_init(&ci->i_snap_realm_item);
-                               spin_unlock(&oldrealm->inodes_with_caps_lock);
-                       }
-
-                       spin_lock(&realm->inodes_with_caps_lock);
-                       list_add(&ci->i_snap_realm_item,
-                                &realm->inodes_with_caps);
-                       ci->i_snap_realm = realm;
-                       if (realm->ino == ci->i_vino.ino)
-                               realm->inode = inode;
-                       spin_unlock(&realm->inodes_with_caps_lock);
-
-                       if (oldrealm)
-                               ceph_put_snap_realm(mdsc, oldrealm);
+                       ceph_change_snap_realm(inode, realm);
                } else {
                        pr_err("ceph_add_cap: couldn't find snap realm %llx\n",
                               realmino);
@@ -1112,20 +1096,6 @@ int ceph_is_any_caps(struct inode *inode)
        return ret;
 }
 
-static void drop_inode_snap_realm(struct ceph_inode_info *ci)
-{
-       struct ceph_snap_realm *realm = ci->i_snap_realm;
-       spin_lock(&realm->inodes_with_caps_lock);
-       list_del_init(&ci->i_snap_realm_item);
-       ci->i_snap_realm_counter++;
-       ci->i_snap_realm = NULL;
-       if (realm->ino == ci->i_vino.ino)
-               realm->inode = NULL;
-       spin_unlock(&realm->inodes_with_caps_lock);
-       ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
-                           realm);
-}
-
 /*
  * Remove a cap.  Take steps to deal with a racing iterate_session_caps.
  *
@@ -1201,7 +1171,7 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
                 * keep i_snap_realm.
                 */
                if (ci->i_wr_ref == 0 && ci->i_snap_realm)
-                       drop_inode_snap_realm(ci);
+                       ceph_change_snap_realm(&ci->vfs_inode, NULL);
 
                __cap_delay_cancel(mdsc, ci);
        }
@@ -3084,7 +3054,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
                        }
                        /* see comment in __ceph_remove_cap() */
                        if (!__ceph_is_any_real_caps(ci) && ci->i_snap_realm)
-                               drop_inode_snap_realm(ci);
+                               ceph_change_snap_realm(inode, NULL);
                }
        }
        if (check_flushsnaps && __ceph_have_pending_cap_snap(ci)) {
index 1bd2cc0..2df1e12 100644 (file)
@@ -581,16 +581,9 @@ void ceph_evict_inode(struct inode *inode)
         */
        if (ci->i_snap_realm) {
                if (ceph_snap(inode) == CEPH_NOSNAP) {
-                       struct ceph_snap_realm *realm = ci->i_snap_realm;
                        dout(" dropping residual ref to snap realm %p\n",
-                            realm);
-                       spin_lock(&realm->inodes_with_caps_lock);
-                       list_del_init(&ci->i_snap_realm_item);
-                       ci->i_snap_realm = NULL;
-                       if (realm->ino == ci->i_vino.ino)
-                               realm->inode = NULL;
-                       spin_unlock(&realm->inodes_with_caps_lock);
-                       ceph_put_snap_realm(mdsc, realm);
+                            ci->i_snap_realm);
+                       ceph_change_snap_realm(inode, NULL);
                } else {
                        ceph_put_snapid_map(mdsc, ci->i_snapid_map);
                        ci->i_snap_realm = NULL;
index 15105f9..b41e672 100644 (file)
@@ -849,6 +849,43 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
        dout("flush_snaps done\n");
 }
 
+/**
+ * ceph_change_snap_realm - change the snap_realm for an inode
+ * @inode: inode to move to new snap realm
+ * @realm: new realm to move inode into (may be NULL)
+ *
+ * Detach an inode from its old snaprealm (if any) and attach it to
+ * the new snaprealm (if any). The old snap realm reference held by
+ * the inode is put. If realm is non-NULL, then the caller's reference
+ * to it is taken over by the inode.
+ */
+void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+       struct ceph_snap_realm *oldrealm = ci->i_snap_realm;
+
+       lockdep_assert_held(&ci->i_ceph_lock);
+
+       if (oldrealm) {
+               spin_lock(&oldrealm->inodes_with_caps_lock);
+               list_del_init(&ci->i_snap_realm_item);
+               if (oldrealm->ino == ci->i_vino.ino)
+                       oldrealm->inode = NULL;
+               spin_unlock(&oldrealm->inodes_with_caps_lock);
+               ceph_put_snap_realm(mdsc, oldrealm);
+       }
+
+       ci->i_snap_realm = realm;
+
+       if (realm) {
+               spin_lock(&realm->inodes_with_caps_lock);
+               list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps);
+               if (realm->ino == ci->i_vino.ino)
+                       realm->inode = inode;
+               spin_unlock(&realm->inodes_with_caps_lock);
+       }
+}
 
 /*
  * Handle a snap notification from the MDS.
@@ -935,7 +972,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        };
                        struct inode *inode = ceph_find_inode(sb, vino);
                        struct ceph_inode_info *ci;
-                       struct ceph_snap_realm *oldrealm;
 
                        if (!inode)
                                continue;
@@ -960,27 +996,10 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        }
                        dout(" will move %p to split realm %llx %p\n",
                             inode, realm->ino, realm);
-                       /*
-                        * Move the inode to the new realm
-                        */
-                       oldrealm = ci->i_snap_realm;
-                       spin_lock(&oldrealm->inodes_with_caps_lock);
-                       list_del_init(&ci->i_snap_realm_item);
-                       spin_unlock(&oldrealm->inodes_with_caps_lock);
-
-                       spin_lock(&realm->inodes_with_caps_lock);
-                       list_add(&ci->i_snap_realm_item,
-                                &realm->inodes_with_caps);
-                       ci->i_snap_realm = realm;
-                       if (realm->ino == ci->i_vino.ino)
-                                realm->inode = inode;
-                       spin_unlock(&realm->inodes_with_caps_lock);
-
-                       spin_unlock(&ci->i_ceph_lock);
 
                        ceph_get_snap_realm(mdsc, realm);
-                       ceph_put_snap_realm(mdsc, oldrealm);
-
+                       ceph_change_snap_realm(inode, realm);
+                       spin_unlock(&ci->i_ceph_lock);
                        iput(inode);
                        continue;
 
index b1a3636..3fad464 100644 (file)
@@ -418,7 +418,6 @@ struct ceph_inode_info {
                struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */
                struct ceph_snapid_map *i_snapid_map; /* snapid -> dev_t */
        };
-       int i_snap_realm_counter; /* snap realm (if caps) */
        struct list_head i_snap_realm_item;
        struct list_head i_snap_flush_item;
        struct timespec64 i_btime;
@@ -929,6 +928,7 @@ extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
 extern int ceph_update_snap_trace(struct ceph_mds_client *m,
                                  void *p, void *e, bool deletion,
                                  struct ceph_snap_realm **realm_ret);
+void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm);
 extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
                             struct ceph_mds_session *session,
                             struct ceph_msg *msg);