diff options
author | Benny Halevy <bhalevy@panasas.com> | 2009-04-03 01:29:17 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-04-03 20:41:23 -0400 |
commit | 79fb54abd285b442e1f30f851902f3ddf58e7704 (patch) | |
tree | 93c8278368e7f6328e1cfa695ce96d5c95f3e338 | |
parent | 8c18f2052e756e7d5dea712fc6e7ed70c00e8a39 (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.c | 15 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 17 | ||||
-rw-r--r-- | include/linux/nfs4.h | 8 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 10 |
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 | ||
263 | static u32 nfsd41_ex_attrmask[] = { | ||
264 | NFSD_SUPPATTR_EXCLCREAT_WORD0, | ||
265 | NFSD_SUPPATTR_EXCLCREAT_WORD1, | ||
266 | NFSD_SUPPATTR_EXCLCREAT_WORD2 | ||
267 | }; | ||
268 | |||
263 | static __be32 | 269 | static __be32 |
264 | nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, u32 *writable, | 270 | nfsd4_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 { | |||
368 | enum createmode4 { | 368 | enum 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 | ||
374 | enum limit_by4 { | 380 | enum 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 | ||
242 | struct nfsd4_open_confirm { | 240 | struct nfsd4_open_confirm { |
243 | stateid_t oc_req_stateid /* request */; | 241 | stateid_t oc_req_stateid /* request */; |