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.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 18f6ed1a0b54..afad0255e7db 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -91,11 +91,10 @@ nfs4_alloc_client(struct in_addr *addr)
91 91
92 if (nfs_callback_up() < 0) 92 if (nfs_callback_up() < 0)
93 return NULL; 93 return NULL;
94 if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { 94 if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
95 nfs_callback_down(); 95 nfs_callback_down();
96 return NULL; 96 return NULL;
97 } 97 }
98 memset(clp, 0, sizeof(*clp));
99 memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); 98 memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
100 init_rwsem(&clp->cl_sem); 99 init_rwsem(&clp->cl_sem);
101 INIT_LIST_HEAD(&clp->cl_delegations); 100 INIT_LIST_HEAD(&clp->cl_delegations);
@@ -108,7 +107,7 @@ nfs4_alloc_client(struct in_addr *addr)
108 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); 107 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
109 clp->cl_rpcclient = ERR_PTR(-EINVAL); 108 clp->cl_rpcclient = ERR_PTR(-EINVAL);
110 clp->cl_boot_time = CURRENT_TIME; 109 clp->cl_boot_time = CURRENT_TIME;
111 clp->cl_state = 0; 110 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
112 return clp; 111 return clp;
113} 112}
114 113
@@ -125,8 +124,6 @@ nfs4_free_client(struct nfs4_client *clp)
125 kfree(sp); 124 kfree(sp);
126 } 125 }
127 BUG_ON(!list_empty(&clp->cl_state_owners)); 126 BUG_ON(!list_empty(&clp->cl_state_owners));
128 if (clp->cl_cred)
129 put_rpccred(clp->cl_cred);
130 nfs_idmap_delete(clp); 127 nfs_idmap_delete(clp);
131 if (!IS_ERR(clp->cl_rpcclient)) 128 if (!IS_ERR(clp->cl_rpcclient))
132 rpc_shutdown_client(clp->cl_rpcclient); 129 rpc_shutdown_client(clp->cl_rpcclient);
@@ -196,21 +193,17 @@ nfs4_put_client(struct nfs4_client *clp)
196 nfs4_free_client(clp); 193 nfs4_free_client(clp);
197} 194}
198 195
199static int __nfs4_init_client(struct nfs4_client *clp) 196static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred)
200{ 197{
201 int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport); 198 int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
199 nfs_callback_tcpport, cred);
202 if (status == 0) 200 if (status == 0)
203 status = nfs4_proc_setclientid_confirm(clp); 201 status = nfs4_proc_setclientid_confirm(clp, cred);
204 if (status == 0) 202 if (status == 0)
205 nfs4_schedule_state_renewal(clp); 203 nfs4_schedule_state_renewal(clp);
206 return status; 204 return status;
207} 205}
208 206
209int nfs4_init_client(struct nfs4_client *clp)
210{
211 return nfs4_map_errors(__nfs4_init_client(clp));
212}
213
214u32 207u32
215nfs4_alloc_lockowner_id(struct nfs4_client *clp) 208nfs4_alloc_lockowner_id(struct nfs4_client *clp)
216{ 209{
@@ -246,6 +239,18 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp)
246 return cred; 239 return cred;
247} 240}
248 241
242struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp)
243{
244 struct nfs4_state_owner *sp;
245
246 if (!list_empty(&clp->cl_state_owners)) {
247 sp = list_entry(clp->cl_state_owners.next,
248 struct nfs4_state_owner, so_list);
249 return get_rpccred(sp->so_cred);
250 }
251 return NULL;
252}
253
249static struct nfs4_state_owner * 254static struct nfs4_state_owner *
250nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) 255nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred)
251{ 256{
@@ -902,6 +907,7 @@ static int reclaimer(void *ptr)
902 struct nfs4_client *clp = ptr; 907 struct nfs4_client *clp = ptr;
903 struct nfs4_state_owner *sp; 908 struct nfs4_state_owner *sp;
904 struct nfs4_state_recovery_ops *ops; 909 struct nfs4_state_recovery_ops *ops;
910 struct rpc_cred *cred;
905 int status = 0; 911 int status = 0;
906 912
907 allow_signal(SIGKILL); 913 allow_signal(SIGKILL);
@@ -913,20 +919,33 @@ static int reclaimer(void *ptr)
913 if (list_empty(&clp->cl_superblocks)) 919 if (list_empty(&clp->cl_superblocks))
914 goto out; 920 goto out;
915restart_loop: 921restart_loop:
916 status = nfs4_proc_renew(clp, clp->cl_cred); 922 ops = &nfs4_network_partition_recovery_ops;
917 switch (status) { 923 /* Are there any open files on this volume? */
918 case 0: 924 cred = nfs4_get_renew_cred(clp);
919 case -NFS4ERR_CB_PATH_DOWN: 925 if (cred != NULL) {
920 goto out; 926 /* Yes there are: try to renew the old lease */
921 case -NFS4ERR_STALE_CLIENTID: 927 status = nfs4_proc_renew(clp, cred);
922 case -NFS4ERR_LEASE_MOVED: 928 switch (status) {
923 ops = &nfs4_reboot_recovery_ops; 929 case 0:
924 break; 930 case -NFS4ERR_CB_PATH_DOWN:
925 default: 931 put_rpccred(cred);
926 ops = &nfs4_network_partition_recovery_ops; 932 goto out;
927 }; 933 case -NFS4ERR_STALE_CLIENTID:
934 case -NFS4ERR_LEASE_MOVED:
935 ops = &nfs4_reboot_recovery_ops;
936 }
937 } else {
938 /* "reboot" to ensure we clear all state on the server */
939 clp->cl_boot_time = CURRENT_TIME;
940 cred = nfs4_get_setclientid_cred(clp);
941 }
942 /* We're going to have to re-establish a clientid */
928 nfs4_state_mark_reclaim(clp); 943 nfs4_state_mark_reclaim(clp);
929 status = __nfs4_init_client(clp); 944 status = -ENOENT;
945 if (cred != NULL) {
946 status = nfs4_init_client(clp, cred);
947 put_rpccred(cred);
948 }
930 if (status) 949 if (status)
931 goto out_error; 950 goto out_error;
932 /* Mark all delegations for reclaim */ 951 /* Mark all delegations for reclaim */