ceph: add helper function that forcibly reconnects to ceph cluster.
authorYan, Zheng <zyan@redhat.com>
Thu, 25 Jul 2019 12:16:44 +0000 (20:16 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 16 Sep 2019 10:06:24 +0000 (12:06 +0200)
It closes mds sessions, drop all caps and invalidates page caches,
then use new entity address to reconnect to the cluster.

After reconnect, all dirty data/metadata are dropped, file locks
get lost sliently. Open files continue to work because client will
try renewing caps on later read/write.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/mds_client.c
fs/ceph/super.c
fs/ceph/super.h

index df4bea2..ed4d20a 100644 (file)
@@ -1394,9 +1394,12 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                struct ceph_cap_flush *cf;
                struct ceph_mds_client *mdsc = fsc->mdsc;
 
-               if (ci->i_wrbuffer_ref > 0 &&
-                   READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
-                       invalidate = true;
+               if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
+                       if (inode->i_data.nrpages > 0)
+                               invalidate = true;
+                       if (ci->i_wrbuffer_ref > 0)
+                               mapping_set_error(&inode->i_data, -EIO);
+               }
 
                while (!list_empty(&ci->i_cap_flush_list)) {
                        cf = list_first_entry(&ci->i_cap_flush_list,
@@ -4369,7 +4372,12 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
                session = __ceph_lookup_mds_session(mdsc, mds);
                if (!session)
                        continue;
+
+               if (session->s_state == CEPH_MDS_SESSION_REJECTED)
+                       __unregister_session(mdsc, session);
+               __wake_requests(mdsc, &session->s_waiting);
                mutex_unlock(&mdsc->mutex);
+
                mutex_lock(&session->s_mutex);
                __close_session(mdsc, session);
                if (session->s_state == CEPH_MDS_SESSION_CLOSING) {
@@ -4378,6 +4386,7 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
                }
                mutex_unlock(&session->s_mutex);
                ceph_put_mds_session(session);
+
                mutex_lock(&mdsc->mutex);
                kick_requests(mdsc, mds);
        }
index ab4868c..a95dd13 100644 (file)
@@ -829,7 +829,6 @@ static void ceph_umount_begin(struct super_block *sb)
        fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
        ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
        ceph_mdsc_force_umount(fsc->mdsc);
-       return;
 }
 
 static int ceph_remount(struct super_block *sb, int *flags, char *data)
@@ -1152,6 +1151,31 @@ static struct file_system_type ceph_fs_type = {
 };
 MODULE_ALIAS_FS("ceph");
 
+int ceph_force_reconnect(struct super_block *sb)
+{
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+       int err = 0;
+
+       ceph_umount_begin(sb);
+
+       /* Make sure all page caches get invalidated.
+        * see remove_session_caps_cb() */
+       flush_workqueue(fsc->inode_wq);
+
+       /* In case that we were blacklisted. This also reset
+        * all mon/osd connections */
+       ceph_reset_client_addr(fsc->client);
+
+       ceph_osdc_clear_abort_err(&fsc->client->osdc);
+       fsc->mount_state = CEPH_MOUNT_MOUNTED;
+
+       if (sb->s_root) {
+               err = __ceph_do_getattr(d_inode(sb->s_root), NULL,
+                                       CEPH_STAT_CAP_INODE, true);
+       }
+       return err;
+}
+
 static int __init init_ceph(void)
 {
        int ret = init_caches();
index 1452f62..7af7f2b 100644 (file)
@@ -846,7 +846,8 @@ static inline int default_congestion_kb(void)
 }
 
 
-
+/* super.c */
+extern int ceph_force_reconnect(struct super_block *sb);
 /* snap.c */
 struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc,
                                               u64 ino);