ceph: refactor remove_session_caps_cb
authorJeff Layton <jlayton@kernel.org>
Thu, 2 Sep 2021 17:06:57 +0000 (13:06 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Nov 2021 02:29:51 +0000 (03:29 +0100)
Move remove_capsnaps to caps.c. Move the part of remove_session_caps_cb
under i_ceph_lock into a separate function that lives in caps.c. Have
remove_session_caps_cb call the new helper after taking the lock.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/super.h

index ccfba5a..e8e663e 100644 (file)
@@ -4561,3 +4561,119 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
        spin_unlock(&dentry->d_lock);
        return ret;
 }
+
+static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap_snap *capsnap;
+       int capsnap_release = 0;
+
+       lockdep_assert_held(&ci->i_ceph_lock);
+
+       dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
+
+       while (!list_empty(&ci->i_cap_snaps)) {
+               capsnap = list_first_entry(&ci->i_cap_snaps,
+                                          struct ceph_cap_snap, ci_item);
+               __ceph_remove_capsnap(inode, capsnap, NULL, NULL);
+               ceph_put_snap_context(capsnap->context);
+               ceph_put_cap_snap(capsnap);
+               capsnap_release++;
+       }
+       wake_up_all(&ci->i_cap_wq);
+       wake_up_all(&mdsc->cap_flushing_wq);
+       return capsnap_release;
+}
+
+int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate)
+{
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+       struct ceph_mds_client *mdsc = fsc->mdsc;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       bool is_auth;
+       bool dirty_dropped = false;
+       int iputs = 0;
+
+       lockdep_assert_held(&ci->i_ceph_lock);
+
+       dout("removing cap %p, ci is %p, inode is %p\n",
+            cap, ci, &ci->vfs_inode);
+
+       is_auth = (cap == ci->i_auth_cap);
+       __ceph_remove_cap(cap, false);
+       if (is_auth) {
+               struct ceph_cap_flush *cf;
+
+               if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
+                       if (inode->i_data.nrpages > 0)
+                               *invalidate = true;
+                       if (ci->i_wrbuffer_ref > 0)
+                               mapping_set_error(&inode->i_data, -EIO);
+               }
+
+               spin_lock(&mdsc->cap_dirty_lock);
+
+               /* trash all of the cap flushes for this inode */
+               while (!list_empty(&ci->i_cap_flush_list)) {
+                       cf = list_first_entry(&ci->i_cap_flush_list,
+                                             struct ceph_cap_flush, i_list);
+                       list_del_init(&cf->g_list);
+                       list_del_init(&cf->i_list);
+                       if (!cf->is_capsnap)
+                               ceph_free_cap_flush(cf);
+               }
+
+               if (!list_empty(&ci->i_dirty_item)) {
+                       pr_warn_ratelimited(
+                               " dropping dirty %s state for %p %lld\n",
+                               ceph_cap_string(ci->i_dirty_caps),
+                               inode, ceph_ino(inode));
+                       ci->i_dirty_caps = 0;
+                       list_del_init(&ci->i_dirty_item);
+                       dirty_dropped = true;
+               }
+               if (!list_empty(&ci->i_flushing_item)) {
+                       pr_warn_ratelimited(
+                               " dropping dirty+flushing %s state for %p %lld\n",
+                               ceph_cap_string(ci->i_flushing_caps),
+                               inode, ceph_ino(inode));
+                       ci->i_flushing_caps = 0;
+                       list_del_init(&ci->i_flushing_item);
+                       mdsc->num_cap_flushing--;
+                       dirty_dropped = true;
+               }
+               spin_unlock(&mdsc->cap_dirty_lock);
+
+               if (dirty_dropped) {
+                       mapping_set_error(inode->i_mapping, -EIO);
+
+                       if (ci->i_wrbuffer_ref_head == 0 &&
+                           ci->i_wr_ref == 0 &&
+                           ci->i_dirty_caps == 0 &&
+                           ci->i_flushing_caps == 0) {
+                               ceph_put_snap_context(ci->i_head_snapc);
+                               ci->i_head_snapc = NULL;
+                       }
+               }
+
+               if (atomic_read(&ci->i_filelock_ref) > 0) {
+                       /* make further file lock syscall return -EIO */
+                       ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
+                       pr_warn_ratelimited(" dropping file locks for %p %lld\n",
+                                           inode, ceph_ino(inode));
+               }
+
+               if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
+                       cf = ci->i_prealloc_cap_flush;
+                       ci->i_prealloc_cap_flush = NULL;
+                       if (!cf->is_capsnap)
+                               ceph_free_cap_flush(cf);
+               }
+
+               if (!list_empty(&ci->i_cap_snaps))
+                       iputs = remove_capsnaps(mdsc, inode);
+       }
+       if (dirty_dropped)
+               ++iputs;
+       return iputs;
+}
index 3239e6c..52d1b53 100644 (file)
@@ -1590,125 +1590,23 @@ out:
        return ret;
 }
 
