ceph: try to check caps immediately after async creating finishes
authorXiubo Li <xiubli@redhat.com>
Mon, 17 Oct 2022 14:17:35 +0000 (22:17 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 12 Dec 2022 18:15:39 +0000 (19:15 +0100)
We should call the check_caps() again immediately after the async
creating finishes in case the MDS is waiting for caps revocation
to finish.

Link: https://tracker.ceph.com/issues/46904
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/super.h

index 1323fa2..4b159f9 100644 (file)
@@ -1916,6 +1916,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
 
        spin_lock(&ci->i_ceph_lock);
        if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) {
+               ci->i_ceph_flags |= CEPH_I_ASYNC_CHECK_CAPS;
+
                /* Don't send messages until we get async create reply */
                spin_unlock(&ci->i_ceph_lock);
                return;
index 4e68220..a6681b1 100644 (file)
@@ -534,14 +534,23 @@ static void wake_async_create_waiters(struct inode *inode,
                                      struct ceph_mds_session *session)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
+       bool check_cap = false;
 
        spin_lock(&ci->i_ceph_lock);
        if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) {
                ci->i_ceph_flags &= ~CEPH_I_ASYNC_CREATE;
                wake_up_bit(&ci->i_ceph_flags, CEPH_ASYNC_CREATE_BIT);
+
+               if (ci->i_ceph_flags & CEPH_I_ASYNC_CHECK_CAPS) {
+                       ci->i_ceph_flags &= ~CEPH_I_ASYNC_CHECK_CAPS;
+                       check_cap = true;
+               }
        }
        ceph_kick_flushing_inode_caps(session, ci);
        spin_unlock(&ci->i_ceph_lock);
+
+       if (check_cap)
+               ceph_check_caps(ci, CHECK_CAPS_FLUSH);
 }
 
 static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
index e8bc1d0..e1bd6f4 100644 (file)
@@ -593,6 +593,8 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
 #define CEPH_ASYNC_CREATE_BIT  (12)      /* async create in flight for this */
 #define CEPH_I_ASYNC_CREATE    (1 << CEPH_ASYNC_CREATE_BIT)
 #define CEPH_I_SHUTDOWN                (1 << 13) /* inode is no longer usable */
+#define CEPH_I_ASYNC_CHECK_CAPS        (1 << 14) /* check caps immediately after async
+                                            creating finishes */
 
 /*
  * Masks of ceph inode work.