Skip to content

Commit 345978e

Browse files
committed
mds: do remove the cap when seqs equal or larger than last issue
There is a race in case of: MDS rw Client - Issue the 'Asx' caps to rw client - Adds the cap, then removes it later by queuing it to the cap release list. But the cap->seq may have been updated by previous cap grant requests. And the cap grant request won't increase the 'last_issue' seq in MDS. - ro client's lookup request comes and the MDS sends a 'Ax' caps revoke request to rw client by increasing the 'seq'. - The revoke request just finds that the cap doesn't exist, then queues a new cap release immediately with the new 'seq'. Then trigger to flush the pending cap releases to MDS. - Just receives the cap release request but the 'seq' > cap's 'last_issue', then MDS will skip removing the cap. And then the _do_cap_release() will issue the 'Ax' caps back to rw client. Then wakes up the ro client's lookup request, while the lookup request will try to revoke the 'Ax' caps again from the rw client. This will cause a spinlock infinitely in mds side. Fixes: https://tracker.ceph.com/issues/64977 Signed-off-by: Xiubo Li <[email protected]>
1 parent 5e689ef commit 345978e

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

src/mds/Locker.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,8 +4191,8 @@ void Locker::_do_cap_release(client_t client, inodeno_t ino, uint64_t cap_id,
41914191
new C_Locker_RetryCapRelease(this, client, ino, cap_id, mseq, seq));
41924192
return;
41934193
}
4194-
if (seq != cap->get_last_issue()) {
4195-
dout(7) << " issue_seq " << seq << " != " << cap->get_last_issue() << dendl;
4194+
if (seq < cap->get_last_issue()) {
4195+
dout(7) << " issue_seq " << seq << " < " << cap->get_last_issue() << dendl;
41964196
// clean out any old revoke history
41974197
cap->clean_revoke_from(seq);
41984198
eval_cap_gather(in);

0 commit comments

Comments
 (0)