aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2009-04-03 01:29:17 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-03 20:41:23 -0400
commit79fb54abd285b442e1f30f851902f3ddf58e7704 (patch)
tree93c8278368e7f6328e1cfa695ce96d5c95f3e338
parent8c18f2052e756e7d5dea712fc6e7ed70c00e8a39 (diff)
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: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfs4proc.c15
-rw-r--r--fs/nfsd/nfs4xdr.c17
-rw-r--r--include/linux/nfs4.h8
-rw-r--r--include/linux/nfsd/xdr4.h10
4 files changed, 43 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e206053433e3..b2883e9c6381 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -93,6 +93,21 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
93 open->op_truncate = 0; 93 open->op_truncate = 0;
94 94
95 if (open->op_create) { 95 if (open->op_create) {
96 /* FIXME: check session persistence and pnfs flags.
97 * The nfsv4.1 spec requires the following semantics:
98 *
99 * Persistent | pNFS | Server REQUIRED | Client Allowed
100 * Reply Cache | server | |
101 * -------------+--------+-----------------+--------------------
102 * no | no | EXCLUSIVE4_1 | EXCLUSIVE4_1
103 * | | | (SHOULD)
104 * | | and EXCLUSIVE4 | or EXCLUSIVE4
105 * | | | (SHOULD NOT)
106 * no | yes | EXCLUSIVE4_1 | EXCLUSIVE4_1
107 * yes | no | GUARDED4 | GUARDED4
108 * yes | yes | GUARDED4 | GUARDED4
109 */
110
96 /* 111 /*
97 * Note: create modes (UNCHECKED,GUARDED...) are the same 112 * Note: create modes (UNCHECKED,GUARDED...) are the same
98 * in NFSv4 as in v3. 113 * in NFSv4 as in v3.
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 533d14fec99e..b820c311931c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -260,6 +260,12 @@ static u32 nfsd_attrmask[] = {
260 NFSD_WRITEABLE_ATTRS_WORD2 260 NFSD_WRITEABLE_ATTRS_WORD2
261}; 261};
262 262
263static u32 nfsd41_ex_attrmask[] = {
264 NFSD_SUPPATTR_EXCLCREAT_WORD0,
265 NFSD_SUPPATTR_EXCLCREAT_WORD1,
266 NFSD_SUPPATTR_EXCLCREAT_WORD2
267};
268
263static __be32 269static __be32
264nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable, 270nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable,
265 struct iattr *iattr, struct nfs4_acl **acl) 271 struct iattr *iattr, struct nfs4_acl **acl)
@@ -684,6 +690,17 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
684 READ_BUF(8); 690 READ_BUF(8);
685 COPYMEM(open->op_verf.data, 8); 691 COPYMEM(open->op_verf.data, 8);
686 break; 692 break;
693 case NFS4_CREATE_EXCLUSIVE4_1:
694 if (argp->minorversion < 1)
695 goto xdr_error;
696 READ_BUF(8);
697 COPYMEM(open->op_verf.data, 8);
698 status = nfsd4_decode_fattr(argp, open->op_bmval,
699 nfsd41_ex_attrmask, &open->op_iattr,
700 &open->op_acl);
701 if (status)
702 goto out;
703 break;
687 default: 704 default:
688 goto xdr_error; 705 goto xdr_error;
689 } 706 }
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index ec3cd49b04f5..e3f0cbcbd0db 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -368,7 +368,13 @@ enum opentype4 {
368enum createmode4 { 368enum createmode4 {
369 NFS4_CREATE_UNCHECKED = 0, 369 NFS4_CREATE_UNCHECKED = 0,
370 NFS4_CREATE_GUARDED = 1, 370 NFS4_CREATE_GUARDED = 1,
371 NFS4_CREATE_EXCLUSIVE = 2 371 NFS4_CREATE_EXCLUSIVE = 2,
372 /*
373 * New to NFSv4.1. If session is persistent,
374 * GUARDED4 MUST be used. Otherwise, use
375 * EXCLUSIVE4_1 instead of EXCLUSIVE4.
376 */
377 NFS4_CREATE_EXCLUSIVE4_1 = 3
372}; 378};
373 379
374enum limit_by4 { 380enum limit_by4 {
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index c07d8fe7bb07..f80d6013fdc3 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -219,10 +219,8 @@ struct nfsd4_open {
219 u32 op_create; /* request */ 219 u32 op_create; /* request */
220 u32 op_createmode; /* request */ 220 u32 op_createmode; /* request */
221 u32 op_bmval[3]; /* request */ 221 u32 op_bmval[3]; /* request */
222 union { /* request */ 222 struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
223 struct iattr iattr; /* UNCHECKED4,GUARDED4 */ 223 nfs4_verifier verf; /* EXCLUSIVE4 */
224 nfs4_verifier verf; /* EXCLUSIVE4 */
225 } u;
226 clientid_t op_clientid; /* request */ 224 clientid_t op_clientid; /* request */
227 struct xdr_netobj op_owner; /* request */ 225 struct xdr_netobj op_owner; /* request */
228 u32 op_seqid; /* request */ 226 u32 op_seqid; /* request */
@@ -236,8 +234,8 @@ struct nfsd4_open {
236 struct nfs4_stateowner *op_stateowner; /* used during processing */ 234 struct nfs4_stateowner *op_stateowner; /* used during processing */
237 struct nfs4_acl *op_acl; 235 struct nfs4_acl *op_acl;
238}; 236};
239#define op_iattr u.iattr 237#define op_iattr iattr
240#define op_verf u.verf 238#define op_verf verf
241 239
242struct nfsd4_open_confirm { 240struct nfsd4_open_confirm {
243 stateid_t oc_req_stateid /* request */; 241 stateid_t oc_req_stateid /* request */;