diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 171 |
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, | |||
7403 | struct nfs41_exchange_id_data { | 7403 | struct 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 | ||
7410 | static 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 | } | ||
7467 | out: | ||
7468 | cdata->rpc_status = status; | ||
7469 | return; | ||
7470 | } | ||
7471 | |||
7472 | static void nfs4_exchange_id_release(void *data) | 7408 | static 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 | ||
7484 | static const struct rpc_call_ops nfs4_exchange_id_call_ops = { | 7420 | static 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 | */ |
7494 | static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, | 7429 | static struct rpc_task * |
7430 | nfs4_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); | ||
7583 | out: | ||
7584 | return status; | ||
7585 | 7510 | ||
7586 | out_impl_id: | 7511 | out_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); |
7592 | out_calldata: | 7517 | out_calldata: |
7593 | kfree(calldata); | 7518 | kfree(calldata); |
7519 | out: | ||
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 | */ | ||
7529 | static 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)); | ||
7578 | out: | ||
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 | } |
7656 | EXPORT_SYMBOL_GPL(nfs4_test_session_trunk); | 7655 | EXPORT_SYMBOL_GPL(nfs4_test_session_trunk); |
7657 | 7656 | ||