Merge tag 'for-linus-6.9-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubca...
[linux-2.6-block.git] / fs / ceph / caps.c
index ad1f46c66fbffbee52ba280ad79e03279e56e1e5..7fb4aae97412464c54b42037f75016085d214bd3 100644 (file)
@@ -2156,6 +2156,30 @@ retry:
                      ceph_cap_string(cap->implemented),
                      ceph_cap_string(revoking));
 
+               /* completed revocation? going down and there are no caps? */
+               if (revoking) {
+                       if ((revoking & cap_used) == 0) {
+                               doutc(cl, "completed revocation of %s\n",
+                                     ceph_cap_string(cap->implemented & ~cap->issued));
+                               goto ack;
+                       }
+
+                       /*
+                        * If the "i_wrbuffer_ref" was increased by mmap or generic
+                        * cache write just before the ceph_check_caps() is called,
+                        * the Fb capability revoking will fail this time. Then we
+                        * must wait for the BDI's delayed work to flush the dirty
+                        * pages and to release the "i_wrbuffer_ref", which will cost
+                        * at most 5 seconds. That means the MDS needs to wait at
+                        * most 5 seconds to finished the Fb capability's revocation.
+                        *
+                        * Let's queue a writeback for it.
+                        */
+                       if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
+                           (revoking & CEPH_CAP_FILE_BUFFER))
+                               queue_writeback = true;
+               }
+
                if (cap == ci->i_auth_cap &&
                    (cap->issued & CEPH_CAP_FILE_WR)) {
                        /* request larger max_size from MDS? */
@@ -2183,30 +2207,6 @@ retry:
                        }
                }
 
-               /* completed revocation? going down and there are no caps? */
-               if (revoking) {
-                       if ((revoking & cap_used) == 0) {
-                               doutc(cl, "completed revocation of %s\n",
-                                     ceph_cap_string(cap->implemented & ~cap->issued));
-                               goto ack;
-                       }
-
-                       /*
-                        * If the "i_wrbuffer_ref" was increased by mmap or generic
-                        * cache write just before the ceph_check_caps() is called,
-                        * the Fb capability revoking will fail this time. Then we
-                        * must wait for the BDI's delayed work to flush the dirty
-                        * pages and to release the "i_wrbuffer_ref", which will cost
-                        * at most 5 seconds. That means the MDS needs to wait at
-                        * most 5 seconds to finished the Fb capability's revocation.
-                        *
-                        * Let's queue a writeback for it.
-                        */
-                       if (S_ISREG(inode->i_mode) && ci->i_wrbuffer_ref &&
-                           (revoking & CEPH_CAP_FILE_BUFFER))
-                               queue_writeback = true;
-               }
-
                /* want more caps from mds? */
                if (want & ~cap->mds_wanted) {
                        if (want & ~(cap->mds_wanted | cap->issued))
@@ -4772,7 +4772,22 @@ int ceph_drop_caps_for_unlink(struct inode *inode)
                if (__ceph_caps_dirty(ci)) {
                        struct ceph_mds_client *mdsc =
                                ceph_inode_to_fs_client(inode)->mdsc;
-                       __cap_delay_requeue_front(mdsc, ci);
+
+                       doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode,
+                             ceph_vinop(inode));
+                       spin_lock(&mdsc->cap_unlink_delay_lock);
+                       ci->i_ceph_flags |= CEPH_I_FLUSH;
+                       if (!list_empty(&ci->i_cap_delay_list))
+                               list_del_init(&ci->i_cap_delay_list);
+                       list_add_tail(&ci->i_cap_delay_list,
+                                     &mdsc->cap_unlink_delay_list);
+                       spin_unlock(&mdsc->cap_unlink_delay_lock);
+
+                       /*
+                        * Fire the work immediately, because the MDS maybe
+                        * waiting for caps release.
+                        */
+                       ceph_queue_cap_unlink_work(mdsc);
                }
        }
        spin_unlock(&ci->i_ceph_lock);