summaryrefslogtreecommitdiff
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c206
1 files changed, 103 insertions, 103 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3923ac71a420..08cc97488904 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7345,7 +7345,9 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
1 << (OP_DESTROY_SESSION - 32) |
1 << (OP_DESTROY_CLIENTID - 32)
};
+ unsigned long flags = 0;
unsigned int i;
+ int ret = 0;
if (sp->how == SP4_MACH_CRED) {
/* Print state protect result */
@@ -7361,7 +7363,8 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) {
if (sp->enforce.u.words[i] & ~supported_enforce[i]) {
dfprintk(MOUNT, "sp4_mach_cred: disabled\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
}
@@ -7380,10 +7383,11 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
test_bit(OP_DESTROY_CLIENTID, sp->enforce.u.longs)) {
dfprintk(MOUNT, "sp4_mach_cred:\n");
dfprintk(MOUNT, " minimal mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_MINIMAL, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_MINIMAL, &flags);
} else {
dfprintk(MOUNT, "sp4_mach_cred: disabled\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (test_bit(OP_CLOSE, sp->allow.u.longs) &&
@@ -7391,110 +7395,46 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
test_bit(OP_DELEGRETURN, sp->allow.u.longs) &&
test_bit(OP_LOCKU, sp->allow.u.longs)) {
dfprintk(MOUNT, " cleanup mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_CLEANUP, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_CLEANUP, &flags);
}
if (test_bit(OP_LAYOUTRETURN, sp->allow.u.longs)) {
dfprintk(MOUNT, " pnfs cleanup mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_PNFS_CLEANUP,
- &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_PNFS_CLEANUP, &flags);
}
if (test_bit(OP_SECINFO, sp->allow.u.longs) &&
test_bit(OP_SECINFO_NO_NAME, sp->allow.u.longs)) {
dfprintk(MOUNT, " secinfo mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_SECINFO, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_SECINFO, &flags);
}
if (test_bit(OP_TEST_STATEID, sp->allow.u.longs) &&
test_bit(OP_FREE_STATEID, sp->allow.u.longs)) {
dfprintk(MOUNT, " stateid mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_STATEID, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_STATEID, &flags);
}
if (test_bit(OP_WRITE, sp->allow.u.longs)) {
dfprintk(MOUNT, " write mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_WRITE, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_WRITE, &flags);
}
if (test_bit(OP_COMMIT, sp->allow.u.longs)) {
dfprintk(MOUNT, " commit mode enabled\n");
- set_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags);
+ __set_bit(NFS_SP4_MACH_CRED_COMMIT, &flags);
}
}
-
+out:
+ clp->cl_sp4_flags = flags;
return 0;
}
struct nfs41_exchange_id_data {
struct nfs41_exchange_id_res res;
struct nfs41_exchange_id_args args;
- struct rpc_xprt *xprt;
- int rpc_status;
};
-static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
-{
- struct nfs41_exchange_id_data *cdata =
- (struct nfs41_exchange_id_data *)data;
- struct nfs_client *clp = cdata->args.client;
- int status = task->tk_status;
-
- trace_nfs4_exchange_id(clp, status);
-
- if (status == 0)
- status = nfs4_check_cl_exchange_flags(cdata->res.flags);
-
- if (cdata->xprt && status == 0) {
- status = nfs4_detect_session_trunking(clp, &cdata->res,
- cdata->xprt);
- goto out;
- }
-
- if (status == 0)
- status = nfs4_sp4_select_mode(clp, &cdata->res.state_protect);
-
- if (status == 0) {
- clp->cl_clientid = cdata->res.clientid;
- clp->cl_exchange_flags = cdata->res.flags;
- clp->cl_seqid = cdata->res.seqid;
- /* Client ID is not confirmed */
- if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))
- clear_bit(NFS4_SESSION_ESTABLISHED,
- &clp->cl_session->session_state);
-
- kfree(clp->cl_serverowner);
- clp->cl_serverowner = cdata->res.server_owner;
- cdata->res.server_owner = NULL;
-
- /* use the most recent implementation id */
- kfree(clp->cl_implid);
- clp->cl_implid = cdata->res.impl_id;
- cdata->res.impl_id = NULL;
-
- if (clp->cl_serverscope != NULL &&
- !nfs41_same_server_scope(clp->cl_serverscope,
- cdata->res.server_scope)) {
- dprintk("%s: server_scope mismatch detected\n",
- __func__);
- set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
- kfree(clp->cl_serverscope);
- clp->cl_serverscope = NULL;
- }
-
- if (clp->cl_serverscope == NULL) {
- clp->cl_serverscope = cdata->res.server_scope;
- cdata->res.server_scope = NULL;
- }
- /* Save the EXCHANGE_ID verifier session trunk tests */
- memcpy(clp->cl_confirm.data, cdata->args.verifier.data,
- sizeof(clp->cl_confirm.data));
- }
-out:
- cdata->rpc_status = status;
- return;
-}
-
static void nfs4_exchange_id_release(void *data)
{
struct nfs41_exchange_id_data *cdata =
@@ -7508,7 +7448,6 @@ static void nfs4_exchange_id_release(void *data)
}
static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
- .rpc_call_done = nfs4_exchange_id_done,
.rpc_release = nfs4_exchange_id_release,
};
@@ -7517,7 +7456,8 @@ static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
*
* Wrapper for EXCHANGE_ID operation.
*/
-static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
+static struct rpc_task *
+nfs4_run_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
u32 sp4_how, struct rpc_xprt *xprt)
{
struct rpc_message msg = {
@@ -7531,17 +7471,15 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
.flags = RPC_TASK_TIMEOUT,
};
struct nfs41_exchange_id_data *calldata;
- struct rpc_task *task;
int status;
if (!atomic_inc_not_zero(&clp->cl_count))
- return -EIO;
+ return ERR_PTR(-EIO);
+ status = -ENOMEM;
calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
- if (!calldata) {
- nfs_put_client(clp);
- return -ENOMEM;
- }
+ if (!calldata)
+ goto out;
nfs4_init_boot_verifier(clp, &calldata->args.verifier);
@@ -7580,34 +7518,22 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
goto out_impl_id;
}
if (xprt) {
- calldata->xprt = xprt;
task_setup_data.rpc_xprt = xprt;
task_setup_data.flags |= RPC_TASK_SOFTCONN;
memcpy(calldata->args.verifier.data, clp->cl_confirm.data,
sizeof(calldata->args.verifier.data));
}
calldata->args.client = clp;
-#ifdef CONFIG_NFS_V4_1_MIGRATION
- calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
- EXCHGID4_FLAG_BIND_PRINC_STATEID |
- EXCHGID4_FLAG_SUPP_MOVED_MIGR,
-#else
calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
- EXCHGID4_FLAG_BIND_PRINC_STATEID,
+ EXCHGID4_FLAG_BIND_PRINC_STATEID;
+#ifdef CONFIG_NFS_V4_1_MIGRATION
+ calldata->args.flags |= EXCHGID4_FLAG_SUPP_MOVED_MIGR;
#endif
msg.rpc_argp = &calldata->args;
msg.rpc_resp = &calldata->res;
task_setup_data.callback_data = calldata;
- task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task))
- return PTR_ERR(task);
-
- status = calldata->rpc_status;
-
- rpc_put_task(task);
-out:
- return status;
+ return rpc_run_task(&task_setup_data);
out_impl_id:
kfree(calldata->res.impl_id);
@@ -7617,8 +7543,69 @@ out_server_owner:
kfree(calldata->res.server_owner);
out_calldata:
kfree(calldata);
+out:
nfs_put_client(clp);
- goto out;
+ return ERR_PTR(status);
+}
+
+/*
+ * _nfs4_proc_exchange_id()
+ *
+ * Wrapper for EXCHANGE_ID operation.
+ */
+static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
+ u32 sp4_how)
+{
+ struct rpc_task *task;
+ struct nfs41_exchange_id_args *argp;
+ struct nfs41_exchange_id_res *resp;
+ int status;
+
+ task = nfs4_run_exchange_id(clp, cred, sp4_how, NULL);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+
+ argp = task->tk_msg.rpc_argp;
+ resp = task->tk_msg.rpc_resp;
+ status = task->tk_status;
+ if (status != 0)
+ goto out;
+
+ status = nfs4_check_cl_exchange_flags(resp->flags);
+ if (status != 0)
+ goto out;
+
+ status = nfs4_sp4_select_mode(clp, &resp->state_protect);
+ if (status != 0)
+ goto out;
+
+ clp->cl_clientid = resp->clientid;
+ clp->cl_exchange_flags = resp->flags;
+ clp->cl_seqid = resp->seqid;
+ /* Client ID is not confirmed */
+ if (!(resp->flags & EXCHGID4_FLAG_CONFIRMED_R))
+ clear_bit(NFS4_SESSION_ESTABLISHED,
+ &clp->cl_session->session_state);
+
+ if (clp->cl_serverscope != NULL &&
+ !nfs41_same_server_scope(clp->cl_serverscope,
+ resp->server_scope)) {
+ dprintk("%s: server_scope mismatch detected\n",
+ __func__);
+ set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
+ }
+
+ swap(clp->cl_serverowner, resp->server_owner);
+ swap(clp->cl_serverscope, resp->server_scope);
+ swap(clp->cl_implid, resp->impl_id);
+
+ /* Save the EXCHANGE_ID verifier session trunk tests */
+ memcpy(clp->cl_confirm.data, argp->verifier.data,
+ sizeof(clp->cl_confirm.data));
+out:
+ trace_nfs4_exchange_id(clp, status);
+ rpc_put_task(task);
+ return status;
}
/*
@@ -7641,13 +7628,13 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
/* try SP4_MACH_CRED if krb5i/p */
if (authflavor == RPC_AUTH_GSS_KRB5I ||
authflavor == RPC_AUTH_GSS_KRB5P) {
- status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED, NULL);
+ status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED);
if (!status)
return 0;
}
/* try SP4_NONE */
- return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL);
+ return _nfs4_proc_exchange_id(clp, cred, SP4_NONE);
}
/**
@@ -7669,6 +7656,9 @@ int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
void *data)
{
struct nfs4_add_xprt_data *adata = (struct nfs4_add_xprt_data *)data;
+ struct rpc_task *task;
+ int status;
+
u32 sp4_how;
dprintk("--> %s try %s\n", __func__,
@@ -7677,7 +7667,17 @@ int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED);
/* Test connection for session trunking. Async exchange_id call */
- return _nfs4_proc_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
+ task = nfs4_run_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+
+ status = task->tk_status;
+ if (status == 0)
+ status = nfs4_detect_session_trunking(adata->clp,
+ task->tk_msg.rpc_resp, xprt);
+
+ rpc_put_task(task);
+ return status;
}
EXPORT_SYMBOL_GPL(nfs4_test_session_trunk);