]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
ceph: defer flushing the capsnap if the Fb is used
authorXiubo Li <xiubli@redhat.com>
Tue, 2 Feb 2021 06:54:53 +0000 (14:54 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 16 Feb 2021 11:09:52 +0000 (12:09 +0100)
If the Fb cap is used it means the current inode is flushing the
dirty data to OSD, just defer flushing the capsnap.

URL: https://tracker.ceph.com/issues/48640
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/snap.c

index abbf48fc62303bc323c5d0ec49ab31a5305639af..570731c4d019d406b9ce90fafe00cb54f02c55c2 100644 (file)
@@ -3047,6 +3047,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
 {
        struct inode *inode = &ci->vfs_inode;
        int last = 0, put = 0, flushsnaps = 0, wake = 0;
+       bool check_flushsnaps = false;
 
        spin_lock(&ci->i_ceph_lock);
        if (had & CEPH_CAP_PIN)
@@ -3063,26 +3064,17 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
        if (had & CEPH_CAP_FILE_BUFFER) {
                if (--ci->i_wb_ref == 0) {
                        last++;
+                       /* put the ref held by ceph_take_cap_refs() */
                        put++;
+                       check_flushsnaps = true;
                }
                dout("put_cap_refs %p wb %d -> %d (?)\n",
                     inode, ci->i_wb_ref+1, ci->i_wb_ref);
        }
-       if (had & CEPH_CAP_FILE_WR)
+       if (had & CEPH_CAP_FILE_WR) {
                if (--ci->i_wr_ref == 0) {
                        last++;
-                       if (__ceph_have_pending_cap_snap(ci)) {
-                               struct ceph_cap_snap *capsnap =
-                                       list_last_entry(&ci->i_cap_snaps,
-                                                       struct ceph_cap_snap,
-                                                       ci_item);
-                               capsnap->writing = 0;
-                               if (ceph_try_drop_cap_snap(ci, capsnap))
-                                       put++;
-                               else if (__ceph_finish_cap_snap(ci, capsnap))
-                                       flushsnaps = 1;
-                               wake = 1;
-                       }
+                       check_flushsnaps = true;
                        if (ci->i_wrbuffer_ref_head == 0 &&
                            ci->i_dirty_caps == 0 &&
                            ci->i_flushing_caps == 0) {
@@ -3094,6 +3086,21 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
                        if (!__ceph_is_any_real_caps(ci) && ci->i_snap_realm)
                                drop_inode_snap_realm(ci);
                }
+       }
+       if (check_flushsnaps && __ceph_have_pending_cap_snap(ci)) {
+               struct ceph_cap_snap *capsnap =
+                       list_last_entry(&ci->i_cap_snaps,
+                                       struct ceph_cap_snap,
+                                       ci_item);
+
+               capsnap->writing = 0;
+               if (ceph_try_drop_cap_snap(ci, capsnap))
+                       /* put the ref held by ceph_queue_cap_snap() */
+                       put++;
+               else if (__ceph_finish_cap_snap(ci, capsnap))
+                       flushsnaps = 1;
+               wake = 1;
+       }
        spin_unlock(&ci->i_ceph_lock);
 
        dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had),
index b611f829cb611590f2baaf36ec799a2fabb0ad66..0728b01d4d431f0d4f6860975146b59d46727cbb 100644 (file)
@@ -623,6 +623,16 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
                return 0;
        }
 
+       /* Fb cap still in use, delay it */
+       if (ci->i_wb_ref) {
+               dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu "
+                    "used WRBUFFER, delaying\n", inode, capsnap,
+                    capsnap->context, capsnap->context->seq,
+                    ceph_cap_string(capsnap->dirty), capsnap->size);
+               capsnap->writing = 1;
+               return 0;
+       }
+
        ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
        dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu\n",
             inode, capsnap, capsnap->context,