Skip to content

Commit

Permalink
ceph: fix multiple mds session shutdown
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sage Weil committed Aug 22, 2010
1 parent e56fa10 commit f3c60c5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 34 deletions.
68 changes: 35 additions & 33 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ static void handle_session(struct ceph_mds_session *session,
pr_info("mds%d reconnect denied\n", session->s_mds);
remove_session_caps(session);
wake = 1; /* for good measure */
complete_all(&mdsc->session_close_waiters);
wake_up_all(&mdsc->session_close_wq);
kick_requests(mdsc, mds);
break;

Expand Down Expand Up @@ -2876,7 +2876,7 @@ int ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
return -ENOMEM;

init_completion(&mdsc->safe_umount_waiters);
init_completion(&mdsc->session_close_waiters);
init_waitqueue_head(&mdsc->session_close_wq);
INIT_LIST_HEAD(&mdsc->waiting_for_map);
mdsc->sessions = NULL;
mdsc->max_sessions = 0;
Expand Down Expand Up @@ -3021,6 +3021,23 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush));
}

/*
* true if all sessions are closed, or we force unmount
*/
bool done_closing_sessions(struct ceph_mds_client *mdsc)
{
int i, n = 0;

if (mdsc->client->mount_state == CEPH_MOUNT_SHUTDOWN)
return true;

mutex_lock(&mdsc->mutex);
for (i = 0; i < mdsc->max_sessions; i++)
if (mdsc->sessions[i])
n++;
mutex_unlock(&mdsc->mutex);
return n == 0;
}

/*
* called after sb is ro.
Expand All @@ -3029,45 +3046,32 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
{
struct ceph_mds_session *session;
int i;
int n;
struct ceph_client *client = mdsc->client;
unsigned long started, timeout = client->mount_args->mount_timeout * HZ;
unsigned long timeout = client->mount_args->mount_timeout * HZ;

dout("close_sessions\n");

mutex_lock(&mdsc->mutex);

/* close sessions */
started = jiffies;
while (time_before(jiffies, started + timeout)) {
dout("closing sessions\n");
n = 0;
for (i = 0; i < mdsc->max_sessions; i++) {
session = __ceph_lookup_mds_session(mdsc, i);
if (!session)
continue;
mutex_unlock(&mdsc->mutex);
mutex_lock(&session->s_mutex);
__close_session(mdsc, session);
mutex_unlock(&session->s_mutex);
ceph_put_mds_session(session);
mutex_lock(&mdsc->mutex);
n++;
}
if (n == 0)
break;

if (client->mount_state == CEPH_MOUNT_SHUTDOWN)
break;

dout("waiting for sessions to close\n");
mutex_lock(&mdsc->mutex);
for (i = 0; i < mdsc->max_sessions; i++) {
session = __ceph_lookup_mds_session(mdsc, i);
if (!session)
continue;
mutex_unlock(&mdsc->mutex);
wait_for_completion_timeout(&mdsc->session_close_waiters,
timeout);
mutex_lock(&session->s_mutex);
__close_session(mdsc, session);
mutex_unlock(&session->s_mutex);
ceph_put_mds_session(session);
mutex_lock(&mdsc->mutex);
}
mutex_unlock(&mdsc->mutex);

dout("waiting for sessions to close\n");
wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
timeout);

/* tear down remaining sessions */
mutex_lock(&mdsc->mutex);
for (i = 0; i < mdsc->max_sessions; i++) {
if (mdsc->sessions[i]) {
session = get_session(mdsc->sessions[i]);
Expand All @@ -3080,9 +3084,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
mutex_lock(&mdsc->mutex);
}
}

WARN_ON(!list_empty(&mdsc->cap_delay_list));

mutex_unlock(&mdsc->mutex);

ceph_cleanup_empty_realms(mdsc);
Expand Down
3 changes: 2 additions & 1 deletion fs/ceph/mds_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ struct ceph_mds_client {
struct mutex mutex; /* all nested structures */

struct ceph_mdsmap *mdsmap;
struct completion safe_umount_waiters, session_close_waiters;
struct completion safe_umount_waiters;
wait_queue_head_t session_close_wq;
struct list_head waiting_for_map;

struct ceph_mds_session **sessions; /* NULL for mds if no session */
Expand Down

0 comments on commit f3c60c5

Please sign in to comment.