aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c171
1 files changed, 85 insertions, 86 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ffd2e712595d..34190c2c0900 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7403,72 +7403,8 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
7403struct nfs41_exchange_id_data { 7403struct nfs41_exchange_id_data {
7404 struct nfs41_exchange_id_res res; 7404 struct nfs41_exchange_id_res res;
7405 struct nfs41_exchange_id_args args; 7405 struct nfs41_exchange_id_args args;
7406 struct rpc_xprt *xprt;
7407 int rpc_status;
7408}; 7406};
7409 7407
7410static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
7411{
7412 struct nfs41_exchange_id_data *cdata =
7413 (struct nfs41_exchange_id_data *)data;
7414 struct nfs_client *clp = cdata->args.client;
7415 int status = task->tk_status;
7416
7417 trace_nfs4_exchange_id(clp, status);
7418
7419 if (status == 0)
7420 status = nfs4_check_cl_exchange_flags(cdata->res.flags);
7421
7422 if (cdata->xprt && status == 0) {
7423 status = nfs4_detect_session_trunking(clp, &cdata->res,
7424 cdata->xprt);
7425 goto out;
7426 }
7427
7428 if (status == 0)
7429 status = nfs4_sp4_select_mode(clp, &cdata->res.state_protect);
7430
7431 if (status == 0) {
7432 clp->cl_clientid = cdata->res.clientid;
7433 clp->cl_exchange_flags = cdata->res.flags;
7434 clp->cl_seqid = cdata->res.seqid;
7435 /* Client ID is not confirmed */
7436 if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))
7437 clear_bit(NFS4_SESSION_ESTABLISHED,
7438 &clp->cl_session->session_state);
7439
7440 kfree(clp->cl_serverowner);
7441 clp->cl_serverowner = cdata->res.server_owner;
7442 cdata->res.server_owner = NULL;
7443
7444 /* use the most recent implementation id */
7445 kfree(clp->cl_implid);
7446 clp->cl_implid = cdata->res.impl_id;
7447 cdata->res.impl_id = NULL;
7448
7449 if (clp->cl_serverscope != NULL &&
7450 !nfs41_same_server_scope(clp->cl_serverscope,
7451 cdata->res.server_scope)) {
7452 dprintk("%s: server_scope mismatch detected\n",
7453 __func__);
7454 set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
7455 kfree(clp->cl_serverscope);
7456 clp->cl_serverscope = NULL;
7457 }
7458
7459 if (clp->cl_serverscope == NULL) {
7460 clp->cl_serverscope = cdata->res.server_scope;
7461 cdata->res.server_scope = NULL;
7462 }
7463 /* Save the EXCHANGE_ID verifier session trunk tests */
7464 memcpy(clp->cl_confirm.data, cdata->args.verifier.data,
7465 sizeof(clp->cl_confirm.data));
7466 }
7467out:
7468 cdata->rpc_status = status;
7469 return;
7470}
7471
7472static void nfs4_exchange_id_release(void *data) 7408static void nfs4_exchange_id_release(void *data)
7473{ 7409{
7474 struct nfs41_exchange_id_data *cdata = 7410 struct nfs41_exchange_id_data *cdata =
@@ -7482,7 +7418,6 @@ static void nfs4_exchange_id_release(void *data)
7482} 7418}
7483 7419
7484static const struct rpc_call_ops nfs4_exchange_id_call_ops = { 7420static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
7485 .rpc_call_done = nfs4_exchange_id_done,
7486 .rpc_release = nfs4_exchange_id_release, 7421 .rpc_release = nfs4_exchange_id_release,
7487}; 7422};
7488 7423
@@ -7491,7 +7426,8 @@ static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
7491 * 7426 *
7492 * Wrapper for EXCHANGE_ID operation. 7427 * Wrapper for EXCHANGE_ID operation.
7493 */ 7428 */
7494static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, 7429static struct rpc_task *
7430nfs4_run_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7495 u32 sp4_how, struct rpc_xprt *xprt) 7431 u32 sp4_how, struct rpc_xprt *xprt)
7496{ 7432{
7497 struct rpc_message msg = { 7433 struct rpc_message msg = {
@@ -7505,17 +7441,15 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7505 .flags = RPC_TASK_TIMEOUT, 7441 .flags = RPC_TASK_TIMEOUT,
7506 }; 7442 };
7507 struct nfs41_exchange_id_data *calldata; 7443 struct nfs41_exchange_id_data *calldata;
7508 struct rpc_task *task;
7509 int status; 7444 int status;
7510 7445
7511 if (!atomic_inc_not_zero(&clp->cl_count)) 7446 if (!atomic_inc_not_zero(&clp->cl_count))
7512 return -EIO; 7447 return ERR_PTR(-EIO);
7513 7448
7449 status = -ENOMEM;
7514 calldata = kzalloc(sizeof(*calldata), GFP_NOFS); 7450 calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
7515 if (!calldata) { 7451 if (!calldata)
7516 nfs_put_client(clp); 7452 goto out;
7517 return -ENOMEM;
7518 }
7519 7453
7520 nfs4_init_boot_verifier(clp, &calldata->args.verifier); 7454 nfs4_init_boot_verifier(clp, &calldata->args.verifier);
7521 7455
@@ -7554,7 +7488,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7554 goto out_impl_id; 7488 goto out_impl_id;
7555 } 7489 }
7556 if (xprt) { 7490 if (xprt) {
7557 calldata->xprt = xprt;
7558 task_setup_data.rpc_xprt = xprt; 7491 task_setup_data.rpc_xprt = xprt;
7559 task_setup_data.flags |= RPC_TASK_SOFTCONN; 7492 task_setup_data.flags |= RPC_TASK_SOFTCONN;
7560 memcpy(calldata->args.verifier.data, clp->cl_confirm.data, 7493 memcpy(calldata->args.verifier.data, clp->cl_confirm.data,
@@ -7573,15 +7506,7 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7573 msg.rpc_resp = &calldata->res; 7506 msg.rpc_resp = &calldata->res;
7574 task_setup_data.callback_data = calldata; 7507 task_setup_data.callback_data = calldata;
7575 7508
7576 task = rpc_run_task(&task_setup_data); 7509 return rpc_run_task(&task_setup_data);
7577 if (IS_ERR(task))
7578 return PTR_ERR(task);
7579
7580 status = calldata->rpc_status;
7581
7582 rpc_put_task(task);
7583out:
7584 return status;
7585 7510
7586out_impl_id: 7511out_impl_id:
7587 kfree(calldata->res.impl_id); 7512 kfree(calldata->res.impl_id);
@@ -7591,8 +7516,69 @@ out_server_owner:
7591 kfree(calldata->res.server_owner); 7516 kfree(calldata->res.server_owner);
7592out_calldata: 7517out_calldata:
7593 kfree(calldata); 7518 kfree(calldata);
7519out:
7594 nfs_put_client(clp); 7520 nfs_put_client(clp);
7595 goto out; 7521 return ERR_PTR(status);
7522}
7523
7524/*
7525 * _nfs4_proc_exchange_id()
7526 *
7527 * Wrapper for EXCHANGE_ID operation.
7528 */
7529static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7530 u32 sp4_how)
7531{
7532 struct rpc_task *task;
7533 struct nfs41_exchange_id_args *argp;
7534 struct nfs41_exchange_id_res *resp;
7535 int status;
7536
7537 task = nfs4_run_exchange_id(clp, cred, sp4_how, NULL);
7538 if (IS_ERR(task))
7539 return PTR_ERR(task);
7540
7541 argp = task->tk_msg.rpc_argp;
7542 resp = task->tk_msg.rpc_resp;
7543 status = task->tk_status;
7544 if (status != 0)
7545 goto out;
7546
7547 status = nfs4_check_cl_exchange_flags(resp->flags);
7548 if (status != 0)
7549 goto out;
7550
7551 status = nfs4_sp4_select_mode(clp, &resp->state_protect);
7552 if (status != 0)
7553 goto out;
7554
7555 clp->cl_clientid = resp->clientid;
7556 clp->cl_exchange_flags = resp->flags;
7557 clp->cl_seqid = resp->seqid;
7558 /* Client ID is not confirmed */
7559 if (!(resp->flags & EXCHGID4_FLAG_CONFIRMED_R))
7560 clear_bit(NFS4_SESSION_ESTABLISHED,
7561 &clp->cl_session->session_state);
7562
7563 if (clp->cl_serverscope != NULL &&
7564 !nfs41_same_server_scope(clp->cl_serverscope,
7565 resp->server_scope)) {
7566 dprintk("%s: server_scope mismatch detected\n",
7567 __func__);
7568 set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
7569 }
7570
7571 swap(clp->cl_serverowner, resp->server_owner);
7572 swap(clp->cl_serverscope, resp->server_scope);
7573 swap(clp->cl_implid, resp->impl_id);
7574
7575 /* Save the EXCHANGE_ID verifier session trunk tests */
7576 memcpy(clp->cl_confirm.data, argp->verifier.data,
7577 sizeof(clp->cl_confirm.data));
7578out:
7579 trace_nfs4_exchange_id(clp, status);
7580 rpc_put_task(task);
7581 return status;
7596} 7582}
7597 7583
7598/* 7584/*
@@ -7615,13 +7601,13 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
7615 /* try SP4_MACH_CRED if krb5i/p */ 7601 /* try SP4_MACH_CRED if krb5i/p */
7616 if (authflavor == RPC_AUTH_GSS_KRB5I || 7602 if (authflavor == RPC_AUTH_GSS_KRB5I ||
7617 authflavor == RPC_AUTH_GSS_KRB5P) { 7603 authflavor == RPC_AUTH_GSS_KRB5P) {
7618 status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED, NULL); 7604 status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED);
7619 if (!status) 7605 if (!status)
7620 return 0; 7606 return 0;
7621 } 7607 }
7622 7608
7623 /* try SP4_NONE */ 7609 /* try SP4_NONE */
7624 return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL); 7610 return _nfs4_proc_exchange_id(clp, cred, SP4_NONE);
7625} 7611}
7626 7612
7627/** 7613/**
@@ -7643,6 +7629,9 @@ int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
7643 void *data) 7629 void *data)
7644{ 7630{
7645 struct nfs4_add_xprt_data *adata = (struct nfs4_add_xprt_data *)data; 7631 struct nfs4_add_xprt_data *adata = (struct nfs4_add_xprt_data *)data;
7632 struct rpc_task *task;
7633 int status;
7634
7646 u32 sp4_how; 7635 u32 sp4_how;
7647 7636
7648 dprintk("--> %s try %s\n", __func__, 7637 dprintk("--> %s try %s\n", __func__,
@@ -7651,7 +7640,17 @@ int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
7651 sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED); 7640 sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED);
7652 7641
7653 /* Test connection for session trunking. Async exchange_id call */ 7642 /* Test connection for session trunking. Async exchange_id call */
7654 return _nfs4_proc_exchange_id(adata->clp, adata->cred, sp4_how, xprt); 7643 task = nfs4_run_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
7644 if (IS_ERR(task))
7645 return PTR_ERR(task);
7646
7647 status = task->tk_status;
7648 if (status == 0)
7649 status = nfs4_detect_session_trunking(adata->clp,
7650 task->tk_msg.rpc_resp, xprt);
7651
7652 rpc_put_task(task);
7653 return status;
7655} 7654}
7656EXPORT_SYMBOL_GPL(nfs4_test_session_trunk); 7655EXPORT_SYMBOL_GPL(nfs4_test_session_trunk);
7657 7656