aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c124
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/* 2218static 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 */
2214static 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 */
2249static 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
3740static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, 3769int 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
3765int 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
3785struct nfs4_delegreturndata { 3794struct 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);