NFS: Add COPY nfs operation
[deliverable/linux.git] / fs / nfs / nfs4proc.c
index 14881594dd07b9944a494d388722f4acf4b5457a..4e83385ea6a962845169e0f9e0155dc6c16376d6 100644 (file)
@@ -2461,14 +2461,15 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
 
        dentry = opendata->dentry;
        if (d_really_is_negative(dentry)) {
-               /* FIXME: Is this d_drop() ever needed? */
+               struct dentry *alias;
                d_drop(dentry);
-               dentry = d_add_unique(dentry, igrab(state->inode));
-               if (dentry == NULL) {
-                       dentry = opendata->dentry;
-               } else {
+               alias = d_exact_alias(dentry, state->inode);
+               if (!alias)
+                       alias = d_splice_alias(igrab(state->inode), dentry);
+               /* d_splice_alias() can't fail here - it's a non-directory */
+               if (alias) {
                        dput(ctx->dentry);
-                       ctx->dentry = dentry;
+                       ctx->dentry = dentry = alias;
                }
                nfs_set_verifier(dentry,
                                nfs_save_change_attribute(d_inode(opendata->dir)));
@@ -6053,6 +6054,7 @@ static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *reques
 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
        struct nfs_inode *nfsi = NFS_I(state->inode);
+       struct nfs4_state_owner *sp = state->owner;
        unsigned char fl_flags = request->fl_flags;
        int status = -ENOLCK;
 
@@ -6067,6 +6069,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
        status = do_vfs_lock(state->inode, request);
        if (status < 0)
                goto out;
+       mutex_lock(&sp->so_delegreturn_mutex);
        down_read(&nfsi->rwsem);
        if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
                /* Yes: cache locks! */
@@ -6074,9 +6077,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
                request->fl_flags = fl_flags & ~FL_SLEEP;
                status = do_vfs_lock(state->inode, request);
                up_read(&nfsi->rwsem);
+               mutex_unlock(&sp->so_delegreturn_mutex);
                goto out;
        }
        up_read(&nfsi->rwsem);
+       mutex_unlock(&sp->so_delegreturn_mutex);
        status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
 out:
        request->fl_flags = fl_flags;
@@ -6782,13 +6787,26 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
        return false;
 }
 
+static void
+nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
+{
+}
+
+static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = {
+       .rpc_call_done =  &nfs4_bind_one_conn_to_session_done,
+};
+
 /*
- * nfs4_proc_bind_conn_to_session()
+ * nfs4_proc_bind_one_conn_to_session()
  *
  * The 4.1 client currently uses the same TCP connection for the
  * fore and backchannel.
  */
-int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
+static
+int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
+               struct rpc_xprt *xprt,
+               struct nfs_client *clp,
+               struct rpc_cred *cred)
 {
        int status;
        struct nfs41_bind_conn_to_session_args args = {
@@ -6803,6 +6821,14 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred
                .rpc_resp = &res,
                .rpc_cred = cred,
        };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = clnt,
+               .rpc_xprt = xprt,
+               .callback_ops = &nfs4_bind_one_conn_to_session_ops,
+               .rpc_message = &msg,
+               .flags = RPC_TASK_TIMEOUT,
+       };
+       struct rpc_task *task;
 
        dprintk("--> %s\n", __func__);
 
@@ -6810,7 +6836,16 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred
        if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
                args.dir = NFS4_CDFC4_FORE;
 
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
+       /* Do not set the backchannel flag unless this is clnt->cl_xprt */
+       if (xprt != rcu_access_pointer(clnt->cl_xprt))
+               args.dir = NFS4_CDFC4_FORE;
+
+       task = rpc_run_task(&task_setup_data);
+       if (!IS_ERR(task)) {
+               status = task->tk_status;
+               rpc_put_task(task);
+       } else
+               status = PTR_ERR(task);
        trace_nfs4_bind_conn_to_session(clp, status);
        if (status == 0) {
                if (memcmp(res.sessionid.data,
@@ -6837,6 +6872,31 @@ out:
        return status;
 }
 
+struct rpc_bind_conn_calldata {
+       struct nfs_client *clp;
+       struct rpc_cred *cred;
+};
+
+static int
+nfs4_proc_bind_conn_to_session_callback(struct rpc_clnt *clnt,
+               struct rpc_xprt *xprt,
+               void *calldata)
+{
+       struct rpc_bind_conn_calldata *p = calldata;
+
+       return nfs4_proc_bind_one_conn_to_session(clnt, xprt, p->clp, p->cred);
+}
+
+int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
+{
+       struct rpc_bind_conn_calldata data = {
+               .clp = clp,
+               .cred = cred,
+       };
+       return rpc_clnt_iterate_for_each_xprt(clp->cl_rpcclient,
+                       nfs4_proc_bind_conn_to_session_callback, &data);
+}
+
 /*
  * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map
  * and operations we'd like to see to enable certain features in the allow map
@@ -7319,7 +7379,7 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
        args->bc_attrs.max_resp_sz = PAGE_SIZE;
        args->bc_attrs.max_resp_sz_cached = 0;
        args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
-       args->bc_attrs.max_reqs = 1;
+       args->bc_attrs.max_reqs = NFS41_BC_MAX_CALLBACKS;
 
        dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
                "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
@@ -8737,6 +8797,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
                | NFS_CAP_STATEID_NFSV41
                | NFS_CAP_ATOMIC_OPEN_V1
                | NFS_CAP_ALLOCATE
+               | NFS_CAP_COPY
                | NFS_CAP_DEALLOCATE
                | NFS_CAP_SEEK
                | NFS_CAP_LAYOUTSTATS
This page took 0.033013 seconds and 5 git commands to generate.