diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 30 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 |
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); | |||
427 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); | 427 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); |
428 | extern void nfs_inode_find_state_and_recover(struct inode *inode, | 428 | extern void nfs_inode_find_state_and_recover(struct inode *inode, |
429 | const nfs4_stateid *stateid); | 429 | const nfs4_stateid *stateid); |
430 | extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *, struct nfs4_state *); | ||
430 | extern void nfs4_schedule_lease_recovery(struct nfs_client *); | 431 | extern void nfs4_schedule_lease_recovery(struct nfs_client *); |
431 | extern int nfs4_wait_clnt_recover(struct nfs_client *clp); | 432 | extern int nfs4_wait_clnt_recover(struct nfs_client *clp); |
432 | extern int nfs4_client_recover_expired_lease(struct nfs_client *clp); | 433 | extern 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 | ||
1140 | static 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 | |||
1140 | static bool nfs_need_update_open_stateid(struct nfs4_state *state, | 1155 | static 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 | ||
1184 | static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) | 1203 | static 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 | ||
1324 | static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) | 1324 | int 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); |