diff options
author | Jeff Layton <jlayton@redhat.com> | 2017-10-19 08:53:58 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2017-11-13 06:11:42 -0500 |
commit | c8a96a31cb04c7664626ab6ada7f66c98c09efbd (patch) | |
tree | f84590b407cb514868f6c03516a24fcf09915d74 | |
parent | 9568c93ecab92d3ee60f2f6bec4e4d91641c61a6 (diff) |
ceph: clean up spinlocking and list handling around cleanup_cap_releases()
Functions that release a lock taken in a parent frame are notoriously
hard to follow. Split cleanup_cap_releases into two functions, one to
detach the cap releases from the session (which should be called with
the spinlock held), and another to dispose of those caps.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | fs/ceph/mds_client.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index b76506be4228..53cde84e698a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -1039,22 +1039,23 @@ void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc, | |||
1039 | * session caps | 1039 | * session caps |
1040 | */ | 1040 | */ |
1041 | 1041 | ||
1042 | /* caller holds s_cap_lock, we drop it */ | 1042 | static void detach_cap_releases(struct ceph_mds_session *session, |
1043 | static void cleanup_cap_releases(struct ceph_mds_client *mdsc, | 1043 | struct list_head *target) |
1044 | struct ceph_mds_session *session) | ||
1045 | __releases(session->s_cap_lock) | ||
1046 | { | 1044 | { |
1047 | LIST_HEAD(tmp_list); | 1045 | lockdep_assert_held(&session->s_cap_lock); |
1048 | list_splice_init(&session->s_cap_releases, &tmp_list); | 1046 | |
1047 | list_splice_init(&session->s_cap_releases, target); | ||
1049 | session->s_num_cap_releases = 0; | 1048 | session->s_num_cap_releases = 0; |
1050 | spin_unlock(&session->s_cap_lock); | 1049 | dout("dispose_cap_releases mds%d\n", session->s_mds); |
1050 | } | ||
1051 | 1051 | ||
1052 | dout("cleanup_cap_releases mds%d\n", session->s_mds); | 1052 | static void dispose_cap_releases(struct ceph_mds_client *mdsc, |
1053 | while (!list_empty(&tmp_list)) { | 1053 | struct list_head *dispose) |
1054 | { | ||
1055 | while (!list_empty(dispose)) { | ||
1054 | struct ceph_cap *cap; | 1056 | struct ceph_cap *cap; |
1055 | /* zero out the in-progress message */ | 1057 | /* zero out the in-progress message */ |
1056 | cap = list_first_entry(&tmp_list, | 1058 | cap = list_first_entry(dispose, struct ceph_cap, session_caps); |
1057 | struct ceph_cap, session_caps); | ||
1058 | list_del(&cap->session_caps); | 1059 | list_del(&cap->session_caps); |
1059 | ceph_put_cap(mdsc, cap); | 1060 | ceph_put_cap(mdsc, cap); |
1060 | } | 1061 | } |
@@ -1251,6 +1252,8 @@ static void remove_session_caps(struct ceph_mds_session *session) | |||
1251 | { | 1252 | { |
1252 | struct ceph_fs_client *fsc = session->s_mdsc->fsc; | 1253 | struct ceph_fs_client *fsc = session->s_mdsc->fsc; |
1253 | struct super_block *sb = fsc->sb; | 1254 | struct super_block *sb = fsc->sb; |
1255 | LIST_HEAD(dispose); | ||
1256 | |||
1254 | dout("remove_session_caps on %p\n", session); | 1257 | dout("remove_session_caps on %p\n", session); |
1255 | iterate_session_caps(session, remove_session_caps_cb, fsc); | 1258 | iterate_session_caps(session, remove_session_caps_cb, fsc); |
1256 | 1259 | ||
@@ -1285,10 +1288,12 @@ static void remove_session_caps(struct ceph_mds_session *session) | |||
1285 | } | 1288 | } |
1286 | 1289 | ||
1287 | // drop cap expires and unlock s_cap_lock | 1290 | // drop cap expires and unlock s_cap_lock |
1288 | cleanup_cap_releases(session->s_mdsc, session); | 1291 | detach_cap_releases(session, &dispose); |
1289 | 1292 | ||
1290 | BUG_ON(session->s_nr_caps > 0); | 1293 | BUG_ON(session->s_nr_caps > 0); |
1291 | BUG_ON(!list_empty(&session->s_cap_flushing)); | 1294 | BUG_ON(!list_empty(&session->s_cap_flushing)); |
1295 | spin_unlock(&session->s_cap_lock); | ||
1296 | dispose_cap_releases(session->s_mdsc, &dispose); | ||
1292 | } | 1297 | } |
1293 | 1298 | ||
1294 | /* | 1299 | /* |
@@ -3015,6 +3020,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, | |||
3015 | int s_nr_caps; | 3020 | int s_nr_caps; |
3016 | struct ceph_pagelist *pagelist; | 3021 | struct ceph_pagelist *pagelist; |
3017 | struct ceph_reconnect_state recon_state; | 3022 | struct ceph_reconnect_state recon_state; |
3023 | LIST_HEAD(dispose); | ||
3018 | 3024 | ||
3019 | pr_info("mds%d reconnect start\n", mds); | 3025 | pr_info("mds%d reconnect start\n", mds); |
3020 | 3026 | ||
@@ -3048,7 +3054,9 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, | |||
3048 | */ | 3054 | */ |
3049 | session->s_cap_reconnect = 1; | 3055 | session->s_cap_reconnect = 1; |
3050 | /* drop old cap expires; we're about to reestablish that state */ | 3056 | /* drop old cap expires; we're about to reestablish that state */ |
3051 | cleanup_cap_releases(mdsc, session); | 3057 | detach_cap_releases(session, &dispose); |
3058 | spin_unlock(&session->s_cap_lock); | ||
3059 | dispose_cap_releases(mdsc, &dispose); | ||
3052 | 3060 | ||
3053 | /* trim unused caps to reduce MDS's cache rejoin time */ | 3061 | /* trim unused caps to reduce MDS's cache rejoin time */ |
3054 | if (mdsc->fsc->sb->s_root) | 3062 | if (mdsc->fsc->sb->s_root) |