Skip to content

Commit adc5246

Browse files
lxbszidryomov
authored andcommitted
ceph: flush all caps releases when syncing the whole filesystem
We have hit a race between cap releases and cap revoke request that will cause the check_caps() to miss sending a cap revoke ack to MDS. And the client will depend on the cap release to release that revoking caps, which could be delayed for some unknown reasons. In Kclient we have figured out the RCA about race and we need a way to explictly trigger this manually could help to get rid of the caps revoke stuck issue. Link: https://tracker.ceph.com/issues/67221 Signed-off-by: Xiubo Li <[email protected]> Reviewed-by: Ilya Dryomov <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent c085f6c commit adc5246

File tree

4 files changed

+25
-0
lines changed

4 files changed

+25
-0
lines changed

fs/ceph/caps.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4702,6 +4702,28 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
47024702
ceph_mdsc_iterate_sessions(mdsc, flush_dirty_session_caps, true);
47034703
}
47044704

4705+
/*
4706+
* Flush all cap releases to the mds
4707+
*/
4708+
static void flush_cap_releases(struct ceph_mds_session *s)
4709+
{
4710+
struct ceph_mds_client *mdsc = s->s_mdsc;
4711+
struct ceph_client *cl = mdsc->fsc->client;
4712+
4713+
doutc(cl, "begin\n");
4714+
spin_lock(&s->s_cap_lock);
4715+
if (s->s_num_cap_releases)
4716+
ceph_flush_session_cap_releases(mdsc, s);
4717+
spin_unlock(&s->s_cap_lock);
4718+
doutc(cl, "done\n");
4719+
4720+
}
4721+
4722+
void ceph_flush_cap_releases(struct ceph_mds_client *mdsc)
4723+
{
4724+
ceph_mdsc_iterate_sessions(mdsc, flush_cap_releases, true);
4725+
}
4726+
47054727
void __ceph_touch_fmode(struct ceph_inode_info *ci,
47064728
struct ceph_mds_client *mdsc, int fmode)
47074729
{

fs/ceph/mds_client.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5877,6 +5877,7 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
58775877
mutex_unlock(&mdsc->mutex);
58785878

58795879
ceph_flush_dirty_caps(mdsc);
5880+
ceph_flush_cap_releases(mdsc);
58805881
spin_lock(&mdsc->cap_dirty_lock);
58815882
want_flush = mdsc->last_cap_flush_tid;
58825883
if (!list_empty(&mdsc->cap_flush_list)) {

fs/ceph/super.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static int ceph_sync_fs(struct super_block *sb, int wait)
126126
if (!wait) {
127127
doutc(cl, "(non-blocking)\n");
128128
ceph_flush_dirty_caps(fsc->mdsc);
129+
ceph_flush_cap_releases(fsc->mdsc);
129130
doutc(cl, "(non-blocking) done\n");
130131
return 0;
131132
}

fs/ceph/super.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ extern bool __ceph_should_report_size(struct ceph_inode_info *ci);
12681268
extern void ceph_check_caps(struct ceph_inode_info *ci, int flags);
12691269
extern unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
12701270
extern void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc);
1271+
extern void ceph_flush_cap_releases(struct ceph_mds_client *mdsc);
12711272
extern int ceph_drop_caps_for_unlink(struct inode *inode);
12721273
extern int ceph_encode_inode_release(void **p, struct inode *inode,
12731274
int mds, int drop, int unless, int force);

0 commit comments

Comments
 (0)