diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 27 |
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 | ||
386 | static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) | 386 | static 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 | ||
395 | static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags) | 393 | static 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 */ |