aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-18 19:45:14 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-25 12:04:10 -0400
commitc58c844187df61ef7cc103d0abb5dd6198bcfcd6 (patch)
tree0e435c37318e290346f3bed74bba05350ec4dd2f
parent5d422301f97b821301efcdb6fc9d1a83a5c102d6 (diff)
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: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4filelayout.c8
-rw-r--r--fs/nfs/nfs4state.c16
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/write.c2
-rw-r--r--include/linux/nfs_fs.h1
6 files changed, 31 insertions, 0 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 1ee5737211d7..4ba32e23eddd 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -305,6 +305,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
305{ 305{
306 struct nfs_read_data *rdata = data; 306 struct nfs_read_data *rdata = data;
307 307
308 if (unlikely(test_bit(NFS_CONTEXT_BAD, &rdata->args.context->flags))) {
309 rpc_exit(task, -EIO);
310 return;
311 }
308 if (filelayout_reset_to_mds(rdata->header->lseg)) { 312 if (filelayout_reset_to_mds(rdata->header->lseg)) {
309 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); 313 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
310 filelayout_reset_read(rdata); 314 filelayout_reset_read(rdata);
@@ -407,6 +411,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
407{ 411{
408 struct nfs_write_data *wdata = data; 412 struct nfs_write_data *wdata = data;
409 413
414 if (unlikely(test_bit(NFS_CONTEXT_BAD, &wdata->args.context->flags))) {
415 rpc_exit(task, -EIO);
416 return;
417 }
410 if (filelayout_reset_to_mds(wdata->header->lseg)) { 418 if (filelayout_reset_to_mds(wdata->header->lseg)) {
411 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid); 419 dprintk("%s task %u reset io to MDS\n", __func__, task->tk_pid);
412 filelayout_reset_write(wdata); 420 filelayout_reset_write(wdata);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index fec1c5bb4863..8db102c7add6 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1328,9 +1328,25 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
1328 nfs4_schedule_state_manager(clp); 1328 nfs4_schedule_state_manager(clp);
1329} 1329}
1330 1330
1331static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
1332{
1333 struct inode *inode = state->inode;
1334 struct nfs_inode *nfsi = NFS_I(inode);
1335 struct nfs_open_context *ctx;
1336
1337 spin_lock(&inode->i_lock);
1338 list_for_each_entry(ctx, &nfsi->open_files, list) {
1339 if (ctx->state != state)
1340 continue;
1341 set_bit(NFS_CONTEXT_BAD, &ctx->flags);
1342 }
1343 spin_unlock(&inode->i_lock);
1344}
1345
1331static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error) 1346static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
1332{ 1347{
1333 set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags); 1348 set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
1349 nfs4_state_mark_open_context_bad(state);
1334} 1350}
1335 1351
1336 1352
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index e56e846e9d2d..7f0933086b36 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -104,6 +104,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
104 struct nfs_page *req; 104 struct nfs_page *req;
105 struct nfs_lock_context *l_ctx; 105 struct nfs_lock_context *l_ctx;
106 106
107 if (test_bit(NFS_CONTEXT_BAD, &ctx->flags))
108 return ERR_PTR(-EBADF);
107 /* try to allocate the request struct */ 109 /* try to allocate the request struct */
108 req = nfs_page_alloc(); 110 req = nfs_page_alloc();
109 if (req == NULL) 111 if (req == NULL)
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a5e5d9899d56..70a26c651f09 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -514,6 +514,8 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata)
514{ 514{
515 struct nfs_read_data *data = calldata; 515 struct nfs_read_data *data = calldata;
516 NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data); 516 NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data);
517 if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
518 rpc_exit(task, -EIO);
517} 519}
518 520
519static const struct rpc_call_ops nfs_read_common_ops = { 521static const struct rpc_call_ops nfs_read_common_ops = {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c483cc50b82e..a2c7c28049d5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1251,6 +1251,8 @@ void nfs_write_prepare(struct rpc_task *task, void *calldata)
1251{ 1251{
1252 struct nfs_write_data *data = calldata; 1252 struct nfs_write_data *data = calldata;
1253 NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data); 1253 NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data);
1254 if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
1255 rpc_exit(task, -EIO);
1254} 1256}
1255 1257
1256void nfs_commit_prepare(struct rpc_task *task, void *calldata) 1258void nfs_commit_prepare(struct rpc_task *task, void *calldata)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 1cc25682b20b..f6b1956f3c86 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -77,6 +77,7 @@ struct nfs_open_context {
77 unsigned long flags; 77 unsigned long flags;
78#define NFS_CONTEXT_ERROR_WRITE (0) 78#define NFS_CONTEXT_ERROR_WRITE (0)
79#define NFS_CONTEXT_RESEND_WRITES (1) 79#define NFS_CONTEXT_RESEND_WRITES (1)
80#define NFS_CONTEXT_BAD (2)
80 int error; 81 int error;
81 82
82 struct list_head list; 83 struct list_head list;