aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-14 16:57:48 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-25 12:04:10 -0400
commit5d422301f97b821301efcdb6fc9d1a83a5c102d6 (patch)
treeed7117feb89a0a804669f9f017d2ce3ef7fee10c /fs/nfs/nfs4state.c
parent3ed5e2a2c394df4e03a680842c2d07a8680f133b (diff)
NFSv4: Fail I/O if the state recovery fails irrevocably
If state recovery fails with an ESTALE or a ENOENT, then we shouldn't keep retrying. Instead, mark the stateid as being invalid and fail the I/O with an EIO error. For other operations such as POSIX and BSD file locking, truncate etc, fail with an EBADF to indicate that this file descriptor is no longer valid. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 6ace365c6334..fec1c5bb4863 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -699,6 +699,8 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
699 list_for_each_entry(state, &nfsi->open_states, inode_states) { 699 list_for_each_entry(state, &nfsi->open_states, inode_states) {
700 if (state->owner != owner) 700 if (state->owner != owner)
701 continue; 701 continue;
702 if (!nfs4_valid_open_stateid(state))
703 continue;
702 if (atomic_inc_not_zero(&state->count)) 704 if (atomic_inc_not_zero(&state->count))
703 return state; 705 return state;
704 } 706 }
@@ -1286,14 +1288,17 @@ static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_s
1286 return 1; 1288 return 1;
1287} 1289}
1288 1290
1289void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) 1291int nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state)
1290{ 1292{
1291 struct nfs_client *clp = server->nfs_client; 1293 struct nfs_client *clp = server->nfs_client;
1292 1294
1295 if (!nfs4_valid_open_stateid(state))
1296 return -EBADF;
1293 nfs4_state_mark_reclaim_nograce(clp, state); 1297 nfs4_state_mark_reclaim_nograce(clp, state);
1294 dprintk("%s: scheduling stateid recovery for server %s\n", __func__, 1298 dprintk("%s: scheduling stateid recovery for server %s\n", __func__,
1295 clp->cl_hostname); 1299 clp->cl_hostname);
1296 nfs4_schedule_state_manager(clp); 1300 nfs4_schedule_state_manager(clp);
1301 return 0;
1297} 1302}
1298EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); 1303EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery);
1299 1304
@@ -1323,6 +1328,11 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
1323 nfs4_schedule_state_manager(clp); 1328 nfs4_schedule_state_manager(clp);
1324} 1329}
1325 1330
1331static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
1332{
1333 set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
1334}
1335
1326 1336
1327static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) 1337static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
1328{ 1338{
@@ -1398,6 +1408,8 @@ restart:
1398 list_for_each_entry(state, &sp->so_states, open_states) { 1408 list_for_each_entry(state, &sp->so_states, open_states) {
1399 if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) 1409 if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
1400 continue; 1410 continue;
1411 if (!nfs4_valid_open_stateid(state))
1412 continue;
1401 if (state->state == 0) 1413 if (state->state == 0)
1402 continue; 1414 continue;
1403 atomic_inc(&state->count); 1415 atomic_inc(&state->count);
@@ -1430,10 +1442,7 @@ restart:
1430 * Open state on this file cannot be recovered 1442 * Open state on this file cannot be recovered
1431 * All we can do is revert to using the zero stateid. 1443 * All we can do is revert to using the zero stateid.
1432 */ 1444 */
1433 memset(&state->stateid, 0, 1445 nfs4_state_mark_recovery_failed(state, status);
1434 sizeof(state->stateid));
1435 /* Mark the file as being 'closed' */
1436 state->state = 0;
1437 break; 1446 break;
1438 case -NFS4ERR_ADMIN_REVOKED: 1447 case -NFS4ERR_ADMIN_REVOKED:
1439 case -NFS4ERR_STALE_STATEID: 1448 case -NFS4ERR_STALE_STATEID: