|
@@ -46,6 +46,7 @@
|
|
|
#include <linux/nfs4.h>
|
|
|
#include <linux/nfs_fs.h>
|
|
|
#include <linux/nfs_page.h>
|
|
|
+#include <linux/nfs_mount.h>
|
|
|
#include <linux/namei.h>
|
|
|
#include <linux/mount.h>
|
|
|
#include <linux/module.h>
|
|
@@ -443,8 +444,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
|
|
|
if (res->sr_status == 1)
|
|
|
res->sr_status = NFS_OK;
|
|
|
|
|
|
- /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
|
|
|
- if (!res->sr_slot)
|
|
|
+ /* don't increment the sequence number if the task wasn't sent */
|
|
|
+ if (!RPC_WAS_SENT(task))
|
|
|
goto out;
|
|
|
|
|
|
/* Check the SEQUENCE operation status */
|
|
@@ -2185,9 +2186,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
|
|
struct nfs4_exception exception = { };
|
|
|
int err;
|
|
|
do {
|
|
|
- err = nfs4_handle_exception(server,
|
|
|
- _nfs4_lookup_root(server, fhandle, info),
|
|
|
- &exception);
|
|
|
+ err = _nfs4_lookup_root(server, fhandle, info);
|
|
|
+ switch (err) {
|
|
|
+ case 0:
|
|
|
+ case -NFS4ERR_WRONGSEC:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ err = nfs4_handle_exception(server, err, &exception);
|
|
|
+ }
|
|
|
} while (exception.retry);
|
|
|
return err;
|
|
|
}
|
|
@@ -2208,25 +2214,47 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * get the file handle for the "/" directory on the server
|
|
|
- */
|
|
|
-static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
|
|
+static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
|
|
struct nfs_fsinfo *info)
|
|
|
{
|
|
|
int i, len, status = 0;
|
|
|
- rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
|
|
|
+ rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
|
|
|
|
|
|
- flav_array[0] = RPC_AUTH_UNIX;
|
|
|
- len = gss_mech_list_pseudoflavors(&flav_array[1]);
|
|
|
- flav_array[1+len] = RPC_AUTH_NULL;
|
|
|
- len += 2;
|
|
|
+ len = gss_mech_list_pseudoflavors(&flav_array[0]);
|
|
|
+ flav_array[len] = RPC_AUTH_NULL;
|
|
|
+ len += 1;
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
|
|
|
- if (status != -EPERM)
|
|
|
- break;
|
|
|
+ if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
|
|
|
+ continue;
|
|
|
+ break;
|
|
|
}
|
|
|
+ /*
|
|
|
+ * -EACCESS could mean that the user doesn't have correct permissions
|
|
|
+ * to access the mount. It could also mean that we tried to mount
|
|
|
+ * with a gss auth flavor, but rpc.gssd isn't running. Either way,
|
|
|
+ * existing mount programs don't handle -EACCES very well so it should
|
|
|
+ * be mapped to -EPERM instead.
|
|
|
+ */
|
|
|
+ if (status == -EACCES)
|
|
|
+ status = -EPERM;
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * get the file handle for the "/" directory on the server
|
|
|
+ */
|
|
|
+static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
|
|
+ struct nfs_fsinfo *info)
|
|
|
+{
|
|
|
+ int status = nfs4_lookup_root(server, fhandle, info);
|
|
|
+ if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
|
|
|
+ /*
|
|
|
+ * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
|
|
|
+ * by nfs4_map_errors() as this function exits.
|
|
|
+ */
|
|
|
+ status = nfs4_find_root_sec(server, fhandle, info);
|
|
|
if (status == 0)
|
|
|
status = nfs4_server_capabilities(server, fhandle);
|
|
|
if (status == 0)
|
|
@@ -3723,21 +3751,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
|
|
|
sizeof(setclientid.sc_uaddr), "%s.%u.%u",
|
|
|
clp->cl_ipaddr, port >> 8, port & 255);
|
|
|
|
|
|
- status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
|
|
|
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
|
if (status != -NFS4ERR_CLID_INUSE)
|
|
|
break;
|
|
|
- if (signalled())
|
|
|
+ if (loop != 0) {
|
|
|
+ ++clp->cl_id_uniquifier;
|
|
|
break;
|
|
|
- if (loop++ & 1)
|
|
|
- ssleep(clp->cl_lease_time / HZ + 1);
|
|
|
- else
|
|
|
- if (++clp->cl_id_uniquifier == 0)
|
|
|
- break;
|
|
|
+ }
|
|
|
+ ++loop;
|
|
|
+ ssleep(clp->cl_lease_time / HZ + 1);
|
|
|
}
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
+int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
struct nfs4_setclientid_res *arg,
|
|
|
struct rpc_cred *cred)
|
|
|
{
|
|
@@ -3752,7 +3779,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
int status;
|
|
|
|
|
|
now = jiffies;
|
|
|
- status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
|
|
|
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
|
if (status == 0) {
|
|
|
spin_lock(&clp->cl_lock);
|
|
|
clp->cl_lease_time = fsinfo.lease_time * HZ;
|
|
@@ -3762,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
|
|
|
- struct nfs4_setclientid_res *arg,
|
|
|
- struct rpc_cred *cred)
|
|
|
-{
|
|
|
- long timeout = 0;
|
|
|
- int err;
|
|
|
- do {
|
|
|
- err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
|
|
|
- switch (err) {
|
|
|
- case 0:
|
|
|
- return err;
|
|
|
- case -NFS4ERR_RESOURCE:
|
|
|
- /* The IBM lawyers misread another document! */
|
|
|
- case -NFS4ERR_DELAY:
|
|
|
- err = nfs4_delay(clp->cl_rpcclient, &timeout);
|
|
|
- }
|
|
|
- } while (err == 0);
|
|
|
- return err;
|
|
|
-}
|
|
|
-
|
|
|
struct nfs4_delegreturndata {
|
|
|
struct nfs4_delegreturnargs args;
|
|
|
struct nfs4_delegreturnres res;
|
|
@@ -4786,7 +4793,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
|
|
|
init_utsname()->domainname,
|
|
|
clp->cl_rpcclient->cl_auth->au_flavor);
|
|
|
|
|
|
- status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
|
|
|
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
|
if (!status)
|
|
|
status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
|
|
|
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)
|
|
|
.rpc_client = clp->cl_rpcclient,
|
|
|
.rpc_message = &msg,
|
|
|
.callback_ops = &nfs4_get_lease_time_ops,
|
|
|
- .callback_data = &data
|
|
|
+ .callback_data = &data,
|
|
|
+ .flags = RPC_TASK_TIMEOUT,
|
|
|
};
|
|
|
int status;
|
|
|
|
|
@@ -5171,7 +5179,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
|
|
|
nfs4_init_channel_attrs(&args);
|
|
|
args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
|
|
|
|
|
|
- status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
|
|
|
+ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
|
|
|
|
if (!status)
|
|
|
/* Verify the session's negotiated channel_attrs values */
|
|
@@ -5194,20 +5202,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
|
|
|
int status;
|
|
|
unsigned *ptr;
|
|
|
struct nfs4_session *session = clp->cl_session;
|
|
|
- long timeout = 0;
|
|
|
- int err;
|
|
|
|
|
|
dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
|
|
|
|
|
|
- do {
|
|
|
- status = _nfs4_proc_create_session(clp);
|
|
|
- if (status == -NFS4ERR_DELAY) {
|
|
|
- err = nfs4_delay(clp->cl_rpcclient, &timeout);
|
|
|
- if (err)
|
|
|
- status = err;
|
|
|
- }
|
|
|
- } while (status == -NFS4ERR_DELAY);
|
|
|
-
|
|
|
+ status = _nfs4_proc_create_session(clp);
|
|
|
if (status)
|
|
|
goto out;
|
|
|
|
|
@@ -5248,7 +5246,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
|
|
|
msg.rpc_argp = session;
|
|
|
msg.rpc_resp = NULL;
|
|
|
msg.rpc_cred = NULL;
|
|
|
- status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
|
|
|
+ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
|
|
|
|
|
if (status)
|
|
|
printk(KERN_WARNING
|