aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c30
-rw-r--r--fs/nfs/nfs4state.c2
3 files changed, 28 insertions, 5 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index df81fcc138a7..e1d1badbe53c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -427,6 +427,7 @@ extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
427extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); 427extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
428extern void nfs_inode_find_state_and_recover(struct inode *inode, 428extern void nfs_inode_find_state_and_recover(struct inode *inode,
429 const nfs4_stateid *stateid); 429 const nfs4_stateid *stateid);
430extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *, struct nfs4_state *);
430extern void nfs4_schedule_lease_recovery(struct nfs_client *); 431extern void nfs4_schedule_lease_recovery(struct nfs_client *);
431extern int nfs4_wait_clnt_recover(struct nfs_client *clp); 432extern int nfs4_wait_clnt_recover(struct nfs_client *clp);
432extern int nfs4_client_recover_expired_lease(struct nfs_client *clp); 433extern int nfs4_client_recover_expired_lease(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1f593a0bd938..2427ef4c4d63 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1137,13 +1137,30 @@ static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
1137 nfs4_state_set_mode_locked(state, state->state | fmode); 1137 nfs4_state_set_mode_locked(state, state->state | fmode);
1138} 1138}
1139 1139
1140static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
1141{
1142 struct nfs_client *clp = state->owner->so_server->nfs_client;
1143 bool need_recover = false;
1144
1145 if (test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags) && state->n_rdonly)
1146 need_recover = true;
1147 if (test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags) && state->n_wronly)
1148 need_recover = true;
1149 if (test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags) && state->n_rdwr)
1150 need_recover = true;
1151 if (need_recover)
1152 nfs4_state_mark_reclaim_nograce(clp, state);
1153}
1154
1140static bool nfs_need_update_open_stateid(struct nfs4_state *state, 1155static bool nfs_need_update_open_stateid(struct nfs4_state *state,
1141 nfs4_stateid *stateid) 1156 nfs4_stateid *stateid)
1142{ 1157{
1143 if (test_and_set_bit(NFS_OPEN_STATE, &state->flags) == 0) 1158 if (test_and_set_bit(NFS_OPEN_STATE, &state->flags) == 0)
1144 return true; 1159 return true;
1145 if (!nfs4_stateid_match_other(stateid, &state->open_stateid)) 1160 if (!nfs4_stateid_match_other(stateid, &state->open_stateid)) {
1161 nfs_test_and_clear_all_open_stateid(state);
1146 return true; 1162 return true;
1163 }
1147 if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) 1164 if (nfs4_stateid_is_newer(stateid, &state->open_stateid))
1148 return true; 1165 return true;
1149 return false; 1166 return false;
@@ -1179,6 +1196,8 @@ static void nfs_clear_open_stateid(struct nfs4_state *state, nfs4_stateid *state
1179 write_seqlock(&state->seqlock); 1196 write_seqlock(&state->seqlock);
1180 nfs_clear_open_stateid_locked(state, stateid, fmode); 1197 nfs_clear_open_stateid_locked(state, stateid, fmode);
1181 write_sequnlock(&state->seqlock); 1198 write_sequnlock(&state->seqlock);
1199 if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
1200 nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
1182} 1201}
1183 1202
1184static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) 1203static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
@@ -1255,6 +1274,8 @@ no_delegation:
1255 __update_open_stateid(state, open_stateid, NULL, fmode); 1274 __update_open_stateid(state, open_stateid, NULL, fmode);
1256 ret = 1; 1275 ret = 1;
1257 } 1276 }
1277 if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
1278 nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
1258 1279
1259 return ret; 1280 return ret;
1260} 1281}
@@ -1488,12 +1509,15 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
1488 struct nfs4_state *newstate; 1509 struct nfs4_state *newstate;
1489 int ret; 1510 int ret;
1490 1511
1512 /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
1513 clear_bit(NFS_O_RDWR_STATE, &state->flags);
1514 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1515 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1491 /* memory barrier prior to reading state->n_* */ 1516 /* memory barrier prior to reading state->n_* */
1492 clear_bit(NFS_DELEGATED_STATE, &state->flags); 1517 clear_bit(NFS_DELEGATED_STATE, &state->flags);
1493 clear_bit(NFS_OPEN_STATE, &state->flags); 1518 clear_bit(NFS_OPEN_STATE, &state->flags);
1494 smp_rmb(); 1519 smp_rmb();
1495 if (state->n_rdwr != 0) { 1520 if (state->n_rdwr != 0) {
1496 clear_bit(NFS_O_RDWR_STATE, &state->flags);
1497 ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); 1521 ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
1498 if (ret != 0) 1522 if (ret != 0)
1499 return ret; 1523 return ret;
@@ -1501,7 +1525,6 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
1501 return -ESTALE; 1525 return -ESTALE;
1502 } 1526 }
1503 if (state->n_wronly != 0) { 1527 if (state->n_wronly != 0) {
1504 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1505 ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); 1528 ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
1506 if (ret != 0) 1529 if (ret != 0)
1507 return ret; 1530 return ret;
@@ -1509,7 +1532,6 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
1509 return -ESTALE; 1532 return -ESTALE;
1510 } 1533 }
1511 if (state->n_rdonly != 0) { 1534 if (state->n_rdonly != 0) {
1512 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1513 ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); 1535 ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
1514 if (ret != 0) 1536 if (ret != 0)
1515 return ret; 1537 return ret;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e5be72518bd7..b524df9f6a74 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1321,7 +1321,7 @@ static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_st
1321 return 1; 1321 return 1;
1322} 1322}
1323 1323
1324static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) 1324int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state)
1325{ 1325{
1326 set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); 1326 set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags);
1327 clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); 1327 clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);