ceph: EIO all operations after forced umount
authorYan, Zheng <zyan@redhat.com>
Wed, 1 Jul 2015 08:27:46 +0000 (16:27 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 8 Sep 2015 20:14:28 +0000 (23:14 +0300)
This patch makes try_get_cap_refs() and __do_request() check
if the file system was forced umount, and return -EIO if it was.
This patch also adds a helper function to drops dirty caps and
wakes up blocking operation.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.c

index 890c50971a690472f6dc795b00fd0bcfbcdf1a39..1594f2c590bd25bbb062eb0e1f50412fd58da3db 100644 (file)
@@ -717,7 +717,7 @@ static int ceph_writepages_start(struct address_space *mapping,
             wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
             (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
 
-       if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
+       if (ACCESS_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
                pr_warn("writepage_start %p on forced umount\n", inode);
                return -EIO; /* we're in a forced umount, don't write! */
        }
index ddd5e94712904501db729c51b59de72cd88ddb5a..27b566874bc1d2b0494b49ebe1769f380ccf8648 100644 (file)
@@ -2413,6 +2413,14 @@ again:
                        goto out_unlock;
                }
 
+               if (!__ceph_is_any_caps(ci) &&
+                   ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
+                       dout("get_cap_refs %p forced umount\n", inode);
+                       *err = -EIO;
+                       ret = 1;
+                       goto out_unlock;
+               }
+
                dout("get_cap_refs %p have %s needed %s\n", inode,
                     ceph_cap_string(have), ceph_cap_string(need));
        }
index 6aa07af67603ada211f49268d3845ea62b625720..ddc471c3223000ef5d272d1cbd6ab5956d003785 100644 (file)
@@ -2107,7 +2107,6 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
        msg = create_request_message(mdsc, req, mds, drop_cap_releases);
        if (IS_ERR(msg)) {
                req->r_err = PTR_ERR(msg);
-               complete_request(mdsc, req);
                return PTR_ERR(msg);
        }
        req->r_request = msg;
@@ -2135,7 +2134,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
 {
        struct ceph_mds_session *session = NULL;
        int mds = -1;
-       int err = -EAGAIN;
+       int err = 0;
 
        if (req->r_err || req->r_got_result) {
                if (req->r_aborted)
@@ -2149,6 +2148,11 @@ static int __do_request(struct ceph_mds_client *mdsc,
                err = -EIO;
                goto finish;
        }
+       if (ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
+               dout("do_request forced umount\n");
+               err = -EIO;
+               goto finish;
+       }
 
        put_request_session(req);
 
@@ -2196,13 +2200,15 @@ static int __do_request(struct ceph_mds_client *mdsc,
 
 out_session:
        ceph_put_mds_session(session);
+finish:
+       if (err) {
+               dout("__do_request early error %d\n", err);
+               req->r_err = err;
+               complete_request(mdsc, req);
+               __unregister_request(mdsc, req);
+       }
 out:
        return err;
-
-finish:
-       req->r_err = err;
-       complete_request(mdsc, req);
-       goto out;
 }
 
 /*
@@ -2289,8 +2295,6 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
 
        if (req->r_err) {
                err = req->r_err;
-               __unregister_request(mdsc, req);
-               dout("do_request early error %d\n", err);
                goto out;
        }
 
@@ -3555,7 +3559,7 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
 {
        u64 want_tid, want_flush, want_snap;
 
-       if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
+       if (ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
                return;
 
        dout("sync\n");
@@ -3584,7 +3588,7 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
  */
 static bool done_closing_sessions(struct ceph_mds_client *mdsc)
 {
-       if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
+       if (ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
                return true;
        return atomic_read(&mdsc->num_sessions) == 0;
 }
@@ -3643,6 +3647,34 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        dout("stopped\n");
 }
 
+void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
+{
+       struct ceph_mds_session *session;
+       int mds;
+
+       dout("force umount\n");
+
+       mutex_lock(&mdsc->mutex);
+       for (mds = 0; mds < mdsc->max_sessions; mds++) {
+               session = __ceph_lookup_mds_session(mdsc, mds);
+               if (!session)
+                       continue;
+               mutex_unlock(&mdsc->mutex);
+               mutex_lock(&session->s_mutex);
+               __close_session(mdsc, session);
+               if (session->s_state == CEPH_MDS_SESSION_CLOSING) {
+                       cleanup_session_requests(mdsc, session);
+                       remove_session_caps(session);
+               }
+               mutex_unlock(&session->s_mutex);
+               ceph_put_mds_session(session);
+               mutex_lock(&mdsc->mutex);
+               kick_requests(mdsc, mds);
+       }
+       __wake_requests(mdsc, &mdsc->waiting_for_map);
+       mutex_unlock(&mdsc->mutex);
+}
+
 static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
 {
        dout("stop\n");
index 762757e6cebf95fff324894d1650b8271210acdd..f575eafe2261cbd5974d8d4f072879e9d5bd7a39 100644 (file)
@@ -366,6 +366,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_destroy(struct ceph_fs_client *fsc);
 
 extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
index d1c833c321b92eff48d9f35bf7171ef0ac59e7bf..69e6e19bcfc172d44d3cb1c369947172222fe4c3 100644 (file)
@@ -708,6 +708,7 @@ static void ceph_umount_begin(struct super_block *sb)
        if (!fsc)
                return;
        fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
+       ceph_mdsc_force_umount(fsc->mdsc);
        return;
 }