-static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
-{
-       struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_cap_snap *capsnap;
-       int capsnap_release = 0;
-
-       lockdep_assert_held(&ci->i_ceph_lock);
-
-       dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
-
-       while (!list_empty(&ci->i_cap_snaps)) {
-               capsnap = list_first_entry(&ci->i_cap_snaps,
-                                          struct ceph_cap_snap, ci_item);
-               __ceph_remove_capsnap(inode, capsnap, NULL, NULL);
-               ceph_put_snap_context(capsnap->context);
-               ceph_put_cap_snap(capsnap);
-               capsnap_release++;
-       }
-       wake_up_all(&ci->i_cap_wq);
-       wake_up_all(&mdsc->cap_flushing_wq);
-       return capsnap_release;
-}
-
 static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                                  void *arg)
 {
-       struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
-       struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       bool is_auth;
-       bool dirty_dropped = false;
        bool invalidate = false;
-       int capsnap_release = 0;
+       int iputs;
 
        dout("removing cap %p, ci is %p, inode is %p\n",
             cap, ci, &ci->vfs_inode);
        spin_lock(&ci->i_ceph_lock);
-       is_auth = (cap == ci->i_auth_cap);
-       __ceph_remove_cap(cap, false);
-       if (is_auth) {
-               struct ceph_cap_flush *cf;
-
-               if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {
-                       if (inode->i_data.nrpages > 0)
-                               invalidate = true;
-                       if (ci->i_wrbuffer_ref > 0)
-                               mapping_set_error(&inode->i_data, -EIO);
-               }
-
-               spin_lock(&mdsc->cap_dirty_lock);
-
-               /* trash all of the cap flushes for this inode */
-               while (!list_empty(&ci->i_cap_flush_list)) {
-                       cf = list_first_entry(&ci->i_cap_flush_list,
-                                             struct ceph_cap_flush, i_list);
-                       list_del_init(&cf->g_list);
-                       list_del_init(&cf->i_list);
-                       if (!cf->is_capsnap)
-                               ceph_free_cap_flush(cf);
-               }
-
-               if (!list_empty(&ci->i_dirty_item)) {
-                       pr_warn_ratelimited(
-                               " dropping dirty %s state for %p %lld\n",
-                               ceph_cap_string(ci->i_dirty_caps),
-                               inode, ceph_ino(inode));
-                       ci->i_dirty_caps = 0;
-                       list_del_init(&ci->i_dirty_item);
-                       dirty_dropped = true;
-               }
-               if (!list_empty(&ci->i_flushing_item)) {
-                       pr_warn_ratelimited(
-                               " dropping dirty+flushing %s state for %p %lld\n",
-                               ceph_cap_string(ci->i_flushing_caps),
-                               inode, ceph_ino(inode));
-                       ci->i_flushing_caps = 0;
-                       list_del_init(&ci->i_flushing_item);
-                       mdsc->num_cap_flushing--;
-                       dirty_dropped = true;
-               }
-               spin_unlock(&mdsc->cap_dirty_lock);
-
-               if (dirty_dropped) {
-                       mapping_set_error(inode->i_mapping, -EIO);
-
-                       if (ci->i_wrbuffer_ref_head == 0 &&
-                           ci->i_wr_ref == 0 &&
-                           ci->i_dirty_caps == 0 &&
-                           ci->i_flushing_caps == 0) {
-                               ceph_put_snap_context(ci->i_head_snapc);
-                               ci->i_head_snapc = NULL;
-                       }
-               }
-
-               if (atomic_read(&ci->i_filelock_ref) > 0) {
-                       /* make further file lock syscall return -EIO */
-                       ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
-                       pr_warn_ratelimited(" dropping file locks for %p %lld\n",
-                                           inode, ceph_ino(inode));
-               }
-
-               if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
-                       cf = ci->i_prealloc_cap_flush;
-                       ci->i_prealloc_cap_flush = NULL;
-                       if (!cf->is_capsnap)
-                               ceph_free_cap_flush(cf);
-               }
-
-               if (!list_empty(&ci->i_cap_snaps))
-                       capsnap_release = remove_capsnaps(mdsc, inode);
-       }
+       iputs = ceph_purge_inode_cap(inode, cap, &invalidate);
        spin_unlock(&ci->i_ceph_lock);
 
        wake_up_all(&ci->i_cap_wq);
        if (invalidate)
                ceph_queue_invalidate(inode);
-       if (dirty_dropped)
-               iput(inode);
-       while (capsnap_release--)
+       while (iputs--)
                iput(inode);
        return 0;
 }
index 6a82fb4..daf7e7e 100644 (file)
@@ -1199,6 +1199,7 @@ extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
 extern int ceph_uninline_data(struct file *filp, struct page *locked_page);
 extern int ceph_pool_perm_check(struct inode *inode, int need);
 extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
+int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate);
 
 /* file.c */
 extern const struct file_operations ceph_file_fops;