aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-02-11 10:41:07 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-02-19 21:21:07 -0500
commit226056c5c312b3dac16ff6d4f40208f95c070b6a (patch)
tree0c1869e6f68abffd43dbef69fa62673373fc27df /fs/nfs/nfs4proc.c
parent78096ccac561ce2d89fbff1d1aa451bf4090a1a2 (diff)
NFSv4: Use correct locking when updating nfs4_state in nfs4_close_done
The stateid and state->flags should be updated atomically under protection of the state->seqlock. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 96e0bd42f38c..1f593a0bd938 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1149,6 +1149,38 @@ static bool nfs_need_update_open_stateid(struct nfs4_state *state,
1149 return false; 1149 return false;
1150} 1150}
1151 1151
1152static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
1153 nfs4_stateid *stateid, fmode_t fmode)
1154{
1155 clear_bit(NFS_O_RDWR_STATE, &state->flags);
1156 switch (fmode & (FMODE_READ|FMODE_WRITE)) {
1157 case FMODE_WRITE:
1158 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1159 break;
1160 case FMODE_READ:
1161 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1162 break;
1163 case 0:
1164 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1165 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1166 clear_bit(NFS_OPEN_STATE, &state->flags);
1167 }
1168 if (stateid == NULL)
1169 return;
1170 if (!nfs_need_update_open_stateid(state, stateid))
1171 return;
1172 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1173 nfs4_stateid_copy(&state->stateid, stateid);
1174 nfs4_stateid_copy(&state->open_stateid, stateid);
1175}
1176
1177static void nfs_clear_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
1178{
1179 write_seqlock(&state->seqlock);
1180 nfs_clear_open_stateid_locked(state, stateid, fmode);
1181 write_sequnlock(&state->seqlock);
1182}
1183
1152static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) 1184static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
1153{ 1185{
1154 switch (fmode) { 1186 switch (fmode) {
@@ -1168,13 +1200,6 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *
1168 nfs4_stateid_copy(&state->open_stateid, stateid); 1200 nfs4_stateid_copy(&state->open_stateid, stateid);
1169} 1201}
1170 1202
1171static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
1172{
1173 write_seqlock(&state->seqlock);
1174 nfs_set_open_stateid_locked(state, stateid, fmode);
1175 write_sequnlock(&state->seqlock);
1176}
1177
1178static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, fmode_t fmode) 1203static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, fmode_t fmode)
1179{ 1204{
1180 /* 1205 /*
@@ -2489,26 +2514,6 @@ static void nfs4_free_closedata(void *data)
2489 kfree(calldata); 2514 kfree(calldata);
2490} 2515}
2491 2516
2492static void nfs4_close_clear_stateid_flags(struct nfs4_state *state,
2493 fmode_t fmode)
2494{
2495 spin_lock(&state->owner->so_lock);
2496 clear_bit(NFS_O_RDWR_STATE, &state->flags);
2497 switch (fmode & (FMODE_READ|FMODE_WRITE)) {
2498 case FMODE_WRITE:
2499 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
2500 break;
2501 case FMODE_READ:
2502 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
2503 break;
2504 case 0:
2505 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
2506 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
2507 clear_bit(NFS_OPEN_STATE, &state->flags);
2508 }
2509 spin_unlock(&state->owner->so_lock);
2510}
2511
2512static void nfs4_close_done(struct rpc_task *task, void *data) 2517static void nfs4_close_done(struct rpc_task *task, void *data)
2513{ 2518{
2514 struct nfs4_closedata *calldata = data; 2519 struct nfs4_closedata *calldata = data;
@@ -2527,9 +2532,9 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
2527 if (calldata->roc) 2532 if (calldata->roc)
2528 pnfs_roc_set_barrier(state->inode, 2533 pnfs_roc_set_barrier(state->inode,
2529 calldata->roc_barrier); 2534 calldata->roc_barrier);
2530 nfs_set_open_stateid(state, &calldata->res.stateid, 0); 2535 nfs_clear_open_stateid(state, &calldata->res.stateid, 0);
2531 renew_lease(server, calldata->timestamp); 2536 renew_lease(server, calldata->timestamp);
2532 break; 2537 goto out_release;
2533 case -NFS4ERR_ADMIN_REVOKED: 2538 case -NFS4ERR_ADMIN_REVOKED:
2534 case -NFS4ERR_STALE_STATEID: 2539 case -NFS4ERR_STALE_STATEID:
2535 case -NFS4ERR_OLD_STATEID: 2540 case -NFS4ERR_OLD_STATEID:
@@ -2543,7 +2548,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
2543 goto out_release; 2548 goto out_release;
2544 } 2549 }
2545 } 2550 }
2546 nfs4_close_clear_stateid_flags(state, calldata->arg.fmode); 2551 nfs_clear_open_stateid(state, NULL, calldata->arg.fmode);
2547out_release: 2552out_release:
2548 nfs_release_seqid(calldata->arg.seqid); 2553 nfs_release_seqid(calldata->arg.seqid);
2549 nfs_refresh_inode(calldata->inode, calldata->res.fattr); 2554 nfs_refresh_inode(calldata->inode, calldata->res.fattr);