Commit c58c8441 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Don't accept more reads/writes if the open context recovery failed

If the state recovery failed, we want to ensure that the application
doesn't try to use the same file descriptor for more reads or writes.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 5d422301
...@@ -305,6 +305,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) ...@@ -305,6 +305,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
{ {
struct nfs_read_data *rdata = data; struct nfs_read_data *rdata = data;
if (unlikely(test_bit(NFS_CONTEXT_BAD, &rdata->args.context->flags))) {
rpc_exit(task, -EIO);
return;
}
if (filelayout_reset_to_mds(rdata->header->lseg)) { if (filelayout_reset_to_mds(rdata->header->lseg)) {
dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
filelayout_reset_read(rdata); filelayout_reset_read(rdata);
...@@ -407,6 +411,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) ...@@ -407,6 +411,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
{ {
struct nfs_write_data *wdata = data; struct nfs_write_data *wdata = data;
if (unlikely(test_bit(NFS_CONTEXT_BAD, &wdata->args.context->flags))) {
rpc_exit(task, -EIO);
return;
}
if (filelayout_reset_to_mds(wdata->header->lseg)) { if (filelayout_reset_to_mds(wdata->header->lseg)) {
dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
filelayout_reset_write(wdata); filelayout_reset_write(wdata);
......
...@@ -1328,9 +1328,25 @@ void nfs_inode_find_state_and_recover(struct inode *inode, ...@@ -1328,9 +1328,25 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
nfs4_schedule_state_manager(clp); nfs4_schedule_state_manager(clp);
} }
static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
{
struct inode *inode = state->inode;
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_context *ctx;
spin_lock(&inode->i_lock);
list_for_each_entry(ctx, &nfsi->open_files, list) {
if (ctx->state != state)
continue;
set_bit(NFS_CONTEXT_BAD, &ctx->flags);
}
spin_unlock(&inode->i_lock);
}
static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error) static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
{ {
set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags); set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
nfs4_state_mark_open_context_bad(state);
} }
......
...@@ -104,6 +104,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, ...@@ -104,6 +104,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
struct nfs_page *req; struct nfs_page *req;
struct nfs_lock_context *l_ctx; struct nfs_lock_context *l_ctx;
if (test_bit(NFS_CONTEXT_BAD, &ctx->flags))
return ERR_PTR(-EBADF);
/* try to allocate the request struct */ /* try to allocate the request struct */
req = nfs_page_alloc(); req = nfs_page_alloc();
if (req == NULL) if (req == NULL)
......
...@@ -514,6 +514,8 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata) ...@@ -514,6 +514,8 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata)
{ {
struct nfs_read_data *data = calldata; struct nfs_read_data *data = calldata;
NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data);
if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
rpc_exit(task, -EIO);
} }
static const struct rpc_call_ops nfs_read_common_ops = { static const struct rpc_call_ops nfs_read_common_ops = {
......
...@@ -1251,6 +1251,8 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata) ...@@ -1251,6 +1251,8 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata)
{ {
struct nfs_write_data *data = calldata; struct nfs_write_data *data = calldata;
NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data); NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data);
if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
rpc_exit(task, -EIO);
} }
void nfs_commit_prepare(struct rpc_task *task, void *calldata) void nfs_commit_prepare(struct rpc_task *task, void *calldata)
......
...@@ -77,6 +77,7 @@ struct nfs_open_context { ...@@ -77,6 +77,7 @@ struct nfs_open_context {
unsigned long flags; unsigned long flags;
#define NFS_CONTEXT_ERROR_WRITE (0) #define NFS_CONTEXT_ERROR_WRITE (0)
#define NFS_CONTEXT_RESEND_WRITES (1) #define NFS_CONTEXT_RESEND_WRITES (1)
#define NFS_CONTEXT_BAD (2)
int error; int error;
struct list_head list; struct list_head list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment