diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
| -rw-r--r-- | fs/ceph/mds_client.c | 34 | 
1 files changed, 19 insertions, 15 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 60a9a4ae47b..24561a557e0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -736,9 +736,10 @@ static void cleanup_cap_releases(struct ceph_mds_session *session)  }  /* - * Helper to safely iterate over all caps associated with a session. + * Helper to safely iterate over all caps associated with a session, with + * special care taken to handle a racing __ceph_remove_cap().   * - * caller must hold session s_mutex + * Caller must hold session s_mutex.   */  static int iterate_session_caps(struct ceph_mds_session *session,  				 int (*cb)(struct inode *, struct ceph_cap *, @@ -2136,7 +2137,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds)  	struct ceph_mds_session *session = NULL;  	struct ceph_msg *reply;  	struct rb_node *p; -	int err; +	int err = -ENOMEM;  	struct ceph_pagelist *pagelist;  	pr_info("reconnect to recovering mds%d\n", mds); @@ -2185,7 +2186,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds)  		goto fail;  	err = iterate_session_caps(session, encode_caps_cb, pagelist);  	if (err < 0) -		goto out; +		goto fail;  	/*  	 * snaprealms.  we provide mds with the ino, seq (version), and @@ -2213,28 +2214,31 @@ send:  	reply->nr_pages = calc_pages_for(0, pagelist->length);  	ceph_con_send(&session->s_con, reply); -	if (session) { -		session->s_state = CEPH_MDS_SESSION_OPEN; -		__wake_requests(mdsc, &session->s_waiting); -	} +	session->s_state = CEPH_MDS_SESSION_OPEN; +	mutex_unlock(&session->s_mutex); + +	mutex_lock(&mdsc->mutex); +	__wake_requests(mdsc, &session->s_waiting); +	mutex_unlock(&mdsc->mutex); + +	ceph_put_mds_session(session); -out:  	up_read(&mdsc->snap_rwsem); -	if (session) { -		mutex_unlock(&session->s_mutex); -		ceph_put_mds_session(session); -	}  	mutex_lock(&mdsc->mutex);  	return;  fail:  	ceph_msg_put(reply); +	up_read(&mdsc->snap_rwsem); +	mutex_unlock(&session->s_mutex); +	ceph_put_mds_session(session);  fail_nomsg:  	ceph_pagelist_release(pagelist);  	kfree(pagelist);  fail_nopagelist: -	pr_err("ENOMEM preparing reconnect for mds%d\n", mds); -	goto out; +	pr_err("error %d preparing reconnect for mds%d\n", err, mds); +	mutex_lock(&mdsc->mutex); +	return;  }  |