diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index a14d64664878..d65da57406bd 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -210,6 +210,31 @@ CEPH_DEFINE_SHOW_FUNC(mdsc_show)
 CEPH_DEFINE_SHOW_FUNC(caps_show)
 CEPH_DEFINE_SHOW_FUNC(mds_sessions_show)
 
+static ssize_t control_file_write(struct file *file,
+				  const char __user *ubuf,
+				  size_t count, loff_t *ppos)
+{
+	struct ceph_fs_client *fsc = file_inode(file)->i_private;
+	char buf[16];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, ubuf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (!strcmp(buf, "force_reconnect")) {
+		ceph_mdsc_force_reconnect(fsc->mdsc);
+	} else {
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static const struct file_operations control_file_fops = {
+	.write = control_file_write,
+};
 
 /*
  * debugfs
@@ -233,7 +258,6 @@ static int congestion_kb_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
 			congestion_kb_set, "%llu\n");
 
-
 void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 {
 	dout("ceph_fs_debugfs_cleanup\n");
@@ -243,6 +267,7 @@ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
 	debugfs_remove(fsc->debugfs_mds_sessions);
 	debugfs_remove(fsc->debugfs_caps);
 	debugfs_remove(fsc->debugfs_mdsc);
+	debugfs_remove(fsc->debugfs_control);
 }
 
 int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
@@ -302,6 +327,13 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_caps)
 		goto out;
 
+	fsc->debugfs_control = debugfs_create_file("control",
+						   0200,
+						   fsc->client->debugfs_dir,
+						   fsc,
+						   &control_file_fops);
+	if (!fsc->debugfs_control)
+		goto out;
 	return 0;
 
 out:
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index f5c3499fdec6..95ee893205c5 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2631,7 +2631,7 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
 		if (req->r_attempts > 0)
 			continue; /* only new requests */
 		if (req->r_session &&
-		    req->r_session->s_mds == mds) {
+		    (mds == -1 || req->r_session->s_mds == mds)) {
 			dout(" kicking tid %llu\n", req->r_tid);
 			list_del_init(&req->r_wait);
 			__do_request(mdsc, req);
@@ -4371,6 +4371,45 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
 	mutex_unlock(&mdsc->mutex);
 }
 
+void ceph_mdsc_force_reconnect(struct ceph_mds_client *mdsc)
+{
+	struct ceph_mds_session *session;
+	int mds;
+	LIST_HEAD(to_wake);
+
+	pr_info("force reconnect\n");
+
+	/* this also reset add mon/osd conntions */
+	ceph_reset_client_addr(mdsc->fsc->client);
+
+	mutex_lock(&mdsc->mutex);
+
+	/* reset mds connections */
+	for (mds = 0; mds < mdsc->max_sessions; mds++) {
+		session = __ceph_lookup_mds_session(mdsc, mds);
+		if (!session)
+			continue;
+
+		__unregister_session(mdsc, session);
+		list_splice_init(&session->s_waiting, &to_wake);
+		mutex_unlock(&mdsc->mutex);
+
+		mutex_lock(&session->s_mutex);
+		cleanup_session_requests(mdsc, session);
+		remove_session_caps(session);
+		mutex_unlock(&session->s_mutex);
+
+		ceph_put_mds_session(session);
+		mutex_lock(&mdsc->mutex);
+	}
+
+	list_splice_init(&mdsc->waiting_for_map, &to_wake);
+	__wake_requests(mdsc, &to_wake);
+	kick_requests(mdsc, -1);
+
+	mutex_unlock(&mdsc->mutex);
+}
+
 static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
 {
 	dout("stop\n");
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 330769ecb601..125e26895f14 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -457,6 +457,7 @@ extern int ceph_send_msg_mds(struct ceph_mds_client *mdsc,
 extern int ceph_mdsc_init(struct ceph_fs_client *fsc);
 extern void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc);
 extern void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc);
+extern void ceph_mdsc_force_reconnect(struct ceph_mds_client *mdsc);
 extern void ceph_mdsc_destroy(struct ceph_fs_client *fsc);
 
 extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 9c82d213a5ab..9ccb6e031988 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -118,6 +118,7 @@ struct ceph_fs_client {
 	struct dentry *debugfs_bdi;
 	struct dentry *debugfs_mdsc, *debugfs_mdsmap;
 	struct dentry *debugfs_mds_sessions;
+	struct dentry *debugfs_control;
 #endif
 
 #ifdef CONFIG_CEPH_FSCACHE
