提交 6f05b30e 编写于 作者: Y Yan, Zheng 提交者: Ilya Dryomov

ceph: reset i_requested_max_size if file write is not wanted

write can stuck at waiting for larger max_size in following sequence of
events:

- client opens a file and writes to position 'A' (larger than unit of
  max size increment)
- client closes the file handle and updates wanted caps (not wanting
  file write caps)
- client opens and truncates the file, writes to position 'A' again.

At the 1st event, client set inode's requested_max_size to 'A'. At the
2nd event, mds removes client's writable range, but client does not reset
requested_max_size. At the 3rd event, client does not request max size
because requested_max_size is already larger than 'A'.
Signed-off-by: N"Yan, Zheng" <zyan@redhat.com>
Reviewed-by: NJeff Layton <jlayton@kernel.org>
Signed-off-by: NIlya Dryomov <idryomov@gmail.com>
上级 88828190
...@@ -1369,8 +1369,12 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap, ...@@ -1369,8 +1369,12 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
arg->size = inode->i_size; arg->size = inode->i_size;
ci->i_reported_size = arg->size; ci->i_reported_size = arg->size;
arg->max_size = ci->i_wanted_max_size; arg->max_size = ci->i_wanted_max_size;
if (cap == ci->i_auth_cap) if (cap == ci->i_auth_cap) {
ci->i_requested_max_size = arg->max_size; if (want & CEPH_CAP_ANY_FILE_WR)
ci->i_requested_max_size = arg->max_size;
else
ci->i_requested_max_size = 0;
}
if (flushing & CEPH_CAP_XATTR_EXCL) { if (flushing & CEPH_CAP_XATTR_EXCL) {
arg->old_xattr_buf = __ceph_build_xattrs_blob(ci); arg->old_xattr_buf = __ceph_build_xattrs_blob(ci);
...@@ -3342,10 +3346,6 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3342,10 +3346,6 @@ static void handle_cap_grant(struct inode *inode,
ci->i_requested_max_size = 0; ci->i_requested_max_size = 0;
} }
wake = true; wake = true;
} else if (ci->i_wanted_max_size > ci->i_max_size &&
ci->i_wanted_max_size > ci->i_requested_max_size) {
/* CEPH_CAP_OP_IMPORT */
wake = true;
} }
} }
...@@ -3421,9 +3421,18 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3421,9 +3421,18 @@ static void handle_cap_grant(struct inode *inode,
fill_inline = true; fill_inline = true;
} }
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { if (ci->i_auth_cap == cap &&
le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
if (newcaps & ~extra_info->issued) if (newcaps & ~extra_info->issued)
wake = true; wake = true;
if (ci->i_requested_max_size > max_size ||
!(le32_to_cpu(grant->wanted) & CEPH_CAP_ANY_FILE_WR)) {
/* re-request max_size if necessary */
ci->i_requested_max_size = 0;
wake = true;
}
ceph_kick_flushing_inode_caps(session, ci); ceph_kick_flushing_inode_caps(session, ci);
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
up_read(&session->s_mdsc->snap_rwsem); up_read(&session->s_mdsc->snap_rwsem);
...@@ -3882,9 +3891,6 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, ...@@ -3882,9 +3891,6 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
__ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE)); __ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
} }
/* make sure we re-request max_size, if necessary */
ci->i_requested_max_size = 0;
*old_issued = issued; *old_issued = issued;
*target_cap = cap; *target_cap = cap;
} }
...@@ -4318,6 +4324,9 @@ int ceph_encode_inode_release(void **p, struct inode *inode, ...@@ -4318,6 +4324,9 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
cap->issued &= ~drop; cap->issued &= ~drop;
cap->implemented &= ~drop; cap->implemented &= ~drop;
cap->mds_wanted = wanted; cap->mds_wanted = wanted;
if (cap == ci->i_auth_cap &&
!(wanted & CEPH_CAP_ANY_FILE_WR))
ci->i_requested_max_size = 0;
} else { } else {
dout("encode_inode_release %p cap %p %s" dout("encode_inode_release %p cap %p %s"
" (force)\n", inode, cap, " (force)\n", inode, cap,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册