diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 76 |
1 files changed, 66 insertions, 10 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 14881594dd07..327b8c34d360 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2461,14 +2461,15 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2461 | 2461 | ||
2462 | dentry = opendata->dentry; | 2462 | dentry = opendata->dentry; |
2463 | if (d_really_is_negative(dentry)) { | 2463 | if (d_really_is_negative(dentry)) { |
2464 | /* FIXME: Is this d_drop() ever needed? */ | 2464 | struct dentry *alias; |
2465 | d_drop(dentry); | 2465 | d_drop(dentry); |
2466 | dentry = d_add_unique(dentry, igrab(state->inode)); | 2466 | alias = d_exact_alias(dentry, state->inode); |
2467 | if (dentry == NULL) { | 2467 | if (!alias) |
2468 | dentry = opendata->dentry; | 2468 | alias = d_splice_alias(igrab(state->inode), dentry); |
2469 | } else { | 2469 | /* d_splice_alias() can't fail here - it's a non-directory */ |
2470 | if (alias) { | ||
2470 | dput(ctx->dentry); | 2471 | dput(ctx->dentry); |
2471 | ctx->dentry = dentry; | 2472 | ctx->dentry = dentry = alias; |
2472 | } | 2473 | } |
2473 | nfs_set_verifier(dentry, | 2474 | nfs_set_verifier(dentry, |
2474 | nfs_save_change_attribute(d_inode(opendata->dir))); | 2475 | nfs_save_change_attribute(d_inode(opendata->dir))); |
@@ -6782,13 +6783,26 @@ nfs41_same_server_scope(struct nfs41_server_scope *a, | |||
6782 | return false; | 6783 | return false; |
6783 | } | 6784 | } |
6784 | 6785 | ||
6786 | static void | ||
6787 | nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata) | ||
6788 | { | ||
6789 | } | ||
6790 | |||
6791 | static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = { | ||
6792 | .rpc_call_done = &nfs4_bind_one_conn_to_session_done, | ||
6793 | }; | ||
6794 | |||
6785 | /* | 6795 | /* |
6786 | * nfs4_proc_bind_conn_to_session() | 6796 | * nfs4_proc_bind_one_conn_to_session() |
6787 | * | 6797 | * |
6788 | * The 4.1 client currently uses the same TCP connection for the | 6798 | * The 4.1 client currently uses the same TCP connection for the |
6789 | * fore and backchannel. | 6799 | * fore and backchannel. |
6790 | */ | 6800 | */ |
6791 | int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred) | 6801 | static |
6802 | int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt, | ||
6803 | struct rpc_xprt *xprt, | ||
6804 | struct nfs_client *clp, | ||
6805 | struct rpc_cred *cred) | ||
6792 | { | 6806 | { |
6793 | int status; | 6807 | int status; |
6794 | struct nfs41_bind_conn_to_session_args args = { | 6808 | struct nfs41_bind_conn_to_session_args args = { |
@@ -6803,6 +6817,14 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
6803 | .rpc_resp = &res, | 6817 | .rpc_resp = &res, |
6804 | .rpc_cred = cred, | 6818 | .rpc_cred = cred, |
6805 | }; | 6819 | }; |
6820 | struct rpc_task_setup task_setup_data = { | ||
6821 | .rpc_client = clnt, | ||
6822 | .rpc_xprt = xprt, | ||
6823 | .callback_ops = &nfs4_bind_one_conn_to_session_ops, | ||
6824 | .rpc_message = &msg, | ||
6825 | .flags = RPC_TASK_TIMEOUT, | ||
6826 | }; | ||
6827 | struct rpc_task *task; | ||
6806 | 6828 | ||
6807 | dprintk("--> %s\n", __func__); | 6829 | dprintk("--> %s\n", __func__); |
6808 | 6830 | ||
@@ -6810,7 +6832,16 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
6810 | if (!(clp->cl_session->flags & SESSION4_BACK_CHAN)) | 6832 | if (!(clp->cl_session->flags & SESSION4_BACK_CHAN)) |
6811 | args.dir = NFS4_CDFC4_FORE; | 6833 | args.dir = NFS4_CDFC4_FORE; |
6812 | 6834 | ||
6813 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 6835 | /* Do not set the backchannel flag unless this is clnt->cl_xprt */ |
6836 | if (xprt != rcu_access_pointer(clnt->cl_xprt)) | ||
6837 | args.dir = NFS4_CDFC4_FORE; | ||
6838 | |||
6839 | task = rpc_run_task(&task_setup_data); | ||
6840 | if (!IS_ERR(task)) { | ||
6841 | status = task->tk_status; | ||
6842 | rpc_put_task(task); | ||
6843 | } else | ||
6844 | status = PTR_ERR(task); | ||
6814 | trace_nfs4_bind_conn_to_session(clp, status); | 6845 | trace_nfs4_bind_conn_to_session(clp, status); |
6815 | if (status == 0) { | 6846 | if (status == 0) { |
6816 | if (memcmp(res.sessionid.data, | 6847 | if (memcmp(res.sessionid.data, |
@@ -6837,6 +6868,31 @@ out: | |||
6837 | return status; | 6868 | return status; |
6838 | } | 6869 | } |
6839 | 6870 | ||
6871 | struct rpc_bind_conn_calldata { | ||
6872 | struct nfs_client *clp; | ||
6873 | struct rpc_cred *cred; | ||
6874 | }; | ||
6875 | |||
6876 | static int | ||
6877 | nfs4_proc_bind_conn_to_session_callback(struct rpc_clnt *clnt, | ||
6878 | struct rpc_xprt *xprt, | ||
6879 | void *calldata) | ||
6880 | { | ||
6881 | struct rpc_bind_conn_calldata *p = calldata; | ||
6882 | |||
6883 | return nfs4_proc_bind_one_conn_to_session(clnt, xprt, p->clp, p->cred); | ||
6884 | } | ||
6885 | |||
6886 | int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred) | ||
6887 | { | ||
6888 | struct rpc_bind_conn_calldata data = { | ||
6889 | .clp = clp, | ||
6890 | .cred = cred, | ||
6891 | }; | ||
6892 | return rpc_clnt_iterate_for_each_xprt(clp->cl_rpcclient, | ||
6893 | nfs4_proc_bind_conn_to_session_callback, &data); | ||
6894 | } | ||
6895 | |||
6840 | /* | 6896 | /* |
6841 | * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map | 6897 | * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map |
6842 | * and operations we'd like to see to enable certain features in the allow map | 6898 | * and operations we'd like to see to enable certain features in the allow map |
@@ -7319,7 +7375,7 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
7319 | args->bc_attrs.max_resp_sz = PAGE_SIZE; | 7375 | args->bc_attrs.max_resp_sz = PAGE_SIZE; |
7320 | args->bc_attrs.max_resp_sz_cached = 0; | 7376 | args->bc_attrs.max_resp_sz_cached = 0; |
7321 | args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS; | 7377 | args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS; |
7322 | args->bc_attrs.max_reqs = 1; | 7378 | args->bc_attrs.max_reqs = NFS41_BC_MAX_CALLBACKS; |
7323 | 7379 | ||
7324 | dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u " | 7380 | dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u " |
7325 | "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", | 7381 | "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n", |