nfsd41: CREATE_EXCLUSIVE4_1
authorBenny Halevy <bhalevy@panasas.com>
Fri, 3 Apr 2009 05:29:17 +0000 (08:29 +0300)
committerJ. Bruce Fields <bfields@citi.umich.edu>
Sat, 4 Apr 2009 00:41:23 +0000 (17:41 -0700)
Implement the CREATE_EXCLUSIVE4_1 open mode conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26

This mode allows the client to atomically create a file
if it doesn't exist while setting some of its attributes.

It must be implemented if the server supports persistent
reply cache and/or pnfs.

Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c
include/linux/nfs4.h
include/linux/nfsd/xdr4.h

index e206053433e3cefcda5ceca21144ee0f7047dcce..b2883e9c6381f22b51bc788174d149a20a5e2e54 100644 (file)
@@ -93,6 +93,21 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
        open->op_truncate = 0;
 
        if (open->op_create) {
+               /* FIXME: check session persistence and pnfs flags.
+                * The nfsv4.1 spec requires the following semantics:
+                *
+                * Persistent   | pNFS   | Server REQUIRED | Client Allowed
+                * Reply Cache  | server |                 |
+                * -------------+--------+-----------------+--------------------
+                * no           | no     | EXCLUSIVE4_1    | EXCLUSIVE4_1
+                *              |        |                 | (SHOULD)
+                *              |        | and EXCLUSIVE4  | or EXCLUSIVE4
+                *              |        |                 | (SHOULD NOT)
+                * no           | yes    | EXCLUSIVE4_1    | EXCLUSIVE4_1
+                * yes          | no     | GUARDED4        | GUARDED4
+                * yes          | yes    | GUARDED4        | GUARDED4
+                */
+
                /*
                 * Note: create modes (UNCHECKED,GUARDED...) are the same
                 * in NFSv4 as in v3.
index 533d14fec99e9dbe8ffe7358e7456f2ab280cf7e..b820c311931c8e7d73218f6aae5cbcfe2bbe4993 100644 (file)
@@ -260,6 +260,12 @@ static u32 nfsd_attrmask[] = {
        NFSD_WRITEABLE_ATTRS_WORD2
 };
 
+static u32 nfsd41_ex_attrmask[] = {
+       NFSD_SUPPATTR_EXCLCREAT_WORD0,
+       NFSD_SUPPATTR_EXCLCREAT_WORD1,
+       NFSD_SUPPATTR_EXCLCREAT_WORD2
+};
+
 static __be32
 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
                   struct iattr *iattr, struct nfs4_acl **acl)
@@ -684,6 +690,17 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
                        READ_BUF(8);
                        COPYMEM(open->op_verf.data, 8);
                        break;
+               case NFS4_CREATE_EXCLUSIVE4_1:
+                       if (argp->minorversion < 1)
+                               goto xdr_error;
+                       READ_BUF(8);
+                       COPYMEM(open->op_verf.data, 8);
+                       status = nfsd4_decode_fattr(argp, open->op_bmval,
+                               nfsd41_ex_attrmask, &open->op_iattr,
+                               &open->op_acl);
+                       if (status)
+                               goto out;
+                       break;
                default:
                        goto xdr_error;
                }
index ec3cd49b04f5ce2197e897ab828a5e58fecb8ce2..e3f0cbcbd0db8179e6055b59411c2d64550d5db2 100644 (file)
@@ -368,7 +368,13 @@ enum opentype4 {
 enum createmode4 {
        NFS4_CREATE_UNCHECKED = 0,
        NFS4_CREATE_GUARDED = 1,
-       NFS4_CREATE_EXCLUSIVE = 2
+       NFS4_CREATE_EXCLUSIVE = 2,
+       /*
+        * New to NFSv4.1. If session is persistent,
+        * GUARDED4 MUST be used. Otherwise, use
+        * EXCLUSIVE4_1 instead of EXCLUSIVE4.
+        */
+       NFS4_CREATE_EXCLUSIVE4_1 = 3
 };
 
 enum limit_by4 {
index c07d8fe7bb07924f09ee8bac9b3fee295f4b7f5a..f80d6013fdc34ef3d19fc5910d3a49768f3c625c 100644 (file)
@@ -219,10 +219,8 @@ struct nfsd4_open {
        u32             op_create;          /* request */
        u32             op_createmode;      /* request */
        u32             op_bmval[3];        /* request */
-       union {                             /* request */
-               struct iattr    iattr;                      /* UNCHECKED4,GUARDED4 */
-               nfs4_verifier   verf;                                /* EXCLUSIVE4 */
-       } u;
+       struct iattr    iattr;              /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
+       nfs4_verifier   verf;               /* EXCLUSIVE4 */
        clientid_t      op_clientid;        /* request */
        struct xdr_netobj op_owner;           /* request */
        u32             op_seqid;           /* request */
@@ -236,8 +234,8 @@ struct nfsd4_open {
        struct nfs4_stateowner *op_stateowner; /* used during processing */
        struct nfs4_acl *op_acl;
 };
-#define op_iattr       u.iattr
-#define op_verf                u.verf
+#define op_iattr       iattr
+#define op_verf                verf
 
 struct nfsd4_open_confirm {
        stateid_t       oc_req_stateid          /* request */;