Commit 1c424629 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ceph-for-6.11-rc2' of https://github.com/ceph/ceph-client

Pull ceph fix from Ilya Dryomov:
 "A fix for a potential hang in the MDS when cap revocation races with
  the client releasing the caps in question, marked for stable"

* tag 'ceph-for-6.11-rc2' of https://github.com/ceph/ceph-client:
  ceph: force sending a cap update msg back to MDS for revoke op
parents 725d410f 31634d75
...@@ -2016,6 +2016,8 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci) ...@@ -2016,6 +2016,8 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci)
* CHECK_CAPS_AUTHONLY - we should only check the auth cap * CHECK_CAPS_AUTHONLY - we should only check the auth cap
* CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without * CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without
* further delay. * further delay.
* CHECK_CAPS_FLUSH_FORCE - we should flush any caps immediately, without
* further delay.
*/ */
void ceph_check_caps(struct ceph_inode_info *ci, int flags) void ceph_check_caps(struct ceph_inode_info *ci, int flags)
{ {
...@@ -2097,7 +2099,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) ...@@ -2097,7 +2099,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
} }
doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s " doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s "
"flushing %s issued %s revoking %s retain %s %s%s%s\n", "flushing %s issued %s revoking %s retain %s %s%s%s%s\n",
inode, ceph_vinop(inode), ceph_cap_string(file_wanted), inode, ceph_vinop(inode), ceph_cap_string(file_wanted),
ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps), ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
ceph_cap_string(ci->i_flushing_caps), ceph_cap_string(ci->i_flushing_caps),
...@@ -2105,7 +2107,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) ...@@ -2105,7 +2107,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
ceph_cap_string(retain), ceph_cap_string(retain),
(flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "", (flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "",
(flags & CHECK_CAPS_FLUSH) ? " FLUSH" : "", (flags & CHECK_CAPS_FLUSH) ? " FLUSH" : "",
(flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : ""); (flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "",
(flags & CHECK_CAPS_FLUSH_FORCE) ? " FLUSH_FORCE" : "");
/* /*
* If we no longer need to hold onto old our caps, and we may * If we no longer need to hold onto old our caps, and we may
...@@ -2180,6 +2183,11 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags) ...@@ -2180,6 +2183,11 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
queue_writeback = true; queue_writeback = true;
} }
if (flags & CHECK_CAPS_FLUSH_FORCE) {
doutc(cl, "force to flush caps\n");
goto ack;
}
if (cap == ci->i_auth_cap && if (cap == ci->i_auth_cap &&
(cap->issued & CEPH_CAP_FILE_WR)) { (cap->issued & CEPH_CAP_FILE_WR)) {
/* request larger max_size from MDS? */ /* request larger max_size from MDS? */
...@@ -3510,6 +3518,8 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3510,6 +3518,8 @@ static void handle_cap_grant(struct inode *inode,
bool queue_invalidate = false; bool queue_invalidate = false;
bool deleted_inode = false; bool deleted_inode = false;
bool fill_inline = false; bool fill_inline = false;
bool revoke_wait = false;
int flags = 0;
/* /*
* If there is at least one crypto block then we'll trust * If there is at least one crypto block then we'll trust
...@@ -3705,16 +3715,18 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3705,16 +3715,18 @@ static void handle_cap_grant(struct inode *inode,
ceph_cap_string(cap->issued), ceph_cap_string(newcaps), ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
ceph_cap_string(revoking)); ceph_cap_string(revoking));
if (S_ISREG(inode->i_mode) && if (S_ISREG(inode->i_mode) &&
(revoking & used & CEPH_CAP_FILE_BUFFER)) (revoking & used & CEPH_CAP_FILE_BUFFER)) {
writeback = true; /* initiate writeback; will delay ack */ writeback = true; /* initiate writeback; will delay ack */
else if (queue_invalidate && revoke_wait = true;
} else if (queue_invalidate &&
revoking == CEPH_CAP_FILE_CACHE && revoking == CEPH_CAP_FILE_CACHE &&
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0) (newcaps & CEPH_CAP_FILE_LAZYIO) == 0) {
; /* do nothing yet, invalidation will be queued */ revoke_wait = true; /* do nothing yet, invalidation will be queued */
else if (cap == ci->i_auth_cap) } else if (cap == ci->i_auth_cap) {
check_caps = 1; /* check auth cap only */ check_caps = 1; /* check auth cap only */
else } else {
check_caps = 2; /* check all caps */ check_caps = 2; /* check all caps */
}
/* If there is new caps, try to wake up the waiters */ /* If there is new caps, try to wake up the waiters */
if (~cap->issued & newcaps) if (~cap->issued & newcaps)
wake = true; wake = true;
...@@ -3741,8 +3753,9 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3741,8 +3753,9 @@ static void handle_cap_grant(struct inode *inode,
BUG_ON(cap->issued & ~cap->implemented); BUG_ON(cap->issued & ~cap->implemented);
/* don't let check_caps skip sending a response to MDS for revoke msgs */ /* don't let check_caps skip sending a response to MDS for revoke msgs */
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) { if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
cap->mds_wanted = 0; cap->mds_wanted = 0;
flags |= CHECK_CAPS_FLUSH_FORCE;
if (cap == ci->i_auth_cap) if (cap == ci->i_auth_cap)
check_caps = 1; /* check auth cap only */ check_caps = 1; /* check auth cap only */
else else
...@@ -3798,9 +3811,9 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3798,9 +3811,9 @@ static void handle_cap_grant(struct inode *inode,
mutex_unlock(&session->s_mutex); mutex_unlock(&session->s_mutex);
if (check_caps == 1) if (check_caps == 1)
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL); ceph_check_caps(ci, flags | CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
else if (check_caps == 2) else if (check_caps == 2)
ceph_check_caps(ci, CHECK_CAPS_NOINVAL); ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL);
} }
/* /*
......
...@@ -203,6 +203,7 @@ struct ceph_cap { ...@@ -203,6 +203,7 @@ struct ceph_cap {
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */ #define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */ #define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */
#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */ #define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */
#define CHECK_CAPS_FLUSH_FORCE 8 /* force flush any caps */
struct ceph_cap_flush { struct ceph_cap_flush {
u64 tid; u64 tid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment