mirror of https://gitee.com/openkylin/linux.git
ceph: defer flushing the capsnap if the Fb is used
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>
This commit is contained in:
parent
d7ef2e59e3
commit
558b4510f6
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue