aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-08-11 17:51:23 -0400
committerSage Weil <sage@newdream.net>2010-08-22 18:04:43 -0400
commitf3c60c5918f26ea16761ddc8b12d8401a3db626b (patch)
tree00bde7250b6753910a38b454c7a9cee2eb7e84e7
parente56fa10e92e077d456cbc33b7025032887772b33 (diff)
ceph: fix multiple mds session shutdown
The use of a completion when waiting for session shutdown during umount is inappropriate, given the complexity of the condition. For multiple MDS's, this resulted in the umount thread spinning, often preventing the session close message from being processed in some cases. Switch to a waitqueue and defined a condition helper. This cleans things up nicely. Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/mds_client.c68
-rw-r--r--fs/ceph/mds_client.h3
2 files changed, 37 insertions, 34 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index a75ddbf9fe37..397a47b696ce 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2208,7 +2208,7 @@ static void handle_session(struct ceph_mds_session *session,
2208 pr_info("mds%d reconnect denied\n", session->s_mds); 2208 pr_info("mds%d reconnect denied\n", session->s_mds);
2209 remove_session_caps(session); 2209 remove_session_caps(session);
2210 wake = 1; /* for good measure */ 2210 wake = 1; /* for good measure */
2211 complete_all(&mdsc->session_close_waiters); 2211 wake_up_all(&mdsc->session_close_wq);
2212 kick_requests(mdsc, mds); 2212 kick_requests(mdsc, mds);
2213 break; 2213 break;
2214 2214
@@ -2876,7 +2876,7 @@ int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
2876 return -ENOMEM; 2876 return -ENOMEM;
2877 2877
2878 init_completion(&mdsc->safe_umount_waiters); 2878 init_completion(&mdsc->safe_umount_waiters);
2879 init_completion(&mdsc->session_close_waiters); 2879 init_waitqueue_head(&mdsc->session_close_wq);
2880 INIT_LIST_HEAD(&mdsc->waiting_for_map); 2880 INIT_LIST_HEAD(&mdsc->waiting_for_map);
2881 mdsc->sessions = NULL; 2881 mdsc->sessions = NULL;
2882 mdsc->max_sessions = 0; 2882 mdsc->max_sessions = 0;
@@ -3021,6 +3021,23 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
3021 wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush)); 3021 wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush));
3022} 3022}
3023 3023
3024/*
3025 * true if all sessions are closed, or we force unmount
3026 */
3027bool done_closing_sessions(struct ceph_mds_client *mdsc)
3028{
3029 int i, n = 0;
3030
3031 if (mdsc->client->mount_state == CEPH_MOUNT_SHUTDOWN)
3032 return true;
3033
3034 mutex_lock(&mdsc->mutex);
3035 for (i = 0; i < mdsc->max_sessions; i++)
3036 if (mdsc->sessions[i])
3037 n++;
3038 mutex_unlock(&mdsc->mutex);
3039 return n == 0;
3040}
3024 3041
3025/* 3042/*
3026 * called after sb is ro. 3043 * called after sb is ro.
@@ -3029,45 +3046,32 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
3029{ 3046{
3030 struct ceph_mds_session *session; 3047 struct ceph_mds_session *session;
3031 int i; 3048 int i;
3032 int n;
3033 struct ceph_client *client = mdsc->client; 3049 struct ceph_client *client = mdsc->client;
3034 unsigned long started, timeout = client->mount_args->mount_timeout * HZ; 3050 unsigned long timeout = client->mount_args->mount_timeout * HZ;
3035 3051
3036 dout("close_sessions\n"); 3052 dout("close_sessions\n");
3037 3053
3038 mutex_lock(&mdsc->mutex);
3039
3040 /* close sessions */ 3054 /* close sessions */
3041 started = jiffies; 3055 mutex_lock(&mdsc->mutex);
3042 while (time_before(jiffies, started + timeout)) { 3056 for (i = 0; i < mdsc->max_sessions; i++) {
3043 dout("closing sessions\n"); 3057 session = __ceph_lookup_mds_session(mdsc, i);
3044 n = 0; 3058 if (!session)
3045 for (i = 0; i < mdsc->max_sessions; i++) { 3059 continue;
3046 session = __ceph_lookup_mds_session(mdsc, i);
3047 if (!session)
3048 continue;
3049 mutex_unlock(&mdsc->mutex);
3050 mutex_lock(&session->s_mutex);
3051 __close_session(mdsc, session);
3052 mutex_unlock(&session->s_mutex);
3053 ceph_put_mds_session(session);
3054 mutex_lock(&mdsc->mutex);
3055 n++;
3056 }
3057 if (n == 0)
3058 break;
3059
3060 if (client->mount_state == CEPH_MOUNT_SHUTDOWN)
3061 break;
3062
3063 dout("waiting for sessions to close\n");
3064 mutex_unlock(&mdsc->mutex); 3060 mutex_unlock(&mdsc->mutex);
3065 wait_for_completion_timeout(&mdsc->session_close_waiters, 3061 mutex_lock(&session->s_mutex);
3066 timeout); 3062 __close_session(mdsc, session);
3063 mutex_unlock(&session->s_mutex);
3064 ceph_put_mds_session(session);
3067 mutex_lock(&mdsc->mutex); 3065 mutex_lock(&mdsc->mutex);
3068 } 3066 }
3067 mutex_unlock(&mdsc->mutex);
3068
3069 dout("waiting for sessions to close\n");
3070 wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
3071 timeout);
3069 3072
3070 /* tear down remaining sessions */ 3073 /* tear down remaining sessions */
3074 mutex_lock(&mdsc->mutex);
3071 for (i = 0; i < mdsc->max_sessions; i++) { 3075 for (i = 0; i < mdsc->max_sessions; i++) {
3072 if (mdsc->sessions[i]) { 3076 if (mdsc->sessions[i]) {
3073 session = get_session(mdsc->sessions[i]); 3077 session = get_session(mdsc->sessions[i]);
@@ -3080,9 +3084,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
3080 mutex_lock(&mdsc->mutex); 3084 mutex_lock(&mdsc->mutex);
3081 } 3085 }
3082 } 3086 }
3083
3084 WARN_ON(!list_empty(&mdsc->cap_delay_list)); 3087 WARN_ON(!list_empty(&mdsc->cap_delay_list));
3085
3086 mutex_unlock(&mdsc->mutex); 3088 mutex_unlock(&mdsc->mutex);
3087 3089
3088 ceph_cleanup_empty_realms(mdsc); 3090 ceph_cleanup_empty_realms(mdsc);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index ab7e89f5e344..c98267ce6d2a 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -234,7 +234,8 @@ struct ceph_mds_client {
234 struct mutex mutex; /* all nested structures */ 234 struct mutex mutex; /* all nested structures */
235 235
236 struct ceph_mdsmap *mdsmap; 236 struct ceph_mdsmap *mdsmap;
237 struct completion safe_umount_waiters, session_close_waiters; 237 struct completion safe_umount_waiters;
238 wait_queue_head_t session_close_wq;
238 struct list_head waiting_for_map; 239 struct list_head waiting_for_map;
239 240
240 struct ceph_mds_session **sessions; /* NULL for mds if no session */ 241 struct ceph_mds_session **sessions; /* NULL for mds if no session */