Commit 79fb54ab authored by Benny Halevy's avatar Benny Halevy Committed by J. Bruce Fields

nfsd41: CREATE_EXCLUSIVE4_1

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: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 8c18f205
...@@ -93,6 +93,21 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o ...@@ -93,6 +93,21 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
open->op_truncate = 0; open->op_truncate = 0;
if (open->op_create) { 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 * Note: create modes (UNCHECKED,GUARDED...) are the same
* in NFSv4 as in v3. * in NFSv4 as in v3.
......
...@@ -260,6 +260,12 @@ static u32 nfsd_attrmask[] = { ...@@ -260,6 +260,12 @@ static u32 nfsd_attrmask[] = {
NFSD_WRITEABLE_ATTRS_WORD2 NFSD_WRITEABLE_ATTRS_WORD2
}; };
static u32 nfsd41_ex_attrmask[] = {
NFSD_SUPPATTR_EXCLCREAT_WORD0,
NFSD_SUPPATTR_EXCLCREAT_WORD1,
NFSD_SUPPATTR_EXCLCREAT_WORD2
};
static __be32 static __be32
nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable, nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
struct iattr *iattr, struct nfs4_acl **acl) struct iattr *iattr, struct nfs4_acl **acl)
...@@ -684,6 +690,17 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) ...@@ -684,6 +690,17 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
READ_BUF(8); READ_BUF(8);
COPYMEM(open->op_verf.data, 8); COPYMEM(open->op_verf.data, 8);
break; 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: default:
goto xdr_error; goto xdr_error;
} }
......
...@@ -368,7 +368,13 @@ enum opentype4 { ...@@ -368,7 +368,13 @@ enum opentype4 {
enum createmode4 { enum createmode4 {
NFS4_CREATE_UNCHECKED = 0, NFS4_CREATE_UNCHECKED = 0,
NFS4_CREATE_GUARDED = 1, 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 { enum limit_by4 {
......
...@@ -219,10 +219,8 @@ struct nfsd4_open { ...@@ -219,10 +219,8 @@ struct nfsd4_open {
u32 op_create; /* request */ u32 op_create; /* request */
u32 op_createmode; /* request */ u32 op_createmode; /* request */
u32 op_bmval[3]; /* request */ u32 op_bmval[3]; /* request */
union { /* request */ struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
struct iattr iattr; /* UNCHECKED4,GUARDED4 */
nfs4_verifier verf; /* EXCLUSIVE4 */ nfs4_verifier verf; /* EXCLUSIVE4 */
} u;
clientid_t op_clientid; /* request */ clientid_t op_clientid; /* request */
struct xdr_netobj op_owner; /* request */ struct xdr_netobj op_owner; /* request */
u32 op_seqid; /* request */ u32 op_seqid; /* request */
...@@ -236,8 +234,8 @@ struct nfsd4_open { ...@@ -236,8 +234,8 @@ struct nfsd4_open {
struct nfs4_stateowner *op_stateowner; /* used during processing */ struct nfs4_stateowner *op_stateowner; /* used during processing */
struct nfs4_acl *op_acl; struct nfs4_acl *op_acl;
}; };
#define op_iattr u.iattr #define op_iattr iattr
#define op_verf u.verf #define op_verf verf
struct nfsd4_open_confirm { struct nfsd4_open_confirm {
stateid_t oc_req_stateid /* request */; stateid_t oc_req_stateid /* request */;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment