mirror of https://gitee.com/openkylin/linux.git
ceph: EIO all operations after forced umount
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>
This commit is contained in:
parent
64291f7db5
commit
48fec5d0a5
|
@ -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! */
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue