ceph: don't WARN if we're forcibly removing the session caps
authorXiubo Li <xiubli@redhat.com>
Wed, 25 Aug 2021 13:45:45 +0000 (21:45 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 2 Sep 2021 20:49:17 +0000 (22:49 +0200)
For example in the case of a forced umount, we'll remove all the session
caps even if they are dirty. Move the warning to a wrapper function and
make most of the callers use it. Call the core function when removing
caps due to a forced umount.

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/caps.c
fs/ceph/mds_client.c
fs/ceph/super.h

index 2e5d265..f92eeb7 100644 (file)
@@ -1114,17 +1114,16 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
                return;
        }
 
+       lockdep_assert_held(&ci->i_ceph_lock);
+
        dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
 
        mdsc = ceph_inode_to_client(&ci->vfs_inode)->mdsc;
 
        /* remove from inode's cap rbtree, and clear auth cap */
        rb_erase(&cap->ci_node, &ci->i_caps);
-       if (ci->i_auth_cap == cap) {
-               WARN_ON_ONCE(!list_empty(&ci->i_dirty_item) &&
-                            !mdsc->fsc->blocklisted);
+       if (ci->i_auth_cap == cap)
                ci->i_auth_cap = NULL;
-       }
 
        /* remove from session list */
        spin_lock(&session->s_cap_lock);
@@ -1176,6 +1175,28 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
        }
 }
 
+void ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
+{
+       struct ceph_inode_info *ci = cap->ci;
+       struct ceph_fs_client *fsc;
+
+       /* 'ci' being NULL means the remove have already occurred */
+       if (!ci) {
+               dout("%s: cap inode is NULL\n", __func__);
+               return;
+       }
+
+       lockdep_assert_held(&ci->i_ceph_lock);
+
+       fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
+       WARN_ON_ONCE(ci->i_auth_cap == cap &&
+                    !list_empty(&ci->i_dirty_item) &&
+                    !fsc->blocklisted &&
+                    READ_ONCE(fsc->mount_state) != CEPH_MOUNT_SHUTDOWN);
+
+       __ceph_remove_cap(cap, queue_release);
+}
+
 struct cap_msg_args {
        struct ceph_mds_session *session;
        u64                     ino, cid, follows;
@@ -1304,7 +1325,7 @@ void __ceph_remove_caps(struct ceph_inode_info *ci)
        while (p) {
                struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
                p = rb_next(p);
-               __ceph_remove_cap(cap, true);
+               ceph_remove_cap(cap, true);
        }
        spin_unlock(&ci->i_ceph_lock);
 }
@@ -3822,7 +3843,7 @@ retry:
                goto out_unlock;
 
        if (target < 0) {
-               __ceph_remove_cap(cap, false);
+               ceph_remove_cap(cap, false);
                goto out_unlock;
        }
 
@@ -3857,7 +3878,7 @@ retry:
                                change_auth_cap_ses(ci, tcap->session);
                        }
                }
-               __ceph_remove_cap(cap, false);
+               ceph_remove_cap(cap, false);
                goto out_unlock;
        } else if (tsession) {
                /* add placeholder for the export tagert */
@@ -3874,7 +3895,7 @@ retry:
                        spin_unlock(&mdsc->cap_dirty_lock);
                }
 
-               __ceph_remove_cap(cap, false);
+               ceph_remove_cap(cap, false);
                goto out_unlock;
        }
 
@@ -3985,7 +4006,7 @@ retry:
                                        ocap->mseq, mds, le32_to_cpu(ph->seq),
                                        le32_to_cpu(ph->mseq));
                }
-               __ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
+               ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
        }
 
        *old_issued = issued;
index c3a0e54..94e90db 100644 (file)
@@ -2016,7 +2016,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
 
        if (oissued) {
                /* we aren't the only cap.. just remove us */
-               __ceph_remove_cap(cap, true);
+               ceph_remove_cap(cap, true);
                (*remaining)--;
        } else {
                struct dentry *dentry;
index e1d62e4..16c7eb0 100644 (file)
@@ -1138,6 +1138,7 @@ extern void ceph_add_cap(struct inode *inode,
                         unsigned cap, unsigned seq, u64 realmino, int flags,
                         struct ceph_cap **new_cap);
 extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
+extern void ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
 extern void __ceph_remove_caps(struct ceph_inode_info *ci);
 extern void ceph_put_cap(struct ceph_mds_client *mdsc,
                         struct ceph_cap *cap);