Commit b05942a3 authored by Kendrick M. Smith's avatar Kendrick M. Smith Committed by Linus Torvalds

[PATCH] kNFSd: NFSv4: tweak nfsd_create_v3() for NFSv4

File creation in NFSv4 is almost the same as in NFSv3, with one minor
difference.  If an UNCHECKED create is done, and the file exists, we
don't set any attributes.  Exception: If size==0 is specified as part
of the attributes, then we do truncate the file, but only after processing
the rest of the OPEN.  (File creation is always part of an OPEN request.)

This patch defines a new argument *truncp to nfsd_create_v3(), which
will be NULL for v3 requests.  For v4 requests, it will point to a
variable which should be set to 1 if file truncation is still needed.

The logic in nfsd_create_v3() is changed as follows: If
  - *truncp is not NULL
  - the create is UNCHECKED
  - the file exists
then nfsd_create_v3() returns immediately.  If size==0 is specified,
then *truncp is set to 1.

This is kind of a hack, but the only alternative I could see was creating
a new routine nfsd_create_v4(), which would be identical to nfsd_create_v3()
except for this point.
parent e31ff0d1
...@@ -267,7 +267,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, ...@@ -267,7 +267,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
/* Now create the file and set attributes */ /* Now create the file and set attributes */
nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
attr, newfhp, attr, newfhp,
argp->createmode, argp->verf); argp->createmode, argp->verf, NULL);
RETURN_STATUS(nfserr); RETURN_STATUS(nfserr);
} }
......
...@@ -907,7 +907,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -907,7 +907,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
int int
nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
char *fname, int flen, struct iattr *iap, char *fname, int flen, struct iattr *iap,
struct svc_fh *resfhp, int createmode, u32 *verifier) struct svc_fh *resfhp, int createmode, u32 *verifier,
int *truncp)
{ {
struct dentry *dentry, *dchild; struct dentry *dentry, *dchild;
struct inode *dirp; struct inode *dirp;
...@@ -969,6 +970,16 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -969,6 +970,16 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode)) if (! S_ISREG(dchild->d_inode->i_mode))
err = nfserr_exist; err = nfserr_exist;
else if (truncp) {
/* in nfsv4, we need to treat this case a little
* differently. we don't want to truncate the
* file now; this would be wrong if the OPEN
* fails for some other reason. furthermore,
* if the size is nonzero, we should ignore it
* according to spec!
*/
*truncp = (iap->ia_valid & ATTR_SIZE) && !iap->ia_size;
}
else { else {
iap->ia_valid &= ATTR_SIZE; iap->ia_valid &= ATTR_SIZE;
goto set_attr; goto set_attr;
......
...@@ -90,7 +90,7 @@ int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *); ...@@ -90,7 +90,7 @@ int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *);
int nfsd_create_v3(struct svc_rqst *, struct svc_fh *, int nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs, char *name, int len, struct iattr *attrs,
struct svc_fh *res, int createmode, struct svc_fh *res, int createmode,
u32 *verifier); u32 *verifier, int *truncp);
int nfsd_commit(struct svc_rqst *, struct svc_fh *, int nfsd_commit(struct svc_rqst *, struct svc_fh *,
off_t, unsigned long); off_t, unsigned long);
#endif /* CONFIG_NFSD_V3 */ #endif /* CONFIG_NFSD_V3 */
......
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