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.c145
1 files changed, 119 insertions, 26 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index afe587d82f1e..f535c219cf3a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void)
264{ 264{
265 struct nfs4_state_owner *sp; 265 struct nfs4_state_owner *sp;
266 266
267 sp = kmalloc(sizeof(*sp),GFP_KERNEL); 267 sp = kzalloc(sizeof(*sp),GFP_KERNEL);
268 if (!sp) 268 if (!sp)
269 return NULL; 269 return NULL;
270 init_MUTEX(&sp->so_sema); 270 init_MUTEX(&sp->so_sema);
271 sp->so_seqid = 0; /* arbitrary */
272 INIT_LIST_HEAD(&sp->so_states); 271 INIT_LIST_HEAD(&sp->so_states);
273 INIT_LIST_HEAD(&sp->so_delegations); 272 INIT_LIST_HEAD(&sp->so_delegations);
273 rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
274 sp->so_seqid.sequence = &sp->so_sequence;
275 spin_lock_init(&sp->so_sequence.lock);
276 INIT_LIST_HEAD(&sp->so_sequence.list);
274 atomic_set(&sp->so_count, 1); 277 atomic_set(&sp->so_count, 1);
275 return sp; 278 return sp;
276} 279}
@@ -553,12 +556,10 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
553 struct nfs4_lock_state *lsp; 556 struct nfs4_lock_state *lsp;
554 struct nfs4_client *clp = state->owner->so_client; 557 struct nfs4_client *clp = state->owner->so_client;
555 558
556 lsp = kmalloc(sizeof(*lsp), GFP_KERNEL); 559 lsp = kzalloc(sizeof(*lsp), GFP_KERNEL);
557 if (lsp == NULL) 560 if (lsp == NULL)
558 return NULL; 561 return NULL;
559 lsp->ls_flags = 0; 562 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); 563 atomic_set(&lsp->ls_count, 1);
563 lsp->ls_owner = fl_owner; 564 lsp->ls_owner = fl_owner;
564 spin_lock(&clp->cl_lock); 565 spin_lock(&clp->cl_lock);
@@ -673,29 +674,102 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
673 nfs4_put_lock_state(lsp); 674 nfs4_put_lock_state(lsp);
674} 675}
675 676
676/* 677struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
677* Called with state->lock_sema and clp->cl_sem held. 678{
678*/ 679 struct rpc_sequence *sequence = counter->sequence;
679void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) 680 struct nfs_seqid *new;
681
682 new = kmalloc(sizeof(*new), GFP_KERNEL);
683 if (new != NULL) {
684 new->sequence = counter;
685 new->task = NULL;
686 spin_lock(&sequence->lock);
687 list_add_tail(&new->list, &sequence->list);
688 spin_unlock(&sequence->lock);
689 }
690 return new;
691}
692
693void nfs_free_seqid(struct nfs_seqid *seqid)
680{ 694{
681 if (status == NFS_OK || seqid_mutating_err(-status)) 695 struct rpc_sequence *sequence = seqid->sequence->sequence;
682 lsp->ls_seqid++; 696 struct rpc_task *next = NULL;
697
698 spin_lock(&sequence->lock);
699 list_del(&seqid->list);
700 if (!list_empty(&sequence->list)) {
701 next = list_entry(sequence->list.next, struct nfs_seqid, list)->task;
702 if (next)
703 rpc_wake_up_task(next);
704 }
705 spin_unlock(&sequence->lock);
706 kfree(seqid);
683} 707}
684 708
685/* 709/*
686* Called with sp->so_sema and clp->cl_sem held. 710 * Called with sp->so_sema and clp->cl_sem held.
687* 711 *
688* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or 712 * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
689* failed with a seqid incrementing error - 713 * failed with a seqid incrementing error -
690* see comments nfs_fs.h:seqid_mutating_error() 714 * see comments nfs_fs.h:seqid_mutating_error()
691*/ 715 */
692void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) 716static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
693{ 717{
694 if (status == NFS_OK || seqid_mutating_err(-status)) 718 switch (status) {
695 sp->so_seqid++; 719 case 0:
696 /* If the server returns BAD_SEQID, unhash state_owner here */ 720 break;
697 if (status == -NFS4ERR_BAD_SEQID) 721 case -NFS4ERR_BAD_SEQID:
722 case -NFS4ERR_STALE_CLIENTID:
723 case -NFS4ERR_STALE_STATEID:
724 case -NFS4ERR_BAD_STATEID:
725 case -NFS4ERR_BADXDR:
726 case -NFS4ERR_RESOURCE:
727 case -NFS4ERR_NOFILEHANDLE:
728 /* Non-seqid mutating errors */
729 return;
730 };
731 /*
732 * Note: no locking needed as we are guaranteed to be first
733 * on the sequence list
734 */
735 seqid->sequence->counter++;
736}
737
738void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
739{
740 if (status == -NFS4ERR_BAD_SEQID) {
741 struct nfs4_state_owner *sp = container_of(seqid->sequence,
742 struct nfs4_state_owner, so_seqid);
698 nfs4_drop_state_owner(sp); 743 nfs4_drop_state_owner(sp);
744 }
745 return nfs_increment_seqid(status, seqid);
746}
747
748/*
749 * Called with ls->lock_sema and clp->cl_sem held.
750 *
751 * Increment the seqid if the LOCK/LOCKU succeeded, or
752 * failed with a seqid incrementing error -
753 * see comments nfs_fs.h:seqid_mutating_error()
754 */
755void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
756{
757 return nfs_increment_seqid(status, seqid);
758}
759
760int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
761{
762 struct rpc_sequence *sequence = seqid->sequence->sequence;
763 int status = 0;
764
765 spin_lock(&sequence->lock);
766 if (sequence->list.next != &seqid->list) {
767 seqid->task = task;
768 rpc_sleep_on(&sequence->wait, task, NULL, NULL);
769 status = -EAGAIN;
770 }
771 spin_unlock(&sequence->lock);
772 return status;
699} 773}
700 774
701static int reclaimer(void *); 775static int reclaimer(void *);
@@ -791,8 +865,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
791 if (state->state == 0) 865 if (state->state == 0)
792 continue; 866 continue;
793 status = ops->recover_open(sp, state); 867 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) { 868 if (status >= 0) {
797 status = nfs4_reclaim_locks(ops, state); 869 status = nfs4_reclaim_locks(ops, state);
798 if (status < 0) 870 if (status < 0)
@@ -831,6 +903,26 @@ out_err:
831 return status; 903 return status;
832} 904}
833 905
906static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
907{
908 struct nfs4_state_owner *sp;
909 struct nfs4_state *state;
910 struct nfs4_lock_state *lock;
911
912 /* Reset all sequence ids to zero */
913 list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
914 sp->so_seqid.counter = 0;
915 sp->so_seqid.flags = 0;
916 list_for_each_entry(state, &sp->so_states, open_states) {
917 list_for_each_entry(lock, &state->lock_states, ls_locks) {
918 lock->ls_seqid.counter = 0;
919 lock->ls_seqid.flags = 0;
920 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
921 }
922 }
923 }
924}
925
834static int reclaimer(void *ptr) 926static int reclaimer(void *ptr)
835{ 927{
836 struct reclaimer_args *args = (struct reclaimer_args *)ptr; 928 struct reclaimer_args *args = (struct reclaimer_args *)ptr;
@@ -864,6 +956,7 @@ restart_loop:
864 default: 956 default:
865 ops = &nfs4_network_partition_recovery_ops; 957 ops = &nfs4_network_partition_recovery_ops;
866 }; 958 };
959 nfs4_state_mark_reclaim(clp);
867 status = __nfs4_init_client(clp); 960 status = __nfs4_init_client(clp);
868 if (status) 961 if (status)
869 goto out_error; 962 goto out_error;