diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 71 |
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 | ||
199 | static int __nfs4_init_client(struct nfs4_client *clp) | 196 | static 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 | ||
209 | int nfs4_init_client(struct nfs4_client *clp) | ||
210 | { | ||
211 | return nfs4_map_errors(__nfs4_init_client(clp)); | ||
212 | } | ||
213 | |||
214 | u32 | 207 | u32 |
215 | nfs4_alloc_lockowner_id(struct nfs4_client *clp) | 208 | nfs4_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 | ||
242 | struct 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 | |||
249 | static struct nfs4_state_owner * | 254 | static struct nfs4_state_owner * |
250 | nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) | 255 | nfs4_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; |
915 | restart_loop: | 921 | restart_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 */ |