mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
A fix for a potential hang in the MDS when cap revocation races with
the client releasing the caps in question, marked for stable. -----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmatDEgTHGlkcnlvbW92 QGdtYWlsLmNvbQAKCRBKf944AhHzixHdB/9k62+n/hLFTXem1WE421sg6oAwCNA+ KCps+TU4ekeo7ckvExeO1MwL5SyRMUc05nY9zHDiqey0hkpuUsZfjvj9v/q0XHDh YcGLfIe9gTl2QiAeEjl6FRkJas5GA/MULjEKltEFUpRTCH9WQvS2z5/MzJByUobf kHtEokAViEB+OpIabN3Vm4ZcQJ5ZLdbmVzlvf3nRYZ1Yw+OinQn3yVQJ2VKYXiOi l9rk9XxUSISV7EKUq9N0qlSH7M1YsspMTM1lSIC1vlaILyeTA1dJa/85ACEtXOfm Z7mC77H6ivR2o+eXilgvpEAyCCDRfmwUp4GV1LnqFDZKBJsBAcwLyLGY =I++X -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1c4246294c
@ -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_FLUSH - we should flush any dirty caps immediately, without
|
||||
* 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)
|
||||
{
|
||||
@ -2097,7 +2099,7 @@ retry:
|
||||
}
|
||||
|
||||
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),
|
||||
ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
|
||||
ceph_cap_string(ci->i_flushing_caps),
|
||||
@ -2105,7 +2107,8 @@ retry:
|
||||
ceph_cap_string(retain),
|
||||
(flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "",
|
||||
(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
|
||||
@ -2180,6 +2183,11 @@ retry:
|
||||
queue_writeback = true;
|
||||
}
|
||||
|
||||
if (flags & CHECK_CAPS_FLUSH_FORCE) {
|
||||
doutc(cl, "force to flush caps\n");
|
||||
goto ack;
|
||||
}
|
||||
|
||||
if (cap == ci->i_auth_cap &&
|
||||
(cap->issued & CEPH_CAP_FILE_WR)) {
|
||||
/* request larger max_size from MDS? */
|
||||
@ -3510,6 +3518,8 @@ static void handle_cap_grant(struct inode *inode,
|
||||
bool queue_invalidate = false;
|
||||
bool deleted_inode = false;
|
||||
bool fill_inline = false;
|
||||
bool revoke_wait = false;
|
||||
int flags = 0;
|
||||
|
||||
/*
|
||||
* If there is at least one crypto block then we'll trust
|
||||
@ -3705,16 +3715,18 @@ static void handle_cap_grant(struct inode *inode,
|
||||
ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
|
||||
ceph_cap_string(revoking));
|
||||
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 */
|
||||
else if (queue_invalidate &&
|
||||
revoke_wait = true;
|
||||
} else if (queue_invalidate &&
|
||||
revoking == CEPH_CAP_FILE_CACHE &&
|
||||
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0)
|
||||
; /* do nothing yet, invalidation will be queued */
|
||||
else if (cap == ci->i_auth_cap)
|
||||
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0) {
|
||||
revoke_wait = true; /* do nothing yet, invalidation will be queued */
|
||||
} else if (cap == ci->i_auth_cap) {
|
||||
check_caps = 1; /* check auth cap only */
|
||||
else
|
||||
} else {
|
||||
check_caps = 2; /* check all caps */
|
||||
}
|
||||
/* If there is new caps, try to wake up the waiters */
|
||||
if (~cap->issued & newcaps)
|
||||
wake = true;
|
||||
@ -3741,8 +3753,9 @@ static void handle_cap_grant(struct inode *inode,
|
||||
BUG_ON(cap->issued & ~cap->implemented);
|
||||
|
||||
/* 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;
|
||||
flags |= CHECK_CAPS_FLUSH_FORCE;
|
||||
if (cap == ci->i_auth_cap)
|
||||
check_caps = 1; /* check auth cap only */
|
||||
else
|
||||
@ -3798,9 +3811,9 @@ static void handle_cap_grant(struct inode *inode,
|
||||
|
||||
mutex_unlock(&session->s_mutex);
|
||||
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)
|
||||
ceph_check_caps(ci, CHECK_CAPS_NOINVAL);
|
||||
ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -200,9 +200,10 @@ struct ceph_cap {
|
||||
struct list_head caps_item;
|
||||
};
|
||||
|
||||
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
|
||||
#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */
|
||||
#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */
|
||||
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
|
||||
#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */
|
||||
#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */
|
||||
#define CHECK_CAPS_FLUSH_FORCE 8 /* force flush any caps */
|
||||
|
||||
struct ceph_cap_flush {
|
||||
u64 tid;
|
||||
|
Loading…
Reference in New Issue
Block a user