Merge tag 'io_uring-5.15-2021-09-11' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / fs / ceph / snap.c
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;