aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c94
1 files changed, 30 insertions, 64 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2d5a6a2b9dec..0675f3215e0a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server)
69void 69void
70destroy_nfsv4_state(struct nfs_server *server) 70destroy_nfsv4_state(struct nfs_server *server)
71{ 71{
72 if (server->mnt_path) { 72 kfree(server->mnt_path);
73 kfree(server->mnt_path); 73 server->mnt_path = NULL;
74 server->mnt_path = NULL;
75 }
76 if (server->nfs4_state) { 74 if (server->nfs4_state) {
77 nfs4_put_client(server->nfs4_state); 75 nfs4_put_client(server->nfs4_state);
78 server->nfs4_state = NULL; 76 server->nfs4_state = NULL;
@@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
311 new = NULL; 309 new = NULL;
312 } 310 }
313 spin_unlock(&clp->cl_lock); 311 spin_unlock(&clp->cl_lock);
314 if (new) 312 kfree(new);
315 kfree(new);
316 if (sp != NULL) 313 if (sp != NULL)
317 return sp; 314 return sp;
318 put_rpccred(cred); 315 put_rpccred(cred);
@@ -366,30 +363,21 @@ nfs4_alloc_open_state(void)
366 return state; 363 return state;
367} 364}
368 365
369static struct nfs4_state * 366void
370__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) 367nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode)
371{ 368{
372 struct nfs_inode *nfsi = NFS_I(inode); 369 if (state->state == mode)
373 struct nfs4_state *state; 370 return;
374 371 /* NB! List reordering - see the reclaim code for why. */
375 mode &= (FMODE_READ|FMODE_WRITE); 372 if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
376 list_for_each_entry(state, &nfsi->open_states, inode_states) {
377 if (state->owner->so_cred != cred)
378 continue;
379 if ((mode & FMODE_READ) != 0 && state->nreaders == 0)
380 continue;
381 if ((mode & FMODE_WRITE) != 0 && state->nwriters == 0)
382 continue;
383 if ((state->state & mode) != mode)
384 continue;
385 atomic_inc(&state->count);
386 if (mode & FMODE_READ)
387 state->nreaders++;
388 if (mode & FMODE_WRITE) 373 if (mode & FMODE_WRITE)
389 state->nwriters++; 374 list_move(&state->open_states, &state->owner->so_states);
390 return state; 375 else
376 list_move_tail(&state->open_states, &state->owner->so_states);
391 } 377 }
392 return NULL; 378 if (mode == 0)
379 list_del_init(&state->inode_states);
380 state->state = mode;
393} 381}
394 382
395static struct nfs4_state * 383static struct nfs4_state *
@@ -400,7 +388,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
400 388
401 list_for_each_entry(state, &nfsi->open_states, inode_states) { 389 list_for_each_entry(state, &nfsi->open_states, inode_states) {
402 /* Is this in the process of being freed? */ 390 /* Is this in the process of being freed? */
403 if (state->nreaders == 0 && state->nwriters == 0) 391 if (state->state == 0)
404 continue; 392 continue;
405 if (state->owner == owner) { 393 if (state->owner == owner) {
406 atomic_inc(&state->count); 394 atomic_inc(&state->count);
@@ -410,17 +398,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
410 return NULL; 398 return NULL;
411} 399}
412 400
413struct nfs4_state *
414nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
415{
416 struct nfs4_state *state;
417
418 spin_lock(&inode->i_lock);
419 state = __nfs4_find_state(inode, cred, mode);
420 spin_unlock(&inode->i_lock);
421 return state;
422}
423
424static void 401static void
425nfs4_free_open_state(struct nfs4_state *state) 402nfs4_free_open_state(struct nfs4_state *state)
426{ 403{
@@ -481,7 +458,6 @@ void nfs4_put_open_state(struct nfs4_state *state)
481 spin_unlock(&inode->i_lock); 458 spin_unlock(&inode->i_lock);
482 spin_unlock(&owner->so_lock); 459 spin_unlock(&owner->so_lock);
483 iput(inode); 460 iput(inode);
484 BUG_ON (state->state != 0);
485 nfs4_free_open_state(state); 461 nfs4_free_open_state(state);
486 nfs4_put_state_owner(owner); 462 nfs4_put_state_owner(owner);
487} 463}
@@ -493,7 +469,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
493{ 469{
494 struct inode *inode = state->inode; 470 struct inode *inode = state->inode;
495 struct nfs4_state_owner *owner = state->owner; 471 struct nfs4_state_owner *owner = state->owner;
496 int newstate; 472 int oldstate, newstate = 0;
497 473
498 atomic_inc(&owner->so_count); 474 atomic_inc(&owner->so_count);
499 /* Protect against nfs4_find_state() */ 475 /* Protect against nfs4_find_state() */
@@ -503,30 +479,20 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
503 state->nreaders--; 479 state->nreaders--;
504 if (mode & FMODE_WRITE) 480 if (mode & FMODE_WRITE)
505 state->nwriters--; 481 state->nwriters--;
506 if (state->nwriters == 0) { 482 oldstate = newstate = state->state;
507 if (state->nreaders == 0) 483 if (state->nreaders == 0)
508 list_del_init(&state->inode_states); 484 newstate &= ~FMODE_READ;
509 /* See reclaim code */ 485 if (state->nwriters == 0)
510 list_move_tail(&state->open_states, &owner->so_states); 486 newstate &= ~FMODE_WRITE;
487 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
488 nfs4_state_set_mode_locked(state, newstate);
489 oldstate = newstate;
511 } 490 }
512 spin_unlock(&inode->i_lock); 491 spin_unlock(&inode->i_lock);
513 spin_unlock(&owner->so_lock); 492 spin_unlock(&owner->so_lock);
514 newstate = 0; 493
515 if (state->state != 0) { 494 if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
516 if (state->nreaders) 495 return;
517 newstate |= FMODE_READ;
518 if (state->nwriters)
519 newstate |= FMODE_WRITE;
520 if (state->state == newstate)
521 goto out;
522 if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
523 state->state = newstate;
524 goto out;
525 }
526 if (nfs4_do_close(inode, state, newstate) == 0)
527 return;
528 }
529out:
530 nfs4_put_open_state(state); 496 nfs4_put_open_state(state);
531 nfs4_put_state_owner(owner); 497 nfs4_put_state_owner(owner);
532} 498}
@@ -815,7 +781,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
815 int status = 0; 781 int status = 0;
816 782
817 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { 783 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
818 if (!(fl->fl_flags & FL_POSIX)) 784 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
819 continue; 785 continue;
820 if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) 786 if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
821 continue; 787 continue;
@@ -830,7 +796,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
830 case -NFS4ERR_NO_GRACE: 796 case -NFS4ERR_NO_GRACE:
831 case -NFS4ERR_RECLAIM_BAD: 797 case -NFS4ERR_RECLAIM_BAD:
832 case -NFS4ERR_RECLAIM_CONFLICT: 798 case -NFS4ERR_RECLAIM_CONFLICT:
833 /* kill_proc(fl->fl_owner, SIGLOST, 1); */ 799 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
834 break; 800 break;
835 case -NFS4ERR_STALE_CLIENTID: 801 case -NFS4ERR_STALE_CLIENTID:
836 goto out_err; 802 goto out_err;