NFSv4: Record the OPEN create mode used in the nfs4_opendata structure
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 16 Apr 2013 22:42:34 +0000 (18:42 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 16 Apr 2013 22:58:26 +0000 (18:58 -0400)
If we're doing NFSv4.1 against a server that has persistent sessions,
then we should not need to call SETATTR in order to reset the file
attributes immediately after doing an exclusive create.

Note that since the create mode depends on the type of session that
has been negotiated with the server, we should not choose the
mode until after we've got a session slot.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h

index af05df3c7c79398d8b22df2924b0e9d7f0517392..282d9fa6994af716a44a0c9792a205f776713f95 100644 (file)
@@ -1525,6 +1525,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
        struct nfs4_state_owner *sp = data->owner;
+       struct nfs_client *clp = sp->so_server->nfs_client;
 
        if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
                goto out_wait;
@@ -1545,7 +1546,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
                rcu_read_unlock();
        }
        /* Update client id. */
-       data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
+       data->o_arg.clientid = clp->cl_clientid;
        if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
                data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
@@ -1557,6 +1558,16 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
                                &data->o_res.seq_res,
                                task) != 0)
                nfs_release_seqid(data->o_arg.seqid);
+
+       /* Set the create mode (note dependency on the session type) */
+       data->o_arg.createmode = NFS4_CREATE_UNCHECKED;
+       if (data->o_arg.open_flags & O_EXCL) {
+               data->o_arg.createmode = NFS4_CREATE_EXCLUSIVE;
+               if (nfs4_has_persistent_session(clp))
+                       data->o_arg.createmode = NFS4_CREATE_GUARDED;
+               else if (clp->cl_mvops->minor_version > 0)
+                       data->o_arg.createmode = NFS4_CREATE_EXCLUSIVE4_1;
+       }
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -2000,7 +2011,8 @@ static int _nfs4_do_open(struct inode *dir,
        if (status != 0)
                goto err_opendata_put;
 
-       if (opendata->o_arg.open_flags & O_EXCL) {
+       if ((opendata->o_arg.open_flags & O_EXCL) &&
+           (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
                nfs4_exclusive_attrset(opendata, sattr);
 
                nfs_fattr_init(opendata->o_res.f_attr);
index 0b744895b9e19e80841abd899f6937585d1d209e..fef71cbec501845ab386632656d06c74a6edc99f 100644 (file)
@@ -1366,33 +1366,28 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
 
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 {
+       struct iattr dummy;
        __be32 *p;
-       struct nfs_client *clp;
 
        p = reserve_space(xdr, 4);
-       switch(arg->open_flags & O_EXCL) {
-       case 0:
+       switch(arg->createmode) {
+       case NFS4_CREATE_UNCHECKED:
                *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
                encode_attrs(xdr, arg->u.attrs, arg->server);
                break;
-       default:
-               clp = arg->server->nfs_client;
-               if (clp->cl_mvops->minor_version > 0) {
-                       if (nfs4_has_persistent_session(clp)) {
-                               *p = cpu_to_be32(NFS4_CREATE_GUARDED);
-                               encode_attrs(xdr, arg->u.attrs, arg->server);
-                       } else {
-                               struct iattr dummy;
-
-                               *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
-                               encode_nfs4_verifier(xdr, &arg->u.verifier);
-                               dummy.ia_valid = 0;
-                               encode_attrs(xdr, &dummy, arg->server);
-                       }
-               } else {
-                       *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
-                       encode_nfs4_verifier(xdr, &arg->u.verifier);
-               }
+       case NFS4_CREATE_GUARDED:
+               *p = cpu_to_be32(NFS4_CREATE_GUARDED);
+               encode_attrs(xdr, arg->u.attrs, arg->server);
+               break;
+       case NFS4_CREATE_EXCLUSIVE:
+               *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
+               encode_nfs4_verifier(xdr, &arg->u.verifier);
+               break;
+       case NFS4_CREATE_EXCLUSIVE4_1:
+               *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
+               encode_nfs4_verifier(xdr, &arg->u.verifier);
+               dummy.ia_valid = 0;
+               encode_attrs(xdr, &dummy, arg->server);
        }
 }
 
index 90a4aa190b439aab06b7ba0d87e05b6aac462383..bdc100f66dfbe38311506d5d3ce5e6364b06db29 100644 (file)
@@ -349,6 +349,7 @@ struct nfs_openargs {
        const u32 *             bitmask;
        const u32 *             open_bitmap;
        __u32                   claim;
+       enum createmode4        createmode;
 };
 
 struct nfs_openres {