Skip to content

Commit 1c42462

Browse files
committed
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
2 parents 725d410 + 31634d7 commit 1c42462

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
@@ -2016,6 +2016,8 @@ bool __ceph_should_report_size(struct ceph_inode_info *ci)
20162016
* CHECK_CAPS_AUTHONLY - we should only check the auth cap
20172017
* CHECK_CAPS_FLUSH - we should flush any dirty caps immediately, without
20182018
* further delay.
2019+
* CHECK_CAPS_FLUSH_FORCE - we should flush any caps immediately, without
2020+
* further delay.
20192021
*/
20202022
void ceph_check_caps(struct ceph_inode_info *ci, int flags)
20212023
{
@@ -2097,15 +2099,16 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
20972099
}
20982100

20992101
doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s "
2100-
"flushing %s issued %s revoking %s retain %s %s%s%s\n",
2102+
"flushing %s issued %s revoking %s retain %s %s%s%s%s\n",
21012103
inode, ceph_vinop(inode), ceph_cap_string(file_wanted),
21022104
ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
21032105
ceph_cap_string(ci->i_flushing_caps),
21042106
ceph_cap_string(issued), ceph_cap_string(revoking),
21052107
ceph_cap_string(retain),
21062108
(flags & CHECK_CAPS_AUTHONLY) ? " AUTHONLY" : "",
21072109
(flags & CHECK_CAPS_FLUSH) ? " FLUSH" : "",
2108-
(flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "");
2110+
(flags & CHECK_CAPS_NOINVAL) ? " NOINVAL" : "",
2111+
(flags & CHECK_CAPS_FLUSH_FORCE) ? " FLUSH_FORCE" : "");
21092112

21102113
/*
21112114
* 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)
21802183
queue_writeback = true;
21812184
}
21822185

2186+
if (flags & CHECK_CAPS_FLUSH_FORCE) {
2187+
doutc(cl, "force to flush caps\n");
2188+
goto ack;
2189+
}
2190+
21832191
if (cap == ci->i_auth_cap &&
21842192
(cap->issued & CEPH_CAP_FILE_WR)) {
21852193
/* request larger max_size from MDS? */
@@ -3510,6 +3518,8 @@ static void handle_cap_grant(struct inode *inode,
35103518
bool queue_invalidate = false;
35113519
bool deleted_inode = false;
35123520
bool fill_inline = false;
3521+
bool revoke_wait = false;
3522+
int flags = 0;
35133523

35143524
/*
35153525
* If there is at least one crypto block then we'll trust
@@ -3705,16 +3715,18 @@ static void handle_cap_grant(struct inode *inode,
37053715
ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
37063716
ceph_cap_string(revoking));
37073717
if (S_ISREG(inode->i_mode) &&
3708-
(revoking & used & CEPH_CAP_FILE_BUFFER))
3718+
(revoking & used & CEPH_CAP_FILE_BUFFER)) {
37093719
writeback = true; /* initiate writeback; will delay ack */
3710-
else if (queue_invalidate &&
3720+
revoke_wait = true;
3721+
} else if (queue_invalidate &&
37113722
revoking == CEPH_CAP_FILE_CACHE &&
3712-
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0)
3713-
; /* do nothing yet, invalidation will be queued */
3714-
else if (cap == ci->i_auth_cap)
3723+
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0) {
3724+
revoke_wait = true; /* do nothing yet, invalidation will be queued */
3725+
} else if (cap == ci->i_auth_cap) {
37153726
check_caps = 1; /* check auth cap only */
3716-
else
3727+
} else {
37173728
check_caps = 2; /* check all caps */
3729+
}
37183730
/* If there is new caps, try to wake up the waiters */
37193731
if (~cap->issued & newcaps)
37203732
wake = true;
@@ -3741,8 +3753,9 @@ static void handle_cap_grant(struct inode *inode,
37413753
BUG_ON(cap->issued & ~cap->implemented);
37423754

37433755
/* don't let check_caps skip sending a response to MDS for revoke msgs */
3744-
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
3756+
if (!revoke_wait && le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) {
37453757
cap->mds_wanted = 0;
3758+
flags |= CHECK_CAPS_FLUSH_FORCE;
37463759
if (cap == ci->i_auth_cap)
37473760
check_caps = 1; /* check auth cap only */
37483761
else
@@ -3798,9 +3811,9 @@ static void handle_cap_grant(struct inode *inode,
37983811

37993812
mutex_unlock(&session->s_mutex);
38003813
if (check_caps == 1)
3801-
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
3814+
ceph_check_caps(ci, flags | CHECK_CAPS_AUTHONLY | CHECK_CAPS_NOINVAL);
38023815
else if (check_caps == 2)
3803-
ceph_check_caps(ci, CHECK_CAPS_NOINVAL);
3816+
ceph_check_caps(ci, flags | CHECK_CAPS_NOINVAL);
38043817
}
38053818

38063819
/*

fs/ceph/super.h

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

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

207208
struct ceph_cap_flush {
208209
u64 tid;

0 commit comments

Comments
 (0)