diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 145 |
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 | /* | 677 | struct 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; |
679 | void 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 | |||
693 | void 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 | */ |
692 | void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) | 716 | static 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 | |||
738 | void 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 | */ | ||
755 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) | ||
756 | { | ||
757 | return nfs_increment_seqid(status, seqid); | ||
758 | } | ||
759 | |||
760 | int 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 | ||
701 | static int reclaimer(void *); | 775 | static 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 | ||
906 | static 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 | |||
834 | static int reclaimer(void *ptr) | 926 | static 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; |