Skip to content

Commit ad612d6

Browse files
committed
ceph: force sending a cap update msg back to MDS for revoke op
JIRA: https://issues.redhat.com/browse/RHEL-48618 Conflicts: missing the commit 38d4640("ceph: print cluster fsid and client global_id in all debug logs") and a tiny debug log conflict. commit 31634d7 Author: Xiubo Li <xiubli@redhat.com> Date: Fri Jul 12 12:40:19 2024 +0800 ceph: force sending a cap update msg back to MDS for revoke op If a client sends out a cap update dropping caps with the prior 'seq' just before an incoming cap revoke request, then the client may drop the revoke because it believes it's already released the requested capabilities. This causes the MDS to wait indefinitely for the client to respond to the revoke. It's therefore always a good idea to ack the cap revoke request with the bumped up 'seq'. Currently if the cap->issued equals to the newcaps the check_caps() will do nothing, we should force flush the caps. Cc: stable@vger.kernel.org Link: https://tracker.ceph.com/issues/61782 Signed-off-by: Xiubo Li <xiubli@redhat.com> Reviewed-by: Venky Shankar <vshankar@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Xiubo Li <xiubli@redhat.com>
1 parent 77affc0 commit ad612d6

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

fs/ceph/caps.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,8 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci)
19631963
* CHECK_CAPS_AUTHONLY - we should only check the auth cap
19641964
* CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without
19651965
* further delay.
1966+
* CHECK_CAPS_FLUSH_FORCE - we should flush any caps immediately, without
1967+
* further delay.
19661968
*/
19671969
void ceph_check_caps(struct ceph_inode_info *ci, int flags)
19681970
{
@@ -2043,15 +2045,16 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
20432045
}
20442046

20452047
dout("check_caps %llx.%llx file_want %s used %s dirty %s flushing %s"
2046-
" issued %s revoking %s retain %s %s%s%s\n", ceph_vinop(inode),
2048+
" issued %s revoking %s retain %s %s%s%s%s\n", ceph_vinop(inode),
20472049
ceph_cap_string(file_wanted),
20482050
ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
20492051
ceph_cap_string(ci->i_flushing_caps),
20502052
ceph_cap_string(issued), ceph_cap_string(revoking),
20512053
ceph_cap_string(retain),
20522054
(flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "",
20532055
(flags & CHECK_CAPS_FLUSH) ? " FLUSH" : "",
2054-
(flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "");
2056+
(flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "",
2057+
(flags & CHECK_CAPS_FLUSH_FORCE) ? " FLUSH_FORCE" : "");
20552058

20562059
/*
20572060
* If we no longer need to hold onto old our caps, and we may
@@ -2126,6 +2129,11 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
21262129
queue_writeback = true;
21272130
}
21282131

2132+
if (flags & CHECK_CAPS_FLUSH_FORCE) {
2133+
dout("force to flush caps\n");
2134+
goto ack;
2135+
}
2136+
21292137
if (cap == ci->i_auth_cap &&
21302138
(cap->issued & CEPH_CAP_FILE_WR)) {
21312139
/* request larger max_size from MDS? */
@@ -3418,6 +3426,8 @@ static void handle_cap_grant(struct inode *inode,
34183426
bool queue_invalidate = false;
34193427
bool deleted_inode = false;
34203428
bool fill_inline = false;
3429+
bool revoke_wait = false;
3430+
int flags = 0;
34213431

34223432
/*
34233433
* If there is at least one crypto block then we'll trust
@@ -3612,16 +3622,18 @@ static void handle_cap_grant(struct inode *inode,
36123622
ceph_cap_string(newcaps),
36133623
ceph_cap_string(revoking));
36143624
if (S_ISREG(inode->i_mode) &&
3615-
(revoking & used & CEPH_CAP_FILE_BUFFER))
3625+
(revoking & used & CEPH_CAP_FILE_BUFFER)) {
36163626
writeback = true; /* initiate writeback; will delay ack */
3617-
else if (queue_invalidate &&
3627+
revoke_wait = true;
3628+
} else if (queue_invalidate &&
36183629
revoking == CEPH_CAP_FILE_CACHE &&
3619-
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0)
3620-
; /* do nothing yet, invalidation will be queued */
3621-
else if (cap == ci->i_auth_cap)
3630+
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0) {
3631+
revoke_wait = true; /* do nothing yet, invalidation will be queued */
3632+
} else if (cap == ci->i_auth_cap) {
36223633
check_caps = 1; /* check auth cap only */
3623-
else
3634+
} else {
36243635
check_caps = 2; /* check all caps */
3636+
}
36253637
/* If there is new caps, try to wake up the waiters */
36263638
if (~cap->issued & newcaps)
36273639
wake = true;
@@ -3647,8 +3659,9 @@ static void handle_cap_grant(struct inode *inode,
36473659
BUG_ON(cap->issued & ~cap->implemented);
36483660

36493661
/* don't let check_caps skip sending a response to MDS for revoke msgs */
3650-
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
3662+
if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
36513663
cap->mds_wanted = 0;
3664+
flags |= CHECK_CAPS_FLUSH_FORCE;
36523665
if (cap == ci->i_auth_cap)
36533666
check_caps = 1; /* check auth cap only */
36543667
else
@@ -3704,9 +3717,9 @@ static void handle_cap_grant(struct inode *inode,
37043717

37053718
mutex_unlock(&session->s_mutex);
37063719
if (check_caps == 1)
3707-
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
3720+
ceph_check_caps(ci, flags | CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
37083721
else if (check_caps == 2)
3709-
ceph_check_caps(ci, CHECK_CAPS_NOINVAL);
3722+
ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL);
37103723
}
37113724

37123725
/*

fs/ceph/super.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,10 @@ struct ceph_cap {
199199
struct list_head caps_item;
200200
};
201201

202-
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
203-
#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */
204-
#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */
202+
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
203+
#define CHECK_CAPS_FLUSH 2 /* flush any dirty caps */
204+
#define CHECK_CAPS_NOINVAL 4 /* don't invalidate pagecache */
205+
#define CHECK_CAPS_FLUSH_FORCE 8 /* force flush any caps */
205206

206207
struct ceph_cap_flush {
207208
u64 tid;

0 commit comments

Comments
 (0)