diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 124 |
1 files changed, 64 insertions, 60 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9bf41eab3e46..cf1b339c3937 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/nfs4.h> | 46 | #include <linux/nfs4.h> |
47 | #include <linux/nfs_fs.h> | 47 | #include <linux/nfs_fs.h> |
48 | #include <linux/nfs_page.h> | 48 | #include <linux/nfs_page.h> |
49 | #include <linux/nfs_mount.h> | ||
49 | #include <linux/namei.h> | 50 | #include <linux/namei.h> |
50 | #include <linux/mount.h> | 51 | #include <linux/mount.h> |
51 | #include <linux/module.h> | 52 | #include <linux/module.h> |
@@ -299,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
299 | ret = nfs4_delay(server->client, &exception->timeout); | 300 | ret = nfs4_delay(server->client, &exception->timeout); |
300 | if (ret != 0) | 301 | if (ret != 0) |
301 | break; | 302 | break; |
303 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
302 | case -NFS4ERR_OLD_STATEID: | 304 | case -NFS4ERR_OLD_STATEID: |
303 | exception->retry = 1; | 305 | exception->retry = 1; |
304 | break; | 306 | break; |
@@ -443,8 +445,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
443 | if (res->sr_status == 1) | 445 | if (res->sr_status == 1) |
444 | res->sr_status = NFS_OK; | 446 | res->sr_status = NFS_OK; |
445 | 447 | ||
446 | /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ | 448 | /* don't increment the sequence number if the task wasn't sent */ |
447 | if (!res->sr_slot) | 449 | if (!RPC_WAS_SENT(task)) |
448 | goto out; | 450 | goto out; |
449 | 451 | ||
450 | /* Check the SEQUENCE operation status */ | 452 | /* Check the SEQUENCE operation status */ |
@@ -2185,9 +2187,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2185 | struct nfs4_exception exception = { }; | 2187 | struct nfs4_exception exception = { }; |
2186 | int err; | 2188 | int err; |
2187 | do { | 2189 | do { |
2188 | err = nfs4_handle_exception(server, | 2190 | err = _nfs4_lookup_root(server, fhandle, info); |
2189 | _nfs4_lookup_root(server, fhandle, info), | 2191 | switch (err) { |
2190 | &exception); | 2192 | case 0: |
2193 | case -NFS4ERR_WRONGSEC: | ||
2194 | break; | ||
2195 | default: | ||
2196 | err = nfs4_handle_exception(server, err, &exception); | ||
2197 | } | ||
2191 | } while (exception.retry); | 2198 | } while (exception.retry); |
2192 | return err; | 2199 | return err; |
2193 | } | 2200 | } |
@@ -2208,25 +2215,47 @@ out: | |||
2208 | return ret; | 2215 | return ret; |
2209 | } | 2216 | } |
2210 | 2217 | ||
2211 | /* | 2218 | static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2212 | * get the file handle for the "/" directory on the server | ||
2213 | */ | ||
2214 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2215 | struct nfs_fsinfo *info) | 2219 | struct nfs_fsinfo *info) |
2216 | { | 2220 | { |
2217 | int i, len, status = 0; | 2221 | int i, len, status = 0; |
2218 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; | 2222 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2219 | 2223 | ||
2220 | flav_array[0] = RPC_AUTH_UNIX; | 2224 | len = gss_mech_list_pseudoflavors(&flav_array[0]); |
2221 | len = gss_mech_list_pseudoflavors(&flav_array[1]); | 2225 | flav_array[len] = RPC_AUTH_NULL; |
2222 | flav_array[1+len] = RPC_AUTH_NULL; | 2226 | len += 1; |
2223 | len += 2; | ||
2224 | 2227 | ||
2225 | for (i = 0; i < len; i++) { | 2228 | for (i = 0; i < len; i++) { |
2226 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2229 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2227 | if (status != -EPERM) | 2230 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2228 | break; | 2231 | continue; |
2232 | break; | ||
2229 | } | 2233 | } |
2234 | /* | ||
2235 | * -EACCESS could mean that the user doesn't have correct permissions | ||
2236 | * to access the mount. It could also mean that we tried to mount | ||
2237 | * with a gss auth flavor, but rpc.gssd isn't running. Either way, | ||
2238 | * existing mount programs don't handle -EACCES very well so it should | ||
2239 | * be mapped to -EPERM instead. | ||
2240 | */ | ||
2241 | if (status == -EACCES) | ||
2242 | status = -EPERM; | ||
2243 | return status; | ||
2244 | } | ||
2245 | |||
2246 | /* | ||
2247 | * get the file handle for the "/" directory on the server | ||
2248 | */ | ||
2249 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2250 | struct nfs_fsinfo *info) | ||
2251 | { | ||
2252 | int status = nfs4_lookup_root(server, fhandle, info); | ||
2253 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) | ||
2254 | /* | ||
2255 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM | ||
2256 | * by nfs4_map_errors() as this function exits. | ||
2257 | */ | ||
2258 | status = nfs4_find_root_sec(server, fhandle, info); | ||
2230 | if (status == 0) | 2259 | if (status == 0) |
2231 | status = nfs4_server_capabilities(server, fhandle); | 2260 | status = nfs4_server_capabilities(server, fhandle); |
2232 | if (status == 0) | 2261 | if (status == 0) |
@@ -3667,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3667 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3696 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
3668 | task->tk_status = 0; | 3697 | task->tk_status = 0; |
3669 | return -EAGAIN; | 3698 | return -EAGAIN; |
3699 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
3670 | case -NFS4ERR_OLD_STATEID: | 3700 | case -NFS4ERR_OLD_STATEID: |
3671 | task->tk_status = 0; | 3701 | task->tk_status = 0; |
3672 | return -EAGAIN; | 3702 | return -EAGAIN; |
@@ -3723,21 +3753,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3723 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 3753 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
3724 | clp->cl_ipaddr, port >> 8, port & 255); | 3754 | clp->cl_ipaddr, port >> 8, port & 255); |
3725 | 3755 | ||
3726 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3756 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3727 | if (status != -NFS4ERR_CLID_INUSE) | 3757 | if (status != -NFS4ERR_CLID_INUSE) |
3728 | break; | 3758 | break; |
3729 | if (signalled()) | 3759 | if (loop != 0) { |
3760 | ++clp->cl_id_uniquifier; | ||
3730 | break; | 3761 | break; |
3731 | if (loop++ & 1) | 3762 | } |
3732 | ssleep(clp->cl_lease_time / HZ + 1); | 3763 | ++loop; |
3733 | else | 3764 | ssleep(clp->cl_lease_time / HZ + 1); |
3734 | if (++clp->cl_id_uniquifier == 0) | ||
3735 | break; | ||
3736 | } | 3765 | } |
3737 | return status; | 3766 | return status; |
3738 | } | 3767 | } |
3739 | 3768 | ||
3740 | static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | 3769 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
3741 | struct nfs4_setclientid_res *arg, | 3770 | struct nfs4_setclientid_res *arg, |
3742 | struct rpc_cred *cred) | 3771 | struct rpc_cred *cred) |
3743 | { | 3772 | { |
@@ -3752,7 +3781,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3752 | int status; | 3781 | int status; |
3753 | 3782 | ||
3754 | now = jiffies; | 3783 | now = jiffies; |
3755 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3784 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3756 | if (status == 0) { | 3785 | if (status == 0) { |
3757 | spin_lock(&clp->cl_lock); | 3786 | spin_lock(&clp->cl_lock); |
3758 | clp->cl_lease_time = fsinfo.lease_time * HZ; | 3787 | clp->cl_lease_time = fsinfo.lease_time * HZ; |
@@ -3762,26 +3791,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3762 | return status; | 3791 | return status; |
3763 | } | 3792 | } |
3764 | 3793 | ||
3765 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | ||
3766 | struct nfs4_setclientid_res *arg, | ||
3767 | struct rpc_cred *cred) | ||
3768 | { | ||
3769 | long timeout = 0; | ||
3770 | int err; | ||
3771 | do { | ||
3772 | err = _nfs4_proc_setclientid_confirm(clp, arg, cred); | ||
3773 | switch (err) { | ||
3774 | case 0: | ||
3775 | return err; | ||
3776 | case -NFS4ERR_RESOURCE: | ||
3777 | /* The IBM lawyers misread another document! */ | ||
3778 | case -NFS4ERR_DELAY: | ||
3779 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
3780 | } | ||
3781 | } while (err == 0); | ||
3782 | return err; | ||
3783 | } | ||
3784 | |||
3785 | struct nfs4_delegreturndata { | 3794 | struct nfs4_delegreturndata { |
3786 | struct nfs4_delegreturnargs args; | 3795 | struct nfs4_delegreturnargs args; |
3787 | struct nfs4_delegreturnres res; | 3796 | struct nfs4_delegreturnres res; |
@@ -4786,7 +4795,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4786 | init_utsname()->domainname, | 4795 | init_utsname()->domainname, |
4787 | clp->cl_rpcclient->cl_auth->au_flavor); | 4796 | clp->cl_rpcclient->cl_auth->au_flavor); |
4788 | 4797 | ||
4789 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 4798 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4790 | if (!status) | 4799 | if (!status) |
4791 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 4800 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); |
4792 | dprintk("<-- %s status= %d\n", __func__, status); | 4801 | dprintk("<-- %s status= %d\n", __func__, status); |
@@ -4837,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4837 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4846 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); |
4838 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4847 | rpc_delay(task, NFS4_POLL_RETRY_MIN); |
4839 | task->tk_status = 0; | 4848 | task->tk_status = 0; |
4849 | /* fall through */ | ||
4850 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
4840 | nfs_restart_rpc(task, data->clp); | 4851 | nfs_restart_rpc(task, data->clp); |
4841 | return; | 4852 | return; |
4842 | } | 4853 | } |
@@ -4869,7 +4880,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
4869 | .rpc_client = clp->cl_rpcclient, | 4880 | .rpc_client = clp->cl_rpcclient, |
4870 | .rpc_message = &msg, | 4881 | .rpc_message = &msg, |
4871 | .callback_ops = &nfs4_get_lease_time_ops, | 4882 | .callback_ops = &nfs4_get_lease_time_ops, |
4872 | .callback_data = &data | 4883 | .callback_data = &data, |
4884 | .flags = RPC_TASK_TIMEOUT, | ||
4873 | }; | 4885 | }; |
4874 | int status; | 4886 | int status; |
4875 | 4887 | ||
@@ -5171,7 +5183,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) | |||
5171 | nfs4_init_channel_attrs(&args); | 5183 | nfs4_init_channel_attrs(&args); |
5172 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | 5184 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); |
5173 | 5185 | ||
5174 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5186 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5175 | 5187 | ||
5176 | if (!status) | 5188 | if (!status) |
5177 | /* Verify the session's negotiated channel_attrs values */ | 5189 | /* Verify the session's negotiated channel_attrs values */ |
@@ -5194,20 +5206,10 @@ int nfs4_proc_create_session(struct nfs_client *clp) | |||
5194 | int status; | 5206 | int status; |
5195 | unsigned *ptr; | 5207 | unsigned *ptr; |
5196 | struct nfs4_session *session = clp->cl_session; | 5208 | struct nfs4_session *session = clp->cl_session; |
5197 | long timeout = 0; | ||
5198 | int err; | ||
5199 | 5209 | ||
5200 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | 5210 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); |
5201 | 5211 | ||
5202 | do { | 5212 | status = _nfs4_proc_create_session(clp); |
5203 | status = _nfs4_proc_create_session(clp); | ||
5204 | if (status == -NFS4ERR_DELAY) { | ||
5205 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
5206 | if (err) | ||
5207 | status = err; | ||
5208 | } | ||
5209 | } while (status == -NFS4ERR_DELAY); | ||
5210 | |||
5211 | if (status) | 5213 | if (status) |
5212 | goto out; | 5214 | goto out; |
5213 | 5215 | ||
@@ -5248,7 +5250,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
5248 | msg.rpc_argp = session; | 5250 | msg.rpc_argp = session; |
5249 | msg.rpc_resp = NULL; | 5251 | msg.rpc_resp = NULL; |
5250 | msg.rpc_cred = NULL; | 5252 | msg.rpc_cred = NULL; |
5251 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5253 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5252 | 5254 | ||
5253 | if (status) | 5255 | if (status) |
5254 | printk(KERN_WARNING | 5256 | printk(KERN_WARNING |
@@ -5481,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5481 | break; | 5483 | break; |
5482 | case -NFS4ERR_DELAY: | 5484 | case -NFS4ERR_DELAY: |
5483 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5485 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5486 | /* fall through */ | ||
5487 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5484 | return -EAGAIN; | 5488 | return -EAGAIN; |
5485 | default: | 5489 | default: |
5486 | nfs4_schedule_lease_recovery(clp); | 5490 | nfs4_schedule_lease_recovery(clp); |