Skip to content

Commit

Permalink
NFS: Don't accept more reads/writes if the open context recovery failed
Browse files Browse the repository at this point in the history
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: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Mar 25, 2013
1 parent 5d42230 commit c58c844
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 0 deletions.
8 changes: 8 additions & 0 deletions fs/nfs/nfs4filelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *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)) {
dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
filelayout_reset_read(rdata);
Expand Down Expand Up @@ -407,6 +411,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *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)) {
dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
filelayout_reset_write(wdata);
Expand Down
16 changes: 16 additions & 0 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1328,9 +1328,25 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
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)
{
set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
nfs4_state_mark_open_context_bad(state);
}


Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/pagelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
struct nfs_page *req;
struct nfs_lock_context *l_ctx;

if (test_bit(NFS_CONTEXT_BAD, &ctx->flags))
return ERR_PTR(-EBADF);
/* try to allocate the request struct */
req = nfs_page_alloc();
if (req == NULL)
Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_read_data *data = calldata;
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 = {
Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,8 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_write_data *data = calldata;
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)
Expand Down
1 change: 1 addition & 0 deletions include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct nfs_open_context {
unsigned long flags;
#define NFS_CONTEXT_ERROR_WRITE (0)
#define NFS_CONTEXT_RESEND_WRITES (1)
#define NFS_CONTEXT_BAD (2)
int error;

struct list_head list;
Expand Down

0 comments on commit c58c844

Please sign in to comment.