aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3a2af8053767..ba86ec654c2e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -385,29 +385,28 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *
385 385
386static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) 386static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
387{ 387{
388 spin_lock(&state->owner->so_lock); 388 write_seqlock(&state->seqlock);
389 spin_lock(&state->inode->i_lock);
390 nfs_set_open_stateid_locked(state, stateid, open_flags); 389 nfs_set_open_stateid_locked(state, stateid, open_flags);
391 spin_unlock(&state->inode->i_lock); 390 write_sequnlock(&state->seqlock);
392 spin_unlock(&state->owner->so_lock);
393} 391}
394 392
395static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags) 393static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
396{ 394{
397 struct inode *inode = state->inode;
398
399 open_flags &= (FMODE_READ|FMODE_WRITE); 395 open_flags &= (FMODE_READ|FMODE_WRITE);
400 /* Protect against nfs4_find_state_byowner() */ 396 /*
401 spin_lock(&state->owner->so_lock); 397 * Protect the call to nfs4_state_set_mode_locked and
402 spin_lock(&inode->i_lock); 398 * serialise the stateid update
399 */
400 write_seqlock(&state->seqlock);
403 if (deleg_stateid != NULL) { 401 if (deleg_stateid != NULL) {
404 memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data)); 402 memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
405 set_bit(NFS_DELEGATED_STATE, &state->flags); 403 set_bit(NFS_DELEGATED_STATE, &state->flags);
406 } 404 }
407 if (open_stateid != NULL) 405 if (open_stateid != NULL)
408 nfs_set_open_stateid_locked(state, open_stateid, open_flags); 406 nfs_set_open_stateid_locked(state, open_stateid, open_flags);
407 write_sequnlock(&state->seqlock);
408 spin_lock(&state->owner->so_lock);
409 update_open_stateflags(state, open_flags); 409 update_open_stateflags(state, open_flags);
410 spin_unlock(&inode->i_lock);
411 spin_unlock(&state->owner->so_lock); 410 spin_unlock(&state->owner->so_lock);
412} 411}
413 412
@@ -608,12 +607,10 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
608 */ 607 */
609 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 && 608 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
610 memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) { 609 memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
611 spin_lock(&state->owner->so_lock); 610 write_seqlock(&state->seqlock);
612 spin_lock(&state->inode->i_lock);
613 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) 611 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
614 memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)); 612 memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
615 spin_unlock(&state->inode->i_lock); 613 write_sequnlock(&state->seqlock);
616 spin_unlock(&state->owner->so_lock);
617 } 614 }
618 return 0; 615 return 0;
619} 616}
@@ -1280,7 +1277,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1280 mode = FMODE_READ|FMODE_WRITE; 1277 mode = FMODE_READ|FMODE_WRITE;
1281 clear_rd = clear_wr = clear_rdwr = 0; 1278 clear_rd = clear_wr = clear_rdwr = 0;
1282 spin_lock(&state->owner->so_lock); 1279 spin_lock(&state->owner->so_lock);
1283 spin_lock(&calldata->inode->i_lock);
1284 /* Calculate the change in open mode */ 1280 /* Calculate the change in open mode */
1285 if (state->n_rdwr == 0) { 1281 if (state->n_rdwr == 0) {
1286 if (state->n_rdonly == 0) { 1282 if (state->n_rdonly == 0) {
@@ -1294,7 +1290,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1294 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags); 1290 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
1295 } 1291 }
1296 } 1292 }
1297 spin_unlock(&calldata->inode->i_lock);
1298 spin_unlock(&state->owner->so_lock); 1293 spin_unlock(&state->owner->so_lock);
1299 if (!clear_rd && !clear_wr && !clear_rdwr) { 1294 if (!clear_rd && !clear_wr && !clear_rdwr) {
1300 /* Note: exit _without_ calling nfs4_close_done */ 1295 /* Note: exit _without_ calling nfs4_close_done */