aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c27
-rw-r--r--fs/nfs/nfs4state.c10
3 files changed, 19 insertions, 20 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 4a1c4d80a577..dd1aa2b598ce 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -139,9 +139,11 @@ struct nfs4_state {
139 unsigned long flags; /* Do we hold any locks? */ 139 unsigned long flags; /* Do we hold any locks? */
140 spinlock_t state_lock; /* Protects the lock_states list */ 140 spinlock_t state_lock; /* Protects the lock_states list */
141 141
142 seqlock_t seqlock; /* Protects the stateid/open_stateid */
142 nfs4_stateid stateid; /* Current stateid: may be delegation */ 143 nfs4_stateid stateid; /* Current stateid: may be delegation */
143 nfs4_stateid open_stateid; /* OPEN stateid */ 144 nfs4_stateid open_stateid; /* OPEN stateid */
144 145
146 /* The following 3 fields are protected by owner->so_lock */
145 unsigned int n_rdonly; /* Number of read-only references */ 147 unsigned int n_rdonly; /* Number of read-only references */
146 unsigned int n_wronly; /* Number of write-only references */ 148 unsigned int n_wronly; /* Number of write-only references */
147 unsigned int n_rdwr; /* Number of read/write references */ 149 unsigned int n_rdwr; /* Number of read/write references */
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 */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 4fa4054cdf34..523cc2cbb5e1 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -307,6 +307,7 @@ nfs4_alloc_open_state(void)
307 atomic_set(&state->count, 1); 307 atomic_set(&state->count, 1);
308 INIT_LIST_HEAD(&state->lock_states); 308 INIT_LIST_HEAD(&state->lock_states);
309 spin_lock_init(&state->state_lock); 309 spin_lock_init(&state->state_lock);
310 seqlock_init(&state->seqlock);
310 return state; 311 return state;
311} 312}
312 313
@@ -411,7 +412,6 @@ void nfs4_put_open_state(struct nfs4_state *state)
411 */ 412 */
412void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 413void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
413{ 414{
414 struct inode *inode = state->inode;
415 struct nfs4_state_owner *owner = state->owner; 415 struct nfs4_state_owner *owner = state->owner;
416 int call_close = 0; 416 int call_close = 0;
417 int newstate; 417 int newstate;
@@ -419,7 +419,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
419 atomic_inc(&owner->so_count); 419 atomic_inc(&owner->so_count);
420 /* Protect against nfs4_find_state() */ 420 /* Protect against nfs4_find_state() */
421 spin_lock(&owner->so_lock); 421 spin_lock(&owner->so_lock);
422 spin_lock(&inode->i_lock);
423 switch (mode & (FMODE_READ | FMODE_WRITE)) { 422 switch (mode & (FMODE_READ | FMODE_WRITE)) {
424 case FMODE_READ: 423 case FMODE_READ:
425 state->n_rdonly--; 424 state->n_rdonly--;
@@ -446,7 +445,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
446 clear_bit(NFS_DELEGATED_STATE, &state->flags); 445 clear_bit(NFS_DELEGATED_STATE, &state->flags);
447 } 446 }
448 nfs4_state_set_mode_locked(state, newstate); 447 nfs4_state_set_mode_locked(state, newstate);
449 spin_unlock(&inode->i_lock);
450 spin_unlock(&owner->so_lock); 448 spin_unlock(&owner->so_lock);
451 449
452 if (!call_close) { 450 if (!call_close) {
@@ -599,8 +597,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
599void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) 597void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
600{ 598{
601 struct nfs4_lock_state *lsp; 599 struct nfs4_lock_state *lsp;
600 int seq;
602 601
603 memcpy(dst, &state->stateid, sizeof(*dst)); 602 do {
603 seq = read_seqbegin(&state->seqlock);
604 memcpy(dst, &state->stateid, sizeof(*dst));
605 } while (read_seqretry(&state->seqlock, seq));
604 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) 606 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
605 return; 607 return;
606 608