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.c265
1 files changed, 160 insertions, 105 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index afe587d82f1e..5ef4c57618fe 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;
@@ -264,13 +262,16 @@ nfs4_alloc_state_owner(void)
264{ 262{
265 struct nfs4_state_owner *sp; 263 struct nfs4_state_owner *sp;
266 264
267 sp = kmalloc(sizeof(*sp),GFP_KERNEL); 265 sp = kzalloc(sizeof(*sp),GFP_KERNEL);
268 if (!sp) 266 if (!sp)
269 return NULL; 267 return NULL;
270 init_MUTEX(&sp->so_sema); 268 spin_lock_init(&sp->so_lock);
271 sp->so_seqid = 0; /* arbitrary */
272 INIT_LIST_HEAD(&sp->so_states); 269 INIT_LIST_HEAD(&sp->so_states);
273 INIT_LIST_HEAD(&sp->so_delegations); 270 INIT_LIST_HEAD(&sp->so_delegations);
271 rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
272 sp->so_seqid.sequence = &sp->so_sequence;
273 spin_lock_init(&sp->so_sequence.lock);
274 INIT_LIST_HEAD(&sp->so_sequence.list);
274 atomic_set(&sp->so_count, 1); 275 atomic_set(&sp->so_count, 1);
275 return sp; 276 return sp;
276} 277}
@@ -308,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
308 new = NULL; 309 new = NULL;
309 } 310 }
310 spin_unlock(&clp->cl_lock); 311 spin_unlock(&clp->cl_lock);
311 if (new) 312 kfree(new);
312 kfree(new);
313 if (sp != NULL) 313 if (sp != NULL)
314 return sp; 314 return sp;
315 put_rpccred(cred); 315 put_rpccred(cred);
@@ -359,35 +359,25 @@ nfs4_alloc_open_state(void)
359 memset(state->stateid.data, 0, sizeof(state->stateid.data)); 359 memset(state->stateid.data, 0, sizeof(state->stateid.data));
360 atomic_set(&state->count, 1); 360 atomic_set(&state->count, 1);
361 INIT_LIST_HEAD(&state->lock_states); 361 INIT_LIST_HEAD(&state->lock_states);
362 init_MUTEX(&state->lock_sema);
363 spin_lock_init(&state->state_lock); 362 spin_lock_init(&state->state_lock);
364 return state; 363 return state;
365} 364}
366 365
367static struct nfs4_state * 366void
368__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)
369{ 368{
370 struct nfs_inode *nfsi = NFS_I(inode); 369 if (state->state == mode)
371 struct nfs4_state *state; 370 return;
372 371 /* NB! List reordering - see the reclaim code for why. */
373 mode &= (FMODE_READ|FMODE_WRITE); 372 if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
374 list_for_each_entry(state, &nfsi->open_states, inode_states) {
375 if (state->owner->so_cred != cred)
376 continue;
377 if ((mode & FMODE_READ) != 0 && state->nreaders == 0)
378 continue;
379 if ((mode & FMODE_WRITE) != 0 && state->nwriters == 0)
380 continue;
381 if ((state->state & mode) != mode)
382 continue;
383 atomic_inc(&state->count);
384 if (mode & FMODE_READ)
385 state->nreaders++;
386 if (mode & FMODE_WRITE) 373 if (mode & FMODE_WRITE)
387 state->nwriters++; 374 list_move(&state->open_states, &state->owner->so_states);
388 return state; 375 else
376 list_move_tail(&state->open_states, &state->owner->so_states);
389 } 377 }
390 return NULL; 378 if (mode == 0)
379 list_del_init(&state->inode_states);
380 state->state = mode;
391} 381}
392 382
393static struct nfs4_state * 383static struct nfs4_state *
@@ -398,7 +388,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
398 388
399 list_for_each_entry(state, &nfsi->open_states, inode_states) { 389 list_for_each_entry(state, &nfsi->open_states, inode_states) {
400 /* Is this in the process of being freed? */ 390 /* Is this in the process of being freed? */
401 if (state->nreaders == 0 && state->nwriters == 0) 391 if (state->state == 0)
402 continue; 392 continue;
403 if (state->owner == owner) { 393 if (state->owner == owner) {
404 atomic_inc(&state->count); 394 atomic_inc(&state->count);
@@ -408,17 +398,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
408 return NULL; 398 return NULL;
409} 399}
410 400
411struct nfs4_state *
412nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
413{
414 struct nfs4_state *state;
415
416 spin_lock(&inode->i_lock);
417 state = __nfs4_find_state(inode, cred, mode);
418 spin_unlock(&inode->i_lock);
419 return state;
420}
421
422static void 401static void
423nfs4_free_open_state(struct nfs4_state *state) 402nfs4_free_open_state(struct nfs4_state *state)
424{ 403{
@@ -437,21 +416,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
437 if (state) 416 if (state)
438 goto out; 417 goto out;
439 new = nfs4_alloc_open_state(); 418 new = nfs4_alloc_open_state();
419 spin_lock(&owner->so_lock);
440 spin_lock(&inode->i_lock); 420 spin_lock(&inode->i_lock);
441 state = __nfs4_find_state_byowner(inode, owner); 421 state = __nfs4_find_state_byowner(inode, owner);
442 if (state == NULL && new != NULL) { 422 if (state == NULL && new != NULL) {
443 state = new; 423 state = new;
444 /* Caller *must* be holding owner->so_sem */
445 /* Note: The reclaim code dictates that we add stateless
446 * and read-only stateids to the end of the list */
447 list_add_tail(&state->open_states, &owner->so_states);
448 state->owner = owner; 424 state->owner = owner;
449 atomic_inc(&owner->so_count); 425 atomic_inc(&owner->so_count);
450 list_add(&state->inode_states, &nfsi->open_states); 426 list_add(&state->inode_states, &nfsi->open_states);
451 state->inode = igrab(inode); 427 state->inode = igrab(inode);
452 spin_unlock(&inode->i_lock); 428 spin_unlock(&inode->i_lock);
429 /* Note: The reclaim code dictates that we add stateless
430 * and read-only stateids to the end of the list */
431 list_add_tail(&state->open_states, &owner->so_states);
432 spin_unlock(&owner->so_lock);
453 } else { 433 } else {
454 spin_unlock(&inode->i_lock); 434 spin_unlock(&inode->i_lock);
435 spin_unlock(&owner->so_lock);
455 if (new) 436 if (new)
456 nfs4_free_open_state(new); 437 nfs4_free_open_state(new);
457 } 438 }
@@ -461,68 +442,59 @@ out:
461 442
462/* 443/*
463 * Beware! Caller must be holding exactly one 444 * Beware! Caller must be holding exactly one
464 * reference to clp->cl_sem and owner->so_sema! 445 * reference to clp->cl_sem!
465 */ 446 */
466void nfs4_put_open_state(struct nfs4_state *state) 447void nfs4_put_open_state(struct nfs4_state *state)
467{ 448{
468 struct inode *inode = state->inode; 449 struct inode *inode = state->inode;
469 struct nfs4_state_owner *owner = state->owner; 450 struct nfs4_state_owner *owner = state->owner;
470 451
471 if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) 452 if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
472 return; 453 return;
454 spin_lock(&inode->i_lock);
473 if (!list_empty(&state->inode_states)) 455 if (!list_empty(&state->inode_states))
474 list_del(&state->inode_states); 456 list_del(&state->inode_states);
475 spin_unlock(&inode->i_lock);
476 list_del(&state->open_states); 457 list_del(&state->open_states);
458 spin_unlock(&inode->i_lock);
459 spin_unlock(&owner->so_lock);
477 iput(inode); 460 iput(inode);
478 BUG_ON (state->state != 0);
479 nfs4_free_open_state(state); 461 nfs4_free_open_state(state);
480 nfs4_put_state_owner(owner); 462 nfs4_put_state_owner(owner);
481} 463}
482 464
483/* 465/*
484 * Beware! Caller must be holding no references to clp->cl_sem! 466 * Close the current file.
485 * of owner->so_sema!
486 */ 467 */
487void nfs4_close_state(struct nfs4_state *state, mode_t mode) 468void nfs4_close_state(struct nfs4_state *state, mode_t mode)
488{ 469{
489 struct inode *inode = state->inode; 470 struct inode *inode = state->inode;
490 struct nfs4_state_owner *owner = state->owner; 471 struct nfs4_state_owner *owner = state->owner;
491 struct nfs4_client *clp = owner->so_client; 472 int oldstate, newstate = 0;
492 int newstate;
493 473
494 atomic_inc(&owner->so_count); 474 atomic_inc(&owner->so_count);
495 down_read(&clp->cl_sem);
496 down(&owner->so_sema);
497 /* Protect against nfs4_find_state() */ 475 /* Protect against nfs4_find_state() */
476 spin_lock(&owner->so_lock);
498 spin_lock(&inode->i_lock); 477 spin_lock(&inode->i_lock);
499 if (mode & FMODE_READ) 478 if (mode & FMODE_READ)
500 state->nreaders--; 479 state->nreaders--;
501 if (mode & FMODE_WRITE) 480 if (mode & FMODE_WRITE)
502 state->nwriters--; 481 state->nwriters--;
503 if (state->nwriters == 0) { 482 oldstate = newstate = state->state;
504 if (state->nreaders == 0) 483 if (state->nreaders == 0)
505 list_del_init(&state->inode_states); 484 newstate &= ~FMODE_READ;
506 /* See reclaim code */ 485 if (state->nwriters == 0)
507 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;
508 } 490 }
509 spin_unlock(&inode->i_lock); 491 spin_unlock(&inode->i_lock);
510 newstate = 0; 492 spin_unlock(&owner->so_lock);
511 if (state->state != 0) { 493
512 if (state->nreaders) 494 if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
513 newstate |= FMODE_READ; 495 return;
514 if (state->nwriters)
515 newstate |= FMODE_WRITE;
516 if (state->state == newstate)
517 goto out;
518 if (nfs4_do_close(inode, state, newstate) == -EINPROGRESS)
519 return;
520 }
521out:
522 nfs4_put_open_state(state); 496 nfs4_put_open_state(state);
523 up(&owner->so_sema);
524 nfs4_put_state_owner(owner); 497 nfs4_put_state_owner(owner);
525 up_read(&clp->cl_sem);
526} 498}
527 499
528/* 500/*
@@ -546,19 +518,16 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
546 * Return a compatible lock_state. If no initialized lock_state structure 518 * Return a compatible lock_state. If no initialized lock_state structure
547 * exists, return an uninitialized one. 519 * exists, return an uninitialized one.
548 * 520 *
549 * The caller must be holding state->lock_sema
550 */ 521 */
551static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) 522static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
552{ 523{
553 struct nfs4_lock_state *lsp; 524 struct nfs4_lock_state *lsp;
554 struct nfs4_client *clp = state->owner->so_client; 525 struct nfs4_client *clp = state->owner->so_client;
555 526
556 lsp = kmalloc(sizeof(*lsp), GFP_KERNEL); 527 lsp = kzalloc(sizeof(*lsp), GFP_KERNEL);
557 if (lsp == NULL) 528 if (lsp == NULL)
558 return NULL; 529 return NULL;
559 lsp->ls_flags = 0; 530 lsp->ls_seqid.sequence = &state->owner->so_sequence;
560 lsp->ls_seqid = 0; /* arbitrary */
561 memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
562 atomic_set(&lsp->ls_count, 1); 531 atomic_set(&lsp->ls_count, 1);
563 lsp->ls_owner = fl_owner; 532 lsp->ls_owner = fl_owner;
564 spin_lock(&clp->cl_lock); 533 spin_lock(&clp->cl_lock);
@@ -572,7 +541,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
572 * Return a compatible lock_state. If no initialized lock_state structure 541 * Return a compatible lock_state. If no initialized lock_state structure
573 * exists, return an uninitialized one. 542 * exists, return an uninitialized one.
574 * 543 *
575 * The caller must be holding state->lock_sema and clp->cl_sem 544 * The caller must be holding clp->cl_sem
576 */ 545 */
577static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) 546static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
578{ 547{
@@ -605,7 +574,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
605 * Release reference to lock_state, and free it if we see that 574 * Release reference to lock_state, and free it if we see that
606 * it is no longer in use 575 * it is no longer in use
607 */ 576 */
608static void nfs4_put_lock_state(struct nfs4_lock_state *lsp) 577void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
609{ 578{
610 struct nfs4_state *state; 579 struct nfs4_state *state;
611 580
@@ -673,29 +642,94 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
673 nfs4_put_lock_state(lsp); 642 nfs4_put_lock_state(lsp);
674} 643}
675 644
676/* 645struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
677* Called with state->lock_sema and clp->cl_sem held. 646{
678*/ 647 struct rpc_sequence *sequence = counter->sequence;
679void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) 648 struct nfs_seqid *new;
649
650 new = kmalloc(sizeof(*new), GFP_KERNEL);
651 if (new != NULL) {
652 new->sequence = counter;
653 spin_lock(&sequence->lock);
654 list_add_tail(&new->list, &sequence->list);
655 spin_unlock(&sequence->lock);
656 }
657 return new;
658}
659
660void nfs_free_seqid(struct nfs_seqid *seqid)
680{ 661{
681 if (status == NFS_OK || seqid_mutating_err(-status)) 662 struct rpc_sequence *sequence = seqid->sequence->sequence;
682 lsp->ls_seqid++; 663
664 spin_lock(&sequence->lock);
665 list_del(&seqid->list);
666 spin_unlock(&sequence->lock);
667 rpc_wake_up(&sequence->wait);
668 kfree(seqid);
683} 669}
684 670
685/* 671/*
686* Called with sp->so_sema and clp->cl_sem held. 672 * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
687* 673 * failed with a seqid incrementing error -
688* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or 674 * see comments nfs_fs.h:seqid_mutating_error()
689* failed with a seqid incrementing error - 675 */
690* see comments nfs_fs.h:seqid_mutating_error() 676static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
691*/ 677{
692void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) 678 switch (status) {
693{ 679 case 0:
694 if (status == NFS_OK || seqid_mutating_err(-status)) 680 break;
695 sp->so_seqid++; 681 case -NFS4ERR_BAD_SEQID:
696 /* If the server returns BAD_SEQID, unhash state_owner here */ 682 case -NFS4ERR_STALE_CLIENTID:
697 if (status == -NFS4ERR_BAD_SEQID) 683 case -NFS4ERR_STALE_STATEID:
684 case -NFS4ERR_BAD_STATEID:
685 case -NFS4ERR_BADXDR:
686 case -NFS4ERR_RESOURCE:
687 case -NFS4ERR_NOFILEHANDLE:
688 /* Non-seqid mutating errors */
689 return;
690 };
691 /*
692 * Note: no locking needed as we are guaranteed to be first
693 * on the sequence list
694 */
695 seqid->sequence->counter++;
696}
697
698void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
699{
700 if (status == -NFS4ERR_BAD_SEQID) {
701 struct nfs4_state_owner *sp = container_of(seqid->sequence,
702 struct nfs4_state_owner, so_seqid);
698 nfs4_drop_state_owner(sp); 703 nfs4_drop_state_owner(sp);
704 }
705 return nfs_increment_seqid(status, seqid);
706}
707
708/*
709 * Increment the seqid if the LOCK/LOCKU succeeded, or
710 * failed with a seqid incrementing error -
711 * see comments nfs_fs.h:seqid_mutating_error()
712 */
713void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
714{
715 return nfs_increment_seqid(status, seqid);
716}
717
718int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
719{
720 struct rpc_sequence *sequence = seqid->sequence->sequence;
721 int status = 0;
722
723 if (sequence->list.next == &seqid->list)
724 goto out;
725 spin_lock(&sequence->lock);
726 if (sequence->list.next != &seqid->list) {
727 rpc_sleep_on(&sequence->wait, task, NULL, NULL);
728 status = -EAGAIN;
729 }
730 spin_unlock(&sequence->lock);
731out:
732 return status;
699} 733}
700 734
701static int reclaimer(void *); 735static int reclaimer(void *);
@@ -747,7 +781,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
747 int status = 0; 781 int status = 0;
748 782
749 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { 783 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
750 if (!(fl->fl_flags & FL_POSIX)) 784 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
751 continue; 785 continue;
752 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)
753 continue; 787 continue;
@@ -762,7 +796,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
762 case -NFS4ERR_NO_GRACE: 796 case -NFS4ERR_NO_GRACE:
763 case -NFS4ERR_RECLAIM_BAD: 797 case -NFS4ERR_RECLAIM_BAD:
764 case -NFS4ERR_RECLAIM_CONFLICT: 798 case -NFS4ERR_RECLAIM_CONFLICT:
765 /* kill_proc(fl->fl_owner, SIGLOST, 1); */ 799 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
766 break; 800 break;
767 case -NFS4ERR_STALE_CLIENTID: 801 case -NFS4ERR_STALE_CLIENTID:
768 goto out_err; 802 goto out_err;
@@ -791,8 +825,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
791 if (state->state == 0) 825 if (state->state == 0)
792 continue; 826 continue;
793 status = ops->recover_open(sp, state); 827 status = ops->recover_open(sp, state);
794 list_for_each_entry(lock, &state->lock_states, ls_locks)
795 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
796 if (status >= 0) { 828 if (status >= 0) {
797 status = nfs4_reclaim_locks(ops, state); 829 status = nfs4_reclaim_locks(ops, state);
798 if (status < 0) 830 if (status < 0)
@@ -831,6 +863,28 @@ out_err:
831 return status; 863 return status;
832} 864}
833 865
866static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
867{
868 struct nfs4_state_owner *sp;
869 struct nfs4_state *state;
870 struct nfs4_lock_state *lock;
871
872 /* Reset all sequence ids to zero */
873 list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
874 sp->so_seqid.counter = 0;
875 sp->so_seqid.flags = 0;
876 spin_lock(&sp->so_lock);
877 list_for_each_entry(state, &sp->so_states, open_states) {
878 list_for_each_entry(lock, &state->lock_states, ls_locks) {
879 lock->ls_seqid.counter = 0;
880 lock->ls_seqid.flags = 0;
881 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
882 }
883 }
884 spin_unlock(&sp->so_lock);
885 }
886}
887
834static int reclaimer(void *ptr) 888static int reclaimer(void *ptr)
835{ 889{
836 struct reclaimer_args *args = (struct reclaimer_args *)ptr; 890 struct reclaimer_args *args = (struct reclaimer_args *)ptr;
@@ -864,6 +918,7 @@ restart_loop:
864 default: 918 default:
865 ops = &nfs4_network_partition_recovery_ops; 919 ops = &nfs4_network_partition_recovery_ops;
866 }; 920 };
921 nfs4_state_mark_reclaim(clp);
867 status = __nfs4_init_client(clp); 922 status = __nfs4_init_client(clp);
868 if (status) 923 if (status)
869 goto out_error; 924 goto out_error;