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.c118
1 files changed, 58 insertions, 60 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9bf41eab3e46..69c0f3c5ee7a 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>
@@ -443,8 +444,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
443 if (res->sr_status == 1) 444 if (res->sr_status == 1)
444 res->sr_status = NFS_OK; 445 res->sr_status = NFS_OK;
445 446
446 /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ 447 /* don't increment the sequence number if the task wasn't sent */
447 if (!res->sr_slot) 448 if (!RPC_WAS_SENT(task))
448 goto out; 449 goto out;
449 450
450 /* Check the SEQUENCE operation status */ 451 /* Check the SEQUENCE operation status */
@@ -2185,9 +2186,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
2185 struct nfs4_exception exception = { }; 2186 struct nfs4_exception exception = { };
2186 int err; 2187 int err;
2187 do { 2188 do {
2188 err = nfs4_handle_exception(server, 2189 err = _nfs4_lookup_root(server, fhandle, info);
2189 _nfs4_lookup_root(server, fhandle, info), 2190 switch (err) {
2190 &exception); 2191 case 0:
2192 case -NFS4ERR_WRONGSEC:
2193 break;
2194 default:
2195 err = nfs4_handle_exception(server, err, &exception);
2196 }
2191 } while (exception.retry); 2197 } while (exception.retry);
2192 return err; 2198 return err;
2193} 2199}
@@ -2208,25 +2214,47 @@ out:
2208 return ret; 2214 return ret;
2209} 2215}
2210 2216
2211/* 2217static 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) 2218 struct nfs_fsinfo *info)
2216{ 2219{
2217 int i, len, status = 0; 2220 int i, len, status = 0;
2218 rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; 2221 rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
2219 2222
2220 flav_array[0] = RPC_AUTH_UNIX; 2223 len = gss_mech_list_pseudoflavors(&flav_array[0]);
2221 len = gss_mech_list_pseudoflavors(&flav_array[1]); 2224 flav_array[len] = RPC_AUTH_NULL;
2222 flav_array[1+len] = RPC_AUTH_NULL; 2225 len += 1;
2223 len += 2;
2224 2226
2225 for (i = 0; i < len; i++) { 2227 for (i = 0; i < len; i++) {
2226 status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); 2228 status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
2227 if (status != -EPERM) 2229 if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
2228 break; 2230 continue;
2231 break;
2229 } 2232 }
2233 /*
2234 * -EACCESS could mean that the user doesn't have correct permissions
2235 * to access the mount. It could also mean that we tried to mount
2236 * with a gss auth flavor, but rpc.gssd isn't running. Either way,
2237 * existing mount programs don't handle -EACCES very well so it should
2238 * be mapped to -EPERM instead.
2239 */
2240 if (status == -EACCES)
2241 status = -EPERM;
2242 return status;
2243}
2244
2245/*
2246 * get the file handle for the "/" directory on the server
2247 */
2248static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2249 struct nfs_fsinfo *info)
2250{
2251 int status = nfs4_lookup_root(server, fhandle, info);
2252 if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
2253 /*
2254 * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
2255 * by nfs4_map_errors() as this function exits.
2256 */
2257 status = nfs4_find_root_sec(server, fhandle, info);
2230 if (status == 0) 2258 if (status == 0)
2231 status = nfs4_server_capabilities(server, fhandle); 2259 status = nfs4_server_capabilities(server, fhandle);
2232 if (status == 0) 2260 if (status == 0)
@@ -3723,21 +3751,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3723 sizeof(setclientid.sc_uaddr), "%s.%u.%u", 3751 sizeof(setclientid.sc_uaddr), "%s.%u.%u",
3724 clp->cl_ipaddr, port >> 8, port & 255); 3752 clp->cl_ipaddr, port >> 8, port & 255);
3725 3753
3726 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); 3754 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
3727 if (status != -NFS4ERR_CLID_INUSE) 3755 if (status != -NFS4ERR_CLID_INUSE)
3728 break; 3756 break;
3729 if (signalled()) 3757 if (loop != 0) {
3758 ++clp->cl_id_uniquifier;
3730 break; 3759 break;
3731 if (loop++ & 1) 3760 }
3732 ssleep(clp->cl_lease_time / HZ + 1); 3761 ++loop;
3733 else 3762 ssleep(clp->cl_lease_time / HZ + 1);
3734 if (++clp->cl_id_uniquifier == 0)
3735 break;
3736 } 3763 }
3737 return status; 3764 return status;
3738} 3765}
3739 3766
3740static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, 3767int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
3741 struct nfs4_setclientid_res *arg, 3768 struct nfs4_setclientid_res *arg,
3742 struct rpc_cred *cred) 3769 struct rpc_cred *cred)
3743{ 3770{
@@ -3752,7 +3779,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
3752 int status; 3779 int status;
3753 3780
3754 now = jiffies; 3781 now = jiffies;
3755 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); 3782 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
3756 if (status == 0) { 3783 if (status == 0) {
3757 spin_lock(&clp->cl_lock); 3784 spin_lock(&clp->cl_lock);
3758 clp->cl_lease_time = fsinfo.lease_time * HZ; 3785 clp->cl_lease_time = fsinfo.lease_time * HZ;
@@ -3762,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
3762 return status; 3789 return status;
3763} 3790}
3764 3791
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 { 3792struct nfs4_delegreturndata {
3786 struct nfs4_delegreturnargs args; 3793 struct nfs4_delegreturnargs args;
3787 struct nfs4_delegreturnres res; 3794 struct nfs4_delegreturnres res;
@@ -4786,7 +4793,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4786 init_utsname()->domainname, 4793 init_utsname()->domainname,
4787 clp->cl_rpcclient->cl_auth->au_flavor); 4794 clp->cl_rpcclient->cl_auth->au_flavor);
4788 4795
4789 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); 4796 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
4790 if (!status) 4797 if (!status)
4791 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); 4798 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
4792 dprintk("<-- %s status= %d\n", __func__, status); 4799 dprintk("<-- %s status= %d\n", __func__, status);
@@ -4869,7 +4876,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4869 .rpc_client = clp->cl_rpcclient, 4876 .rpc_client = clp->cl_rpcclient,
4870 .rpc_message = &msg, 4877 .rpc_message = &msg,
4871 .callback_ops = &nfs4_get_lease_time_ops, 4878 .callback_ops = &nfs4_get_lease_time_ops,
4872 .callback_data = &data 4879 .callback_data = &data,
4880 .flags = RPC_TASK_TIMEOUT,
4873 }; 4881 };
4874 int status; 4882 int status;
4875 4883
@@ -5171,7 +5179,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
5171 nfs4_init_channel_attrs(&args); 5179 nfs4_init_channel_attrs(&args);
5172 args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); 5180 args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
5173 5181
5174 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); 5182 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
5175 5183
5176 if (!status) 5184 if (!status)
5177 /* Verify the session's negotiated channel_attrs values */ 5185 /* Verify the session's negotiated channel_attrs values */
@@ -5194,20 +5202,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
5194 int status; 5202 int status;
5195 unsigned *ptr; 5203 unsigned *ptr;
5196 struct nfs4_session *session = clp->cl_session; 5204 struct nfs4_session *session = clp->cl_session;
5197 long timeout = 0;
5198 int err;
5199 5205
5200 dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); 5206 dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
5201 5207
5202 do { 5208 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) 5209 if (status)
5212 goto out; 5210 goto out;
5213 5211
@@ -5248,7 +5246,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
5248 msg.rpc_argp = session; 5246 msg.rpc_argp = session;
5249 msg.rpc_resp = NULL; 5247 msg.rpc_resp = NULL;
5250 msg.rpc_cred = NULL; 5248 msg.rpc_cred = NULL;
5251 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); 5249 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
5252 5250
5253 if (status) 5251 if (status)
5254 printk(KERN_WARNING 5252 printk(KERN_WARNING