ceph: fix auth cap handling logic in remove_session_caps_cb
authorJeff Layton <jlayton@kernel.org>
Thu, 2 Sep 2021 16:47:01 +0000 (12:47 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Nov 2021 02:29:51 +0000 (03:29 +0100)
The existing logic relies on ci->i_auth_cap being NULL, but if we end up
removing the auth cap early, then we'll do a lot of useless work and
lock-taking on the remaining caps. Ensure that we only do the auth cap
removal when we're _actually_ removing the auth cap.

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

index 9967824ad9c32efb26f8b870e15d0143c27b8c7a..3239e6c9047f7899aa8805753c78ceefa199a6dc 100644 (file)
@@ -1619,6 +1619,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
        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;
@@ -1626,8 +1627,9 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
        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 (!ci->i_auth_cap) {
+       if (is_auth) {
                struct ceph_cap_flush *cf;
 
                if (READ_ONCE(fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) {