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.c415
1 files changed, 294 insertions, 121 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 401ef8b28f97..2022fe47966f 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -71,14 +71,12 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
71 return status; 71 return status;
72} 72}
73 73
74static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp) 74static struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp)
75{ 75{
76 struct rpc_cred *cred = NULL; 76 struct rpc_cred *cred = NULL;
77 77
78 spin_lock(&clp->cl_lock);
79 if (clp->cl_machine_cred != NULL) 78 if (clp->cl_machine_cred != NULL)
80 cred = get_rpccred(clp->cl_machine_cred); 79 cred = get_rpccred(clp->cl_machine_cred);
81 spin_unlock(&clp->cl_lock);
82 return cred; 80 return cred;
83} 81}
84 82
@@ -94,7 +92,7 @@ static void nfs4_clear_machine_cred(struct nfs_client *clp)
94 put_rpccred(cred); 92 put_rpccred(cred);
95} 93}
96 94
97struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) 95struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
98{ 96{
99 struct nfs4_state_owner *sp; 97 struct nfs4_state_owner *sp;
100 struct rb_node *pos; 98 struct rb_node *pos;
@@ -110,13 +108,24 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
110 return cred; 108 return cred;
111} 109}
112 110
111static struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
112{
113 struct rpc_cred *cred;
114
115 spin_lock(&clp->cl_lock);
116 cred = nfs4_get_renew_cred_locked(clp);
117 spin_unlock(&clp->cl_lock);
118 return cred;
119}
120
113static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) 121static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
114{ 122{
115 struct nfs4_state_owner *sp; 123 struct nfs4_state_owner *sp;
116 struct rb_node *pos; 124 struct rb_node *pos;
117 struct rpc_cred *cred; 125 struct rpc_cred *cred;
118 126
119 cred = nfs4_get_machine_cred(clp); 127 spin_lock(&clp->cl_lock);
128 cred = nfs4_get_machine_cred_locked(clp);
120 if (cred != NULL) 129 if (cred != NULL)
121 goto out; 130 goto out;
122 pos = rb_first(&clp->cl_state_owners); 131 pos = rb_first(&clp->cl_state_owners);
@@ -125,6 +134,7 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
125 cred = get_rpccred(sp->so_cred); 134 cred = get_rpccred(sp->so_cred);
126 } 135 }
127out: 136out:
137 spin_unlock(&clp->cl_lock);
128 return cred; 138 return cred;
129} 139}
130 140
@@ -295,10 +305,6 @@ nfs4_drop_state_owner(struct nfs4_state_owner *sp)
295 } 305 }
296} 306}
297 307
298/*
299 * Note: must be called with clp->cl_sem held in order to prevent races
300 * with reboot recovery!
301 */
302struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) 308struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
303{ 309{
304 struct nfs_client *clp = server->nfs_client; 310 struct nfs_client *clp = server->nfs_client;
@@ -327,10 +333,6 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
327 return sp; 333 return sp;
328} 334}
329 335
330/*
331 * Must be called with clp->cl_sem held in order to avoid races
332 * with state recovery...
333 */
334void nfs4_put_state_owner(struct nfs4_state_owner *sp) 336void nfs4_put_state_owner(struct nfs4_state_owner *sp)
335{ 337{
336 struct nfs_client *clp = sp->so_client; 338 struct nfs_client *clp = sp->so_client;
@@ -361,18 +363,18 @@ nfs4_alloc_open_state(void)
361} 363}
362 364
363void 365void
364nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode) 366nfs4_state_set_mode_locked(struct nfs4_state *state, fmode_t fmode)
365{ 367{
366 if (state->state == mode) 368 if (state->state == fmode)
367 return; 369 return;
368 /* NB! List reordering - see the reclaim code for why. */ 370 /* NB! List reordering - see the reclaim code for why. */
369 if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) { 371 if ((fmode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
370 if (mode & FMODE_WRITE) 372 if (fmode & FMODE_WRITE)
371 list_move(&state->open_states, &state->owner->so_states); 373 list_move(&state->open_states, &state->owner->so_states);
372 else 374 else
373 list_move_tail(&state->open_states, &state->owner->so_states); 375 list_move_tail(&state->open_states, &state->owner->so_states);
374 } 376 }
375 state->state = mode; 377 state->state = fmode;
376} 378}
377 379
378static struct nfs4_state * 380static struct nfs4_state *
@@ -432,10 +434,6 @@ out:
432 return state; 434 return state;
433} 435}
434 436
435/*
436 * Beware! Caller must be holding exactly one
437 * reference to clp->cl_sem!
438 */
439void nfs4_put_open_state(struct nfs4_state *state) 437void nfs4_put_open_state(struct nfs4_state *state)
440{ 438{
441 struct inode *inode = state->inode; 439 struct inode *inode = state->inode;
@@ -456,16 +454,16 @@ void nfs4_put_open_state(struct nfs4_state *state)
456/* 454/*
457 * Close the current file. 455 * Close the current file.
458 */ 456 */
459static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait) 457static void __nfs4_close(struct path *path, struct nfs4_state *state, fmode_t fmode, int wait)
460{ 458{
461 struct nfs4_state_owner *owner = state->owner; 459 struct nfs4_state_owner *owner = state->owner;
462 int call_close = 0; 460 int call_close = 0;
463 int newstate; 461 fmode_t newstate;
464 462
465 atomic_inc(&owner->so_count); 463 atomic_inc(&owner->so_count);
466 /* Protect against nfs4_find_state() */ 464 /* Protect against nfs4_find_state() */
467 spin_lock(&owner->so_lock); 465 spin_lock(&owner->so_lock);
468 switch (mode & (FMODE_READ | FMODE_WRITE)) { 466 switch (fmode & (FMODE_READ | FMODE_WRITE)) {
469 case FMODE_READ: 467 case FMODE_READ:
470 state->n_rdonly--; 468 state->n_rdonly--;
471 break; 469 break;
@@ -500,14 +498,14 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mod
500 nfs4_do_close(path, state, wait); 498 nfs4_do_close(path, state, wait);
501} 499}
502 500
503void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 501void nfs4_close_state(struct path *path, struct nfs4_state *state, fmode_t fmode)
504{ 502{
505 __nfs4_close(path, state, mode, 0); 503 __nfs4_close(path, state, fmode, 0);
506} 504}
507 505
508void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode) 506void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
509{ 507{
510 __nfs4_close(path, state, mode, 1); 508 __nfs4_close(path, state, fmode, 1);
511} 509}
512 510
513/* 511/*
@@ -568,7 +566,6 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
568 * Return a compatible lock_state. If no initialized lock_state structure 566 * Return a compatible lock_state. If no initialized lock_state structure
569 * exists, return an uninitialized one. 567 * exists, return an uninitialized one.
570 * 568 *
571 * The caller must be holding clp->cl_sem
572 */ 569 */
573static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) 570static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
574{ 571{
@@ -770,32 +767,34 @@ unlock:
770 return status; 767 return status;
771} 768}
772 769
773static int reclaimer(void *); 770static int nfs4_run_state_manager(void *);
774 771
775static inline void nfs4_clear_recover_bit(struct nfs_client *clp) 772static void nfs4_clear_state_manager_bit(struct nfs_client *clp)
776{ 773{
777 smp_mb__before_clear_bit(); 774 smp_mb__before_clear_bit();
778 clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); 775 clear_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
779 smp_mb__after_clear_bit(); 776 smp_mb__after_clear_bit();
780 wake_up_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER); 777 wake_up_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING);
781 rpc_wake_up(&clp->cl_rpcwaitq); 778 rpc_wake_up(&clp->cl_rpcwaitq);
782} 779}
783 780
784/* 781/*
785 * State recovery routine 782 * Schedule the nfs_client asynchronous state management routine
786 */ 783 */
787static void nfs4_recover_state(struct nfs_client *clp) 784void nfs4_schedule_state_manager(struct nfs_client *clp)
788{ 785{
789 struct task_struct *task; 786 struct task_struct *task;
790 787
788 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
789 return;
791 __module_get(THIS_MODULE); 790 __module_get(THIS_MODULE);
792 atomic_inc(&clp->cl_count); 791 atomic_inc(&clp->cl_count);
793 task = kthread_run(reclaimer, clp, "%s-reclaim", 792 task = kthread_run(nfs4_run_state_manager, clp, "%s-manager",
794 rpc_peeraddr2str(clp->cl_rpcclient, 793 rpc_peeraddr2str(clp->cl_rpcclient,
795 RPC_DISPLAY_ADDR)); 794 RPC_DISPLAY_ADDR));
796 if (!IS_ERR(task)) 795 if (!IS_ERR(task))
797 return; 796 return;
798 nfs4_clear_recover_bit(clp); 797 nfs4_clear_state_manager_bit(clp);
799 nfs_put_client(clp); 798 nfs_put_client(clp);
800 module_put(THIS_MODULE); 799 module_put(THIS_MODULE);
801} 800}
@@ -807,16 +806,42 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
807{ 806{
808 if (!clp) 807 if (!clp)
809 return; 808 return;
810 if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) 809 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
811 nfs4_recover_state(clp); 810 set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
811 nfs4_schedule_state_manager(clp);
812} 812}
813 813
814static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state) 814static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
815{
816
817 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
818 /* Don't recover state that expired before the reboot */
819 if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) {
820 clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
821 return 0;
822 }
823 set_bit(NFS_OWNER_RECLAIM_REBOOT, &state->owner->so_flags);
824 set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
825 return 1;
826}
827
828int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state)
829{
830 set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags);
831 clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
832 set_bit(NFS_OWNER_RECLAIM_NOGRACE, &state->owner->so_flags);
833 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
834 return 1;
835}
836
837static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
815{ 838{
816 struct inode *inode = state->inode; 839 struct inode *inode = state->inode;
840 struct nfs_inode *nfsi = NFS_I(inode);
817 struct file_lock *fl; 841 struct file_lock *fl;
818 int status = 0; 842 int status = 0;
819 843
844 down_write(&nfsi->rwsem);
820 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 845 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
821 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 846 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
822 continue; 847 continue;
@@ -839,12 +864,14 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
839 goto out_err; 864 goto out_err;
840 } 865 }
841 } 866 }
867 up_write(&nfsi->rwsem);
842 return 0; 868 return 0;
843out_err: 869out_err:
870 up_write(&nfsi->rwsem);
844 return status; 871 return status;
845} 872}
846 873
847static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct nfs4_state_owner *sp) 874static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops)
848{ 875{
849 struct nfs4_state *state; 876 struct nfs4_state *state;
850 struct nfs4_lock_state *lock; 877 struct nfs4_lock_state *lock;
@@ -858,28 +885,34 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
858 * recovering after a network partition or a reboot from a 885 * recovering after a network partition or a reboot from a
859 * server that doesn't support a grace period. 886 * server that doesn't support a grace period.
860 */ 887 */
888restart:
889 spin_lock(&sp->so_lock);
861 list_for_each_entry(state, &sp->so_states, open_states) { 890 list_for_each_entry(state, &sp->so_states, open_states) {
891 if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
892 continue;
862 if (state->state == 0) 893 if (state->state == 0)
863 continue; 894 continue;
895 atomic_inc(&state->count);
896 spin_unlock(&sp->so_lock);
864 status = ops->recover_open(sp, state); 897 status = ops->recover_open(sp, state);
865 if (status >= 0) { 898 if (status >= 0) {
866 status = nfs4_reclaim_locks(ops, state); 899 status = nfs4_reclaim_locks(state, ops);
867 if (status < 0) 900 if (status >= 0) {
868 goto out_err; 901 list_for_each_entry(lock, &state->lock_states, ls_locks) {
869 list_for_each_entry(lock, &state->lock_states, ls_locks) { 902 if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))
870 if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) 903 printk("%s: Lock reclaim failed!\n",
871 printk("%s: Lock reclaim failed!\n",
872 __func__); 904 __func__);
905 }
906 nfs4_put_open_state(state);
907 goto restart;
873 } 908 }
874 continue;
875 } 909 }
876 switch (status) { 910 switch (status) {
877 default: 911 default:
878 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", 912 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
879 __func__, status); 913 __func__, status);
880 case -ENOENT: 914 case -ENOENT:
881 case -NFS4ERR_RECLAIM_BAD: 915 case -ESTALE:
882 case -NFS4ERR_RECLAIM_CONFLICT:
883 /* 916 /*
884 * Open state on this file cannot be recovered 917 * Open state on this file cannot be recovered
885 * All we can do is revert to using the zero stateid. 918 * All we can do is revert to using the zero stateid.
@@ -889,84 +922,176 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
889 /* Mark the file as being 'closed' */ 922 /* Mark the file as being 'closed' */
890 state->state = 0; 923 state->state = 0;
891 break; 924 break;
925 case -NFS4ERR_RECLAIM_BAD:
926 case -NFS4ERR_RECLAIM_CONFLICT:
927 nfs4_state_mark_reclaim_nograce(sp->so_client, state);
928 break;
892 case -NFS4ERR_EXPIRED: 929 case -NFS4ERR_EXPIRED:
893 case -NFS4ERR_NO_GRACE: 930 case -NFS4ERR_NO_GRACE:
931 nfs4_state_mark_reclaim_nograce(sp->so_client, state);
894 case -NFS4ERR_STALE_CLIENTID: 932 case -NFS4ERR_STALE_CLIENTID:
895 goto out_err; 933 goto out_err;
896 } 934 }
935 nfs4_put_open_state(state);
936 goto restart;
897 } 937 }
938 spin_unlock(&sp->so_lock);
898 return 0; 939 return 0;
899out_err: 940out_err:
941 nfs4_put_open_state(state);
900 return status; 942 return status;
901} 943}
902 944
903static void nfs4_state_mark_reclaim(struct nfs_client *clp) 945static void nfs4_clear_open_state(struct nfs4_state *state)
946{
947 struct nfs4_lock_state *lock;
948
949 clear_bit(NFS_DELEGATED_STATE, &state->flags);
950 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
951 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
952 clear_bit(NFS_O_RDWR_STATE, &state->flags);
953 list_for_each_entry(lock, &state->lock_states, ls_locks) {
954 lock->ls_seqid.flags = 0;
955 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
956 }
957}
958
959static void nfs4_state_mark_reclaim_helper(struct nfs_client *clp, int (*mark_reclaim)(struct nfs_client *clp, struct nfs4_state *state))
904{ 960{
905 struct nfs4_state_owner *sp; 961 struct nfs4_state_owner *sp;
906 struct rb_node *pos; 962 struct rb_node *pos;
907 struct nfs4_state *state; 963 struct nfs4_state *state;
908 struct nfs4_lock_state *lock;
909 964
910 /* Reset all sequence ids to zero */ 965 /* Reset all sequence ids to zero */
911 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { 966 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
912 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); 967 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
913 sp->so_seqid.counter = 0;
914 sp->so_seqid.flags = 0; 968 sp->so_seqid.flags = 0;
915 spin_lock(&sp->so_lock); 969 spin_lock(&sp->so_lock);
916 list_for_each_entry(state, &sp->so_states, open_states) { 970 list_for_each_entry(state, &sp->so_states, open_states) {
917 clear_bit(NFS_DELEGATED_STATE, &state->flags); 971 if (mark_reclaim(clp, state))
918 clear_bit(NFS_O_RDONLY_STATE, &state->flags); 972 nfs4_clear_open_state(state);
919 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
920 clear_bit(NFS_O_RDWR_STATE, &state->flags);
921 list_for_each_entry(lock, &state->lock_states, ls_locks) {
922 lock->ls_seqid.counter = 0;
923 lock->ls_seqid.flags = 0;
924 lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
925 }
926 } 973 }
927 spin_unlock(&sp->so_lock); 974 spin_unlock(&sp->so_lock);
928 } 975 }
929} 976}
930 977
931static int reclaimer(void *ptr) 978static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
979{
980 /* Mark all delegations for reclaim */
981 nfs_delegation_mark_reclaim(clp);
982 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
983}
984
985static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
932{ 986{
933 struct nfs_client *clp = ptr;
934 struct nfs4_state_owner *sp; 987 struct nfs4_state_owner *sp;
935 struct rb_node *pos; 988 struct rb_node *pos;
936 struct nfs4_state_recovery_ops *ops; 989 struct nfs4_state *state;
937 struct rpc_cred *cred; 990
991 if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
992 return;
993
994 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
995 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
996 spin_lock(&sp->so_lock);
997 list_for_each_entry(state, &sp->so_states, open_states) {
998 if (!test_and_clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags))
999 continue;
1000 nfs4_state_mark_reclaim_nograce(clp, state);
1001 }
1002 spin_unlock(&sp->so_lock);
1003 }
1004
1005 nfs_delegation_reap_unclaimed(clp);
1006}
1007
1008static void nfs_delegation_clear_all(struct nfs_client *clp)
1009{
1010 nfs_delegation_mark_reclaim(clp);
1011 nfs_delegation_reap_unclaimed(clp);
1012}
1013
1014static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
1015{
1016 nfs_delegation_clear_all(clp);
1017 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
1018}
1019
1020static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp)
1021{
1022 clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1023}
1024
1025static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1026{
1027 switch (error) {
1028 case -NFS4ERR_CB_PATH_DOWN:
1029 nfs_handle_cb_pathdown(clp);
1030 break;
1031 case -NFS4ERR_STALE_CLIENTID:
1032 case -NFS4ERR_LEASE_MOVED:
1033 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1034 nfs4_state_start_reclaim_reboot(clp);
1035 break;
1036 case -NFS4ERR_EXPIRED:
1037 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1038 nfs4_state_start_reclaim_nograce(clp);
1039 }
1040}
1041
1042static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
1043{
1044 struct rb_node *pos;
938 int status = 0; 1045 int status = 0;
939 1046
940 allow_signal(SIGKILL); 1047restart:
1048 spin_lock(&clp->cl_lock);
1049 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
1050 struct nfs4_state_owner *sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
1051 if (!test_and_clear_bit(ops->owner_flag_bit, &sp->so_flags))
1052 continue;
1053 atomic_inc(&sp->so_count);
1054 spin_unlock(&clp->cl_lock);
1055 status = nfs4_reclaim_open_state(sp, ops);
1056 if (status < 0) {
1057 set_bit(ops->owner_flag_bit, &sp->so_flags);
1058 nfs4_put_state_owner(sp);
1059 nfs4_recovery_handle_error(clp, status);
1060 return status;
1061 }
1062 nfs4_put_state_owner(sp);
1063 goto restart;
1064 }
1065 spin_unlock(&clp->cl_lock);
1066 return status;
1067}
941 1068
942 /* Ensure exclusive access to NFSv4 state */ 1069static int nfs4_check_lease(struct nfs_client *clp)
943 down_write(&clp->cl_sem); 1070{
944 /* Are there any NFS mounts out there? */ 1071 struct rpc_cred *cred;
945 if (list_empty(&clp->cl_superblocks)) 1072 int status = -NFS4ERR_EXPIRED;
946 goto out; 1073
947restart_loop: 1074 /* Is the client already known to have an expired lease? */
948 ops = &nfs4_network_partition_recovery_ops; 1075 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
949 /* Are there any open files on this volume? */ 1076 return 0;
950 cred = nfs4_get_renew_cred(clp); 1077 cred = nfs4_get_renew_cred(clp);
951 if (cred != NULL) { 1078 if (cred == NULL) {
952 /* Yes there are: try to renew the old lease */ 1079 cred = nfs4_get_setclientid_cred(clp);
953 status = nfs4_proc_renew(clp, cred); 1080 if (cred == NULL)
954 put_rpccred(cred); 1081 goto out;
955 switch (status) {
956 case 0:
957 case -NFS4ERR_CB_PATH_DOWN:
958 goto out;
959 case -NFS4ERR_STALE_CLIENTID:
960 case -NFS4ERR_LEASE_MOVED:
961 ops = &nfs4_reboot_recovery_ops;
962 }
963 } else {
964 /* "reboot" to ensure we clear all state on the server */
965 clp->cl_boot_time = CURRENT_TIME;
966 } 1082 }
967 /* We're going to have to re-establish a clientid */ 1083 status = nfs4_proc_renew(clp, cred);
968 nfs4_state_mark_reclaim(clp); 1084 put_rpccred(cred);
969 status = -ENOENT; 1085out:
1086 nfs4_recovery_handle_error(clp, status);
1087 return status;
1088}
1089
1090static int nfs4_reclaim_lease(struct nfs_client *clp)
1091{
1092 struct rpc_cred *cred;
1093 int status = -ENOENT;
1094
970 cred = nfs4_get_setclientid_cred(clp); 1095 cred = nfs4_get_setclientid_cred(clp);
971 if (cred != NULL) { 1096 if (cred != NULL) {
972 status = nfs4_init_client(clp, cred); 1097 status = nfs4_init_client(clp, cred);
@@ -974,42 +1099,90 @@ restart_loop:
974 /* Handle case where the user hasn't set up machine creds */ 1099 /* Handle case where the user hasn't set up machine creds */
975 if (status == -EACCES && cred == clp->cl_machine_cred) { 1100 if (status == -EACCES && cred == clp->cl_machine_cred) {
976 nfs4_clear_machine_cred(clp); 1101 nfs4_clear_machine_cred(clp);
977 goto restart_loop; 1102 status = -EAGAIN;
978 } 1103 }
979 } 1104 }
980 if (status) 1105 return status;
981 goto out_error; 1106}
982 /* Mark all delegations for reclaim */ 1107
983 nfs_delegation_mark_reclaim(clp); 1108static void nfs4_state_manager(struct nfs_client *clp)
984 /* Note: list is protected by exclusive lock on cl->cl_sem */ 1109{
985 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { 1110 int status = 0;
986 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); 1111
987 status = nfs4_reclaim_open_state(ops, sp); 1112 /* Ensure exclusive access to NFSv4 state */
988 if (status < 0) { 1113 for(;;) {
989 if (status == -NFS4ERR_NO_GRACE) { 1114 if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
990 ops = &nfs4_network_partition_recovery_ops; 1115 /* We're going to have to re-establish a clientid */
991 status = nfs4_reclaim_open_state(ops, sp); 1116 status = nfs4_reclaim_lease(clp);
1117 if (status) {
1118 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1119 if (status == -EAGAIN)
1120 continue;
1121 goto out_error;
992 } 1122 }
1123 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
1124 }
1125
1126 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
1127 status = nfs4_check_lease(clp);
1128 if (status != 0)
1129 continue;
1130 }
1131
1132 /* First recover reboot state... */
1133 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
1134 status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops);
993 if (status == -NFS4ERR_STALE_CLIENTID) 1135 if (status == -NFS4ERR_STALE_CLIENTID)
994 goto restart_loop; 1136 continue;
995 if (status == -NFS4ERR_EXPIRED) 1137 nfs4_state_end_reclaim_reboot(clp);
996 goto restart_loop; 1138 continue;
1139 }
1140
1141 /* Now recover expired state... */
1142 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
1143 status = nfs4_do_reclaim(clp, &nfs4_nograce_recovery_ops);
1144 if (status < 0) {
1145 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1146 if (status == -NFS4ERR_STALE_CLIENTID)
1147 continue;
1148 if (status == -NFS4ERR_EXPIRED)
1149 continue;
1150 goto out_error;
1151 } else
1152 nfs4_state_end_reclaim_nograce(clp);
1153 continue;
997 } 1154 }
1155
1156 if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
1157 nfs_client_return_marked_delegations(clp);
1158 continue;
1159 }
1160
1161 nfs4_clear_state_manager_bit(clp);
1162 /* Did we race with an attempt to give us more work? */
1163 if (clp->cl_state == 0)
1164 break;
1165 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
1166 break;
998 } 1167 }
999 nfs_delegation_reap_unclaimed(clp); 1168 return;
1000out: 1169out_error:
1001 up_write(&clp->cl_sem); 1170 printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
1002 if (status == -NFS4ERR_CB_PATH_DOWN) 1171 " with error %d\n", clp->cl_hostname, -status);
1003 nfs_handle_cb_pathdown(clp); 1172 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1004 nfs4_clear_recover_bit(clp); 1173 nfs4_state_end_reclaim_reboot(clp);
1174 nfs4_clear_state_manager_bit(clp);
1175}
1176
1177static int nfs4_run_state_manager(void *ptr)
1178{
1179 struct nfs_client *clp = ptr;
1180
1181 allow_signal(SIGKILL);
1182 nfs4_state_manager(clp);
1005 nfs_put_client(clp); 1183 nfs_put_client(clp);
1006 module_put_and_exit(0); 1184 module_put_and_exit(0);
1007 return 0; 1185 return 0;
1008out_error:
1009 printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s"
1010 " with error %d\n", clp->cl_hostname, -status);
1011 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1012 goto out;
1013} 1186}
1014 1187
1015/* 1188/*