Skip to content

Commit

Permalink
ceph: EIO all operations after forced umount
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yan, Zheng authored and Ilya Dryomov committed Sep 8, 2015
1 parent 64291f7 commit 48fec5d
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 12 deletions.
2 changes: 1 addition & 1 deletion fs/ceph/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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! */
}
Expand Down
8 changes: 8 additions & 0 deletions fs/ceph/caps.c
Original file line number Diff line number Diff line change
Expand Up @@ -2413,6 +2413,14 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
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));
}
Expand Down
54 changes: 43 additions & 11 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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);

Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions fs/ceph/mds_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions fs/ceph/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 48fec5d

Please sign in to comment.