summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c12
-rw-r--r--fs/nfsd/lockd.c17
-rw-r--r--fs/nfsd/nfs3proc.c182
-rw-r--r--fs/nfsd/nfs3xdr.c37
-rw-r--r--fs/nfsd/nfsctl.c66
-rw-r--r--fs/nfsd/nfsfh.c201
-rw-r--r--fs/nfsd/nfsproc.c148
-rw-r--r--fs/nfsd/nfsxdr.c65
-rw-r--r--fs/nfsd/vfs.c201
9 files changed, 483 insertions, 446 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 24a8208bb..8d2b610a8 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -66,8 +66,6 @@ static int want_lock = 0;
static int hash_count = 0;
static DECLARE_WAIT_QUEUE_HEAD( hash_wait );
-#define READLOCK 0
-#define WRITELOCK 1
/*
* Find a client's export for a device.
@@ -435,7 +433,7 @@ out:
*/
int
exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
- char *path, struct knfs_fh *f)
+ char *path, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
struct dentry *dentry = NULL;
@@ -484,11 +482,11 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
/*
* fh must be initialized before calling fh_compose
*/
- fh_init(&fh);
- fh_compose(&fh, exp, dentry);
- memcpy(f, &fh.fh_handle, sizeof(struct knfs_fh));
+ fh_init(&fh, maxsize);
+ err = fh_compose(&fh, exp, dentry);
+ memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
fh_put(&fh);
- return 0;
+ return err;
out:
dput(dentry);
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 4062410c6..c45d494ba 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -20,14 +20,14 @@
* Note: we hold the dentry use count while the file is open.
*/
static u32
-nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
{
u32 nfserr;
struct svc_fh fh;
- /* must initialize before using! */
- fh_init(&fh);
- fh.fh_handle = *f;
+ /* must initialize before using! but maxsize doesn't matter */
+ fh_init(&fh,0);
+ memcpy((char*)&fh.fh_handle.fh_base, (char*)f, NFS_FHSIZE);
fh.fh_export = NULL;
nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
@@ -39,11 +39,14 @@ nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
* 1 = stale file handle
* 2 = other error
*/
- if (nfserr == 0)
+ switch (nfserr) {
+ case nfs_ok:
return 0;
- else if (nfserr == nfserr_stale)
+ case nfserr_stale:
return 1;
- else return 2;
+ default:
+ return 2;
+ }
}
static void
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 3b0de5545..8f69cb53e 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -28,7 +28,7 @@
#define NFSDDBG_FACILITY NFSDDBG_PROC
-#define RETURN(st) { resp->status = (st); return (st); }
+#define RETURN_STATUS(st) { resp->status = (st); return (st); }
static int nfs3_ftypes[] = {
0, /* NF3NON */
@@ -69,13 +69,12 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: GETATTR(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: GETATTR(3) %s\n",
+ SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -87,13 +86,12 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
{
int nfserr;
- dprintk("nfsd: SETATTR(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: SETATTR(3) %s\n",
+ SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -105,17 +103,18 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: LOOKUP(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: LOOKUP(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->dirfh, &argp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
+
nfserr = nfsd_lookup(rqstp, &resp->dirfh,
argp->name,
argp->len,
&resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -127,15 +126,14 @@ nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
{
int nfserr;
- dprintk("nfsd: ACCESS(3) %x/%ld 0x%x\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: ACCESS(3) %s 0x%x\n",
+ SVCFH_fmt(&argp->fh),
argp->access);
fh_copy(&resp->fh, &argp->fh);
resp->access = argp->access;
nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -148,9 +146,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
u32 *path;
int dummy, nfserr;
- dprintk("nfsd: READLINK(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
/* Reserve room for status, post_op_attr, and path length */
svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy,
@@ -160,7 +156,7 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
fh_copy(&resp->fh, &argp->fh);
resp->len = NFS3_MAXPATHLEN;
nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -173,9 +169,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
u32 * buffer;
int nfserr, avail;
- dprintk("nfsd: READ(3) %x/%ld %lu bytes at %lu\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
+ SVCFH_fmt(&argp->fh),
(unsigned long) argp->count,
(unsigned long) argp->offset);
@@ -201,7 +196,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
resp->eof = (argp->offset + resp->count) >= inode->i_size;
}
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -213,22 +208,21 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
{
int nfserr;
- dprintk("nfsd: WRITE(3) %x/%ld %d bytes at %ld%s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n",
+ SVCFH_fmt(&argp->fh),
argp->len,
(unsigned long) argp->offset,
argp->stable? " stable" : "");
fh_copy(&resp->fh, &argp->fh);
+ resp->committed = argp->stable;
nfserr = nfsd_write(rqstp, &resp->fh,
argp->offset,
argp->data,
argp->len,
- argp->stable);
- resp->committed = argp->stable;
+ &resp->committed);
resp->count = argp->count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -244,19 +238,18 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
struct iattr *attr;
u32 nfserr;
- dprintk("nfsd: CREATE(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: CREATE(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
dirfhp = fh_copy(&resp->dirfh, &argp->fh);
- newfhp = fh_init(&resp->fh);
+ newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
attr = &argp->attrs;
/* Get the directory inode */
nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
if (nfserr)
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
/* Unfudge the mode bits */
attr->ia_mode &= ~S_IFMT;
@@ -272,7 +265,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
attr, newfhp,
argp->createmode, argp->verf);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -284,18 +277,17 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
{
int nfserr;
- dprintk("nfsd: MKDIR(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: MKDIR(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
argp->attrs.ia_valid &= ~ATTR_SIZE;
fh_copy(&resp->dirfh, &argp->fh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -304,17 +296,16 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
{
int nfserr;
- dprintk("nfsd: SYMLINK(3) %x/%ld %s -> %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
+ dprintk("nfsd: SYMLINK(3) %s %s -> %s\n",
+ SVCFH_fmt(&argp->ffh),
argp->fname, argp->tname);
fh_copy(&resp->dirfh, &argp->ffh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
argp->tname, argp->tlen,
&resp->fh, &argp->attrs);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -327,31 +318,30 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
int nfserr, type;
dev_t rdev = 0;
- dprintk("nfsd: MKNOD(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: MKNOD(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->dirfh, &argp->fh);
- fh_init(&resp->fh);
+ fh_init(&resp->fh, NFS3_FHSIZE);
if (argp->ftype == 0 || argp->ftype >= NF3BAD)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV)
|| (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
|| argp->minor > 0xFF)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
rdev = ((argp->major) << 8) | (argp->minor);
} else
if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
type = nfs3_ftypes[argp->ftype];
nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
&argp->attrs, type, rdev, &resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -363,15 +353,14 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: REMOVE(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: REMOVE(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
/* Unlink. -S_IFDIR means file must not be a directory */
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -383,14 +372,13 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: RMDIR(3) %x/%ld %s\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: RMDIR(3) %s %s\n",
+ SVCFH_fmt(&argp->fh),
argp->name);
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -399,19 +387,18 @@ nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
{
int nfserr;
- dprintk("nfsd: RENAME(3) %x/%ld %s -> %x/%ld %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
- argp->fname,
- SVCFH_DEV(&argp->tfh),
- (long)SVCFH_INO(&argp->tfh),
+ dprintk("nfsd: RENAME(3) %s %s ->\n",
+ SVCFH_fmt(&argp->ffh),
+ argp->fname);
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
fh_copy(&resp->ffh, &argp->ffh);
fh_copy(&resp->tfh, &argp->tfh);
nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
&resp->tfh, argp->tname, argp->tlen);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
static int
@@ -420,18 +407,17 @@ nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
{
int nfserr;
- dprintk("nfsd: LINK(3) %x/%ld -> %x/%ld %s\n",
- SVCFH_DEV(&argp->ffh),
- (long)SVCFH_INO(&argp->ffh),
- SVCFH_DEV(&argp->tfh),
- (long)SVCFH_INO(&argp->tfh),
+ dprintk("nfsd: LINK(3) %s ->\n",
+ SVCFH_fmt(&argp->ffh));
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
fh_copy(&resp->fh, &argp->ffh);
fh_copy(&resp->tfh, &argp->tfh);
nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
&resp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -445,9 +431,8 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
int nfserr, count;
unsigned int want;
- dprintk("nfsd: READDIR(3) %x/%ld %d bytes at %d\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, (u32) argp->cookie);
/* Reserve buffer space for status, attributes and verifier */
@@ -467,7 +452,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -481,9 +466,8 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
u32 * buffer;
int nfserr, count, want;
- dprintk("nfsd: READDIR+(3) %x/%ld %d bytes at %d\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, (u32) argp->cookie);
/* Reserve buffer space for status, attributes and verifier */
@@ -503,7 +487,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -515,13 +499,12 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: FSSTAT(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: FSSTAT(3) %s\n",
+ SVCFH_fmt(&argp->fh));
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -533,9 +516,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: FSINFO(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: FSINFO(3) %s\n",
+ SVCFH_fmt(&argp->fh));
resp->f_rtmax = NFSSVC_MAXBLKSIZE;
resp->f_rtpref = NFSSVC_MAXBLKSIZE;
@@ -562,7 +544,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
}
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
/*
@@ -574,9 +556,8 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: PATHCONF(3) %x/%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh));
+ dprintk("nfsd: PATHCONF(3) %s\n",
+ SVCFH_fmt(&argp->fh));
/* Set default pathconf */
resp->p_link_max = 255; /* at least */
@@ -605,7 +586,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
}
fh_put(&argp->fh);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
@@ -618,19 +599,18 @@ nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
{
int nfserr;
- dprintk("nfsd: COMMIT(3) %x/%ld %d@%ld\n",
- SVCFH_DEV(&argp->fh),
- (long)SVCFH_INO(&argp->fh),
+ dprintk("nfsd: COMMIT(3) %s %d@%ld\n",
+ SVCFH_fmt(&argp->fh),
argp->count,
(unsigned long) argp->offset);
if (argp->offset > NFS_OFFSET_MAX)
- return nfserr_inval;
+ RETURN_STATUS(nfserr_inval);
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
- RETURN(nfserr);
+ RETURN_STATUS(nfserr);
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 84ef13ded..7dc5739eb 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -21,10 +21,6 @@
# define inline
#endif
-/*
- * Size of encoded NFS3 file handle, in words
- */
-#define NFS3_FHANDLE_WORDS (1 + XDR_QUADLEN(sizeof(struct knfs_fh)))
/*
* Mapping of S_IF* types to NFS file types
@@ -64,19 +60,36 @@ decode_time3(u32 *p, time_t *secp)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- if (ntohl(*p++) != sizeof(struct knfs_fh))
+ int size;
+ fh_init(fhp, NFS3_FHSIZE);
+ size = ntohl(*p++);
+ if (size > NFS3_FHSIZE)
return NULL;
- memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+ memcpy(&fhp->fh_handle.fh_base, p, size);
+ fhp->fh_handle.fh_size = size;
+ return p + XDR_QUADLEN(size);
}
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
- *p++ = htonl(sizeof(struct knfs_fh));
- memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+#if 0
+ int size = fhp->fh_handle.fh_size;
+ *p++ = htonl(size);
+ if (size) p[XDR_QUADLEN(size)-1]=0;
+ memcpy(p, &fhp->fh_handle.fh_base, size);
+ return p + XDR_QUADLEN(size);
+#else
+ /* until locked knows about var-length file handles,
+ * we always return NFS_FHSIZE handles
+ */
+ int size = fhp->fh_handle.fh_size;
+ *p++ = htonl(NFS_FHSIZE);
+ memset(p, 0, NFS_FHSIZE);
+ memcpy(p, &fhp->fh_handle.fh_base, size);
+ return p + XDR_QUADLEN(NFS_FHSIZE);
+#endif
}
/*
@@ -698,6 +711,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
}
*p++ = xdr_one; /* mark entry present */
p = xdr_encode_hyper(p, ino); /* file id */
+ p[slen - 1] = 0; /* don't leak kernel data */
#ifdef XDR_ENCODE_STRING_TAKES_LENGTH
p = xdr_encode_string(p, name, namlen); /* name length & name */
#else
@@ -706,7 +720,6 @@ encode_entry(struct readdir_cd *cd, const char *name,
memcpy(p, name, namlen);
p += slen;
#endif
- p[slen - 1] = 0; /* don't leak kernel data */
cd->offset = p; /* remember pointer */
p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
@@ -715,7 +728,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
if (plus) {
struct svc_fh fh;
- fh_init(&fh);
+ fh_init(&fh, NFS3_FHSIZE);
/* Disabled for now because of lock-up */
if (0 && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh) == 0) {
p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index b0aac3280..815208e09 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -40,8 +40,9 @@ static int nfsctl_addclient(struct nfsctl_client *data);
static int nfsctl_delclient(struct nfsctl_client *data);
static int nfsctl_export(struct nfsctl_export *data);
static int nfsctl_unexport(struct nfsctl_export *data);
-static int nfsctl_getfh(struct nfsctl_fhparm *, struct knfs_fh *);
-static int nfsctl_getfd(struct nfsctl_fdparm *, struct knfs_fh *);
+static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
+static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
+static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
/* static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data); */
static int initialized = 0;
@@ -63,7 +64,6 @@ void proc_export_init(void)
static void
nfsd_init(void)
{
- nfsd_xdr_init(); /* XDR */
nfsd_stat_init(); /* Statistics */
nfsd_cache_init(); /* RPC reply cache */
nfsd_export_init(); /* Exports table */
@@ -110,12 +110,37 @@ nfsctl_ugidupdate(nfs_ugidmap *data)
}
#endif
+#ifdef notyet
+static inline int
+nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
+{
+ struct sockaddr_in *sin;
+ struct svc_client *clp;
+ int err = 0;
+
+ if (data->gd_addr.sa_family != AF_INET)
+ return -EPROTONOSUPPORT;
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ if (data->gd_maxlen > NFS3_FHSIZE)
+ data->gd_maxlen = NFS3_FHSIZE;
+ exp_readlock();
+ if (!(clp = exp_getclient(sin)))
+ err = -EPERM;
+ else
+ err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
+ exp_unlock();
+
+ return err;
+}
+#endif
+
static inline int
-nfsctl_getfd(struct nfsctl_fdparm *data, struct knfs_fh *res)
+nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
+ struct knfsd_fh fh;
if (data->gd_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
@@ -127,18 +152,28 @@ nfsctl_getfd(struct nfsctl_fdparm *data, struct knfs_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, 0, 0, data->gd_path, res);
+ err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
+ if (err == 0) {
+ if (fh.fh_size > NFS_FHSIZE)
+ err = -EINVAL;
+ else {
+ memset(res,0, NFS_FHSIZE);
+ memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+ }
+ }
+
return err;
}
static inline int
-nfsctl_getfh(struct nfsctl_fhparm *data, struct knfs_fh *res)
+nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
+ struct knfsd_fh fh;
if (data->gf_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
@@ -150,9 +185,18 @@ nfsctl_getfh(struct nfsctl_fhparm *data, struct knfs_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
- err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, res);
+ err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
exp_unlock();
+ if (err == 0) {
+ if (fh.fh_size > NFS_FHSIZE)
+ err = -EINVAL;
+ else {
+ memset(res,0, NFS_FHSIZE);
+ memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+ }
+ }
+
return err;
}
@@ -218,11 +262,15 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
break;
#endif
case NFSCTL_GETFH:
- err = nfsctl_getfh(&arg->ca_getfh, &res->cr_getfh);
+ err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
break;
case NFSCTL_GETFD:
- err = nfsctl_getfd(&arg->ca_getfd, &res->cr_getfh);
+ err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
break;
+#ifdef notyet
+ case NFSCTL_GETFS:
+ err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
+#endif
default:
err = -EINVAL;
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 084a17d9b..4a7e63dcb 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -328,7 +328,7 @@ static struct dentry *splice(struct dentry *child, struct dentry *parent)
* connection if made.
*/
static struct dentry *
-find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
+find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, int needpath)
{
struct dentry *dentry, *result = NULL;
struct dentry *tmp;
@@ -347,7 +347,7 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
* Attempt to find the inode.
*/
retry:
- result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
+ result = nfsd_iget(sb, ino, generation);
err = PTR_ERR(result);
if (IS_ERR(result))
goto err_out;
@@ -370,10 +370,10 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
/* It's a directory, or we are required to confirm the file's
* location in the tree.
*/
- dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
+ dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
down(&sb->s_nfsd_free_path_sem);
- /* claiming the semaphore might have allow things to get fixed up */
+ /* claiming the semaphore might have allowed things to get fixed up */
if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
up(&sb->s_nfsd_free_path_sem);
return result;
@@ -383,11 +383,11 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
found = 0;
if (!S_ISDIR(result->d_inode->i_mode)) {
nfsdstats.fh_nocache_nondir++;
- if (fh->fh_dirino == 0)
+ if (dirino == 0)
goto err_result; /* don't know how to find parent */
else {
- /* need to iget fh->fh_dirino and make sure this inode is in that directory */
- dentry = nfsd_iget(sb, fh->fh_dirino, 0);
+ /* need to iget dirino and make sure this inode is in that directory */
+ dentry = nfsd_iget(sb, dirino, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto err_result;
@@ -490,38 +490,58 @@ err_out:
u32
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
{
- struct knfs_fh *fh = &fhp->fh_handle;
+ struct knfsd_fh *fh = &fhp->fh_handle;
struct svc_export *exp;
struct dentry *dentry;
struct inode *inode;
u32 error = 0;
- dprintk("nfsd: fh_verify(exp %s/%u file (%s/%u dir %u)\n",
- kdevname(fh->fh_xdev),
- fh->fh_xino,
- kdevname(fh->fh_dev),
- fh->fh_ino,
- fh->fh_dirino);
+ dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
if (!fhp->fh_dverified) {
- /*
- * Security: Check that the fh is internally consistant (from <gam3@acm.org>)
- */
- if (fh->fh_dev != fh->fh_xdev) {
- printk("fh_verify: Security: export on other device (%s, %s).\n",
- kdevname(fh->fh_dev), kdevname(fh->fh_xdev));
- error = nfserr_stale;
- nfsdstats.fh_stale++;
- goto out;
+ kdev_t xdev;
+ ino_t xino;
+ __u32 *datap=NULL;
+ int data_left = fh->fh_size/4;
+ int nfsdev;
+ error = nfserr_stale;
+#if CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 3)
+ error = nfserr_badhandle;
+#endif
+ if (fh->fh_version == 1) {
+
+ datap = fh->fh_auth;
+ if (--data_left<0) goto out;
+ switch (fh->fh_auth_type) {
+ case 0: break;
+ default: goto out;
+ }
+
+ switch (fh->fh_fsid_type) {
+ case 0:
+ if ((data_left-=2)<0) goto out;
+ nfsdev = ntohl(*datap++);
+ xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
+ xino = *datap++;
+ break;
+ default:
+ goto out;
+ }
+ } else {
+ if (fh->fh_size != NFS_FHSIZE)
+ goto out;
+ /* assume old filehandle format */
+ xdev = u32_to_kdev_t(fh->ofh_xdev);
+ xino = u32_to_ino_t(fh->ofh_xino);
}
/*
* Look up the export entry.
*/
error = nfserr_stale;
- exp = exp_get(rqstp->rq_client,
- u32_to_kdev_t(fh->fh_xdev),
- u32_to_ino_t(fh->fh_xino));
+ exp = exp_get(rqstp->rq_client, xdev, xino);
+
if (!exp) {
/* export entry revoked */
nfsdstats.fh_stale++;
@@ -544,13 +564,44 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
/*
* Look up the dentry using the NFS file handle.
*/
+ error = nfserr_stale;
+#if CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 3)
+ error = nfserr_badhandle;
+#endif
- dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
- fh,
- !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ if (fh->fh_version == 1) {
+ /* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
+ * then should use that */
+ switch (fh->fh_fileid_type) {
+ case 0:
+ dentry = dget(exp->ex_dentry);
+ break;
+ case 1:
+ if ((data_left-=2)<0) goto out;
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ datap[0], datap[1],
+ 0,
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ break;
+ case 2:
+ if ((data_left-=3)<0) goto out;
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ datap[0], datap[1],
+ datap[2],
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ break;
+ default: goto out;
+ }
+ } else {
+ dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+ fh->ofh_ino, fh->ofh_generation,
+ fh->ofh_dirino,
+ !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+ }
if (IS_ERR(dentry)) {
- error = nfserrno(-PTR_ERR(dentry));
+ error = nfserrno(PTR_ERR(dentry));
goto out;
}
#ifdef NFSD_PARANOIA
@@ -652,72 +703,96 @@ out:
* an inode. In this case a call to fh_update should be made
* before the fh goes out on the wire ...
*/
-void
+inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+ __u32 **datapp, int maxsize)
+{
+ __u32 *datap= *datapp;
+ if (dentry == exp->ex_dentry)
+ return 0;
+ /* if super_operations provides dentry_to_fh lookup, should use that */
+
+ *datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
+ *datap++ = dentry->d_inode->i_generation;
+ if (S_ISDIR(dentry->d_inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK)){
+ *datapp = datap;
+ return 1;
+ }
+ *datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
+ *datapp = datap;
+ return 2;
+}
+
+int
fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
{
struct inode * inode = dentry->d_inode;
struct dentry *parent = dentry->d_parent;
+ __u32 *datap;
dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
exp->ex_dev, (long) exp->ex_ino,
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
- /*
- * N.B. We shouldn't need to init the fh -- the call to fh_compose
- * may not be done on error paths, but the cleanup must call fh_put.
- * Fix this soon!
- */
if (fhp->fh_dverified || fhp->fh_locked || fhp->fh_dentry) {
printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
parent->d_name.name, dentry->d_name.name);
}
- fh_init(fhp);
-
- fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
- fhp->fh_handle.fh_dev = kdev_t_to_u32(parent->d_inode->i_dev);
- fhp->fh_handle.fh_xdev = kdev_t_to_u32(exp->ex_dev);
- fhp->fh_handle.fh_xino = ino_t_to_u32(exp->ex_ino);
- fhp->fh_handle.fh_dcookie = (struct dentry *)0xfeebbaca;
- if (inode) {
- fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
- fhp->fh_handle.fh_generation = inode->i_generation;
- if (S_ISDIR(inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
- fhp->fh_handle.fh_dirino = 0;
- }
+ if (fhp->fh_maxsize < NFS_FHSIZE)
+ printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
+ fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
fhp->fh_dentry = dentry; /* our internal copy */
fhp->fh_export = exp;
+ fhp->fh_handle.fh_version = 1;
+ fhp->fh_handle.fh_auth_type = 0;
+ fhp->fh_handle.fh_fsid_type = 0;
+ datap = fhp->fh_handle.fh_auth+0;
+ /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
+ *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+ *datap++ = ino_t_to_u32(exp->ex_ino);
+
+ if (inode)
+ fhp->fh_handle.fh_fileid_type =
+ _fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
+
+ fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+
+
/* We stuck it there, we know it's good. */
fhp->fh_dverified = 1;
nfsd_nr_verified++;
+ if (fhp->fh_handle.fh_fileid_type == 255)
+ return nfserr_opnotsupp;
+ return 0;
}
/*
* Update file handle information after changing a dentry.
- * This is only called by nfsd_create
+ * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
*/
-void
+int
fh_update(struct svc_fh *fhp)
{
struct dentry *dentry;
- struct inode *inode;
-
+ __u32 *datap;
+
if (!fhp->fh_dverified)
goto out_bad;
dentry = fhp->fh_dentry;
- inode = dentry->d_inode;
- if (!inode)
+ if (!dentry->d_inode)
goto out_negative;
- fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
- fhp->fh_handle.fh_generation = inode->i_generation;
- if (S_ISDIR(inode->i_mode) || (fhp->fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
- fhp->fh_handle.fh_dirino = 0;
-
+ if (fhp->fh_handle.fh_fileid_type != 0)
+ goto out_uptodate;
+ datap = fhp->fh_handle.fh_auth+
+ fhp->fh_handle.fh_size/4 -1;
+ fhp->fh_handle.fh_fileid_type =
+ _fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
+ fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
out:
- return;
+ return 0;
out_bad:
printk(KERN_ERR "fh_update: fh not verified!\n");
@@ -726,6 +801,10 @@ out_negative:
printk(KERN_ERR "fh_update: %s/%s still negative!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
goto out;
+out_uptodate:
+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ goto out;
}
/*
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ef69be746..7d570299f 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -30,7 +30,6 @@ typedef struct svc_buf svc_buf;
#define NFSDDBG_FACILITY NFSDDBG_PROC
-#define RETURN(st) return st
static void
svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
@@ -42,7 +41,7 @@ svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
static int
nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
{
- RETURN(nfs_ok);
+ return nfs_ok;
}
/*
@@ -53,11 +52,10 @@ static int
nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
struct nfsd_attrstat *resp)
{
- dprintk("nfsd: GETATTR %d/%d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh));
+ dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- RETURN(fh_verify(rqstp, &resp->fh, 0, MAY_NOP));
+ return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
}
/*
@@ -68,12 +66,12 @@ static int
nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
struct nfsd_attrstat *resp)
{
- dprintk("nfsd: SETATTR %d/%d, valid=%x, size=%ld\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
+ SVCFH_fmt(&argp->fh),
argp->attrs.ia_valid, (long) argp->attrs.ia_size);
fh_copy(&resp->fh, &argp->fh);
- RETURN(nfsd_setattr(rqstp, &resp->fh, &argp->attrs));
+ return nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
}
/*
@@ -88,14 +86,15 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: LOOKUP %d/%d %s\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh), argp->name);
+ dprintk("nfsd: LOOKUP %s %s\n",
+ SVCFH_fmt(&argp->fh), argp->name);
+ fh_init(&resp->fh, NFS_FHSIZE);
nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
&resp->fh);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -108,7 +107,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
u32 *path;
int dummy, nfserr;
- dprintk("nfsd: READLINK %p\n", SVCFH_DENTRY(&argp->fh));
+ dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
/* Reserve room for status and path length */
svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 2);
@@ -118,7 +117,7 @@ nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -132,8 +131,8 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
u32 * buffer;
int nfserr, avail;
- dprintk("nfsd: READ %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READ %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, argp->offset);
/* Obtain buffer pointer for payload. 19 is 1 word for
@@ -156,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
(char *) buffer,
&resp->count);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -168,17 +167,18 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
struct nfsd_attrstat *resp)
{
int nfserr;
+ int stable = 1;
- dprintk("nfsd: WRITE %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: WRITE %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->len, argp->offset);
nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
argp->offset,
argp->data,
argp->len,
- 0);
- RETURN(nfserr);
+ &stable);
+ return nfserr;
}
/*
@@ -198,8 +198,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
int nfserr, type, mode, rdonly = 0;
dev_t rdev = NODEV;
- dprintk("nfsd: CREATE %d/%d %s\n",
- SVCFH_DEV(dirfhp), SVCFH_INO(dirfhp), argp->name);
+ dprintk("nfsd: CREATE %s %s\n",
+ SVCFH_fmt(dirfhp), argp->name);
/* First verify the parent file handle */
nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
@@ -217,6 +217,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
/*
* Do a lookup to verify the new file handle.
*/
+ fh_init(newfhp, NFS_FHSIZE);
nfserr = nfsd_lookup(rqstp, dirfhp, argp->name, argp->len, newfhp);
if (nfserr) {
if (nfserr != nfserr_noent)
@@ -240,9 +241,11 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
if (nfserr)
goto done;
inode = newfhp->fh_dentry->d_inode;
- if (inode && newfhp->fh_handle.fh_ino == 0)
+ if (inode && newfhp->fh_handle.fh_fileid_type == 0)
/* inode might have been instantiated while we slept */
- fh_update(newfhp);
+ nfserr = fh_update(newfhp);
+ if (nfserr)
+ goto done;
/* Unfudge the mode bits */
if (attr->ia_valid & ATTR_MODE) {
@@ -321,7 +324,7 @@ out_unlock:
done:
fh_put(dirfhp);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -330,12 +333,12 @@ nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: REMOVE %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: REMOVE %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
/* Unlink. -SIFDIR means file must not be a directory */
nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -344,15 +347,16 @@ nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
{
int nfserr;
- dprintk("nfsd: RENAME %p %s -> %p %s\n",
- SVCFH_DENTRY(&argp->ffh), argp->fname,
- SVCFH_DENTRY(&argp->tfh), argp->tname);
+ dprintk("nfsd: RENAME %s %s -> \n",
+ SVCFH_fmt(&argp->ffh), argp->fname);
+ dprintk("nfsd: -> %s %s\n",
+ SVCFH_fmt(&argp->tfh), argp->tname);
nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
&argp->tfh, argp->tname, argp->tlen);
fh_put(&argp->ffh);
fh_put(&argp->tfh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -361,16 +365,17 @@ nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
{
int nfserr;
- dprintk("nfsd: LINK %p -> %p %s\n",
- SVCFH_DENTRY(&argp->ffh),
- SVCFH_DENTRY(&argp->tfh),
+ dprintk("nfsd: LINK %s ->\n",
+ SVCFH_fmt(&argp->ffh));
+ dprintk("nfsd: %s %s\n",
+ SVCFH_fmt(&argp->tfh),
argp->tname);
nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
&argp->ffh);
fh_put(&argp->ffh);
fh_put(&argp->tfh);
- RETURN(nfserr);
+ return nfserr;
}
static int
@@ -380,10 +385,10 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
struct svc_fh newfh;
int nfserr;
- dprintk("nfsd: SYMLINK %p %s -> %s\n",
- SVCFH_DENTRY(&argp->ffh), argp->fname, argp->tname);
+ dprintk("nfsd: SYMLINK %s %s -> %s\n",
+ SVCFH_fmt(&argp->ffh), argp->fname, argp->tname);
- memset(&newfh, 0, sizeof(struct svc_fh));
+ fh_init(&newfh, NFS_FHSIZE);
/*
* Create the link, look up new file and set attrs.
*/
@@ -394,7 +399,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
fh_put(&argp->ffh);
fh_put(&newfh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -407,7 +412,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
{
int nfserr;
- dprintk("nfsd: MKDIR %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: MKDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
if (resp->fh.fh_dverified) {
printk(KERN_WARNING
@@ -415,10 +420,11 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
}
argp->attrs.ia_valid &= ~ATTR_SIZE;
+ fh_init(&resp->fh, NFS_FHSIZE);
nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -430,11 +436,11 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
{
int nfserr;
- dprintk("nfsd: RMDIR %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+ dprintk("nfsd: RMDIR %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -447,8 +453,8 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
u32 * buffer;
int nfserr, count;
- dprintk("nfsd: READDIR %d/%d %d bytes at %d\n",
- SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+ dprintk("nfsd: READDIR %s %d bytes at %d\n",
+ SVCFH_fmt(&argp->fh),
argp->count, argp->cookie);
/* Reserve buffer space for status */
@@ -470,7 +476,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
resp->count = count;
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -482,11 +488,11 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: STATFS %p\n", SVCFH_DENTRY(&argp->fh));
+ dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
fh_put(&argp->fh);
- RETURN(nfserr);
+ return nfserr;
}
/*
@@ -539,36 +545,36 @@ nfserrno (int errno)
int nfserr;
int syserr;
} nfs_errtbl[] = {
- { NFS_OK, 0 },
- { NFSERR_PERM, EPERM },
- { NFSERR_NOENT, ENOENT },
- { NFSERR_IO, EIO },
- { NFSERR_NXIO, ENXIO },
- { NFSERR_ACCES, EACCES },
- { NFSERR_EXIST, EEXIST },
- { NFSERR_XDEV, EXDEV },
- { NFSERR_MLINK, EMLINK },
- { NFSERR_NODEV, ENODEV },
- { NFSERR_NOTDIR, ENOTDIR },
- { NFSERR_ISDIR, EISDIR },
- { NFSERR_INVAL, EINVAL },
- { NFSERR_FBIG, EFBIG },
- { NFSERR_NOSPC, ENOSPC },
- { NFSERR_ROFS, EROFS },
- { NFSERR_MLINK, EMLINK },
- { NFSERR_NAMETOOLONG, ENAMETOOLONG },
- { NFSERR_NOTEMPTY, ENOTEMPTY },
+ { nfs_ok, 0 },
+ { nfserr_perm, -EPERM },
+ { nfserr_noent, -ENOENT },
+ { nfserr_io, -EIO },
+ { nfserr_nxio, -ENXIO },
+ { nfserr_acces, -EACCES },
+ { nfserr_exist, -EEXIST },
+ { nfserr_xdev, -EXDEV },
+ { nfserr_mlink, -EMLINK },
+ { nfserr_nodev, -ENODEV },
+ { nfserr_notdir, -ENOTDIR },
+ { nfserr_isdir, -EISDIR },
+ { nfserr_inval, -EINVAL },
+ { nfserr_fbig, -EFBIG },
+ { nfserr_nospc, -ENOSPC },
+ { nfserr_rofs, -EROFS },
+ { nfserr_mlink, -EMLINK },
+ { nfserr_nametoolong, -ENAMETOOLONG },
+ { nfserr_notempty, -ENOTEMPTY },
#ifdef EDQUOT
- { NFSERR_DQUOT, EDQUOT },
+ { nfserr_dquot, -EDQUOT },
#endif
- { NFSERR_STALE, ESTALE },
- { -1, EIO }
+ { nfserr_stale, -ESTALE },
+ { -1, -EIO }
};
int i;
for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
if (nfs_errtbl[i].syserr == errno)
- return htonl(nfs_errtbl[i].nfserr);
+ return nfs_errtbl[i].nfserr;
}
printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
return nfserr_io;
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 3afe9f83e..2984f0330 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -17,15 +17,6 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR
-u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
- nfserr_acces, nfserr_exist, nfserr_xdev, nfserr_nodev,
- nfserr_notdir, nfserr_isdir, nfserr_inval, nfserr_fbig,
- nfserr_nospc, nfserr_rofs, nfserr_mlink,
- nfserr_nametoolong, nfserr_notempty, nfserr_dquot, nfserr_stale,
- nfserr_remote, nfserr_badhandle, nfserr_notsync,
- nfserr_badcookie, nfserr_notsupp, nfserr_toosmall,
- nfserr_serverfault, nfserr_badtype, nfserr_jukebox;
-
#ifdef NFSD_OPTIMIZE_SPACE
# define inline
@@ -41,51 +32,6 @@ static u32 nfs_ftypes[] = {
NFSOCK, NFBAD, NFLNK, NFBAD,
};
-/*
- * Initialization of NFS status variables
- */
-void
-nfsd_xdr_init(void)
-{
- static int inited = 0;
-
- if (inited)
- return;
-
- nfs_ok = htonl(NFS_OK);
- nfserr_perm = htonl(NFSERR_PERM);
- nfserr_noent = htonl(NFSERR_NOENT);
- nfserr_io = htonl(NFSERR_IO);
- nfserr_inval = htonl(NFSERR_INVAL);
- nfserr_nxio = htonl(NFSERR_NXIO);
- nfserr_acces = htonl(NFSERR_ACCES);
- nfserr_exist = htonl(NFSERR_EXIST);
- nfserr_xdev = htonl(NFSERR_XDEV);
- nfserr_nodev = htonl(NFSERR_NODEV);
- nfserr_notdir = htonl(NFSERR_NOTDIR);
- nfserr_isdir = htonl(NFSERR_ISDIR);
- nfserr_inval = htonl(NFSERR_INVAL);
- nfserr_fbig = htonl(NFSERR_FBIG);
- nfserr_nospc = htonl(NFSERR_NOSPC);
- nfserr_rofs = htonl(NFSERR_ROFS);
- nfserr_mlink = htonl(NFSERR_MLINK);
- nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
- nfserr_notempty = htonl(NFSERR_NOTEMPTY);
- nfserr_dquot = htonl(NFSERR_DQUOT);
- nfserr_stale = htonl(NFSERR_STALE);
- nfserr_remote = htonl(NFSERR_REMOTE);
- nfserr_badhandle = htonl(NFSERR_BADHANDLE);
- nfserr_notsync = htonl(NFSERR_NOT_SYNC);
- nfserr_badcookie = htonl(NFSERR_BAD_COOKIE);
- nfserr_notsupp = htonl(NFSERR_NOTSUPP);
- nfserr_toosmall = htonl(NFSERR_TOOSMALL);
- nfserr_serverfault = htonl(NFSERR_SERVERFAULT);
- nfserr_badtype = htonl(NFSERR_BADTYPE);
- nfserr_jukebox = htonl(NFSERR_JUKEBOX);
-
-
- inited = 1;
-}
/*
* XDR functions for basic NFS types
@@ -93,19 +39,20 @@ nfsd_xdr_init(void)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- fh_init(fhp);
- memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
+ fh_init(fhp, NFS_FHSIZE);
+ memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
+ fhp->fh_handle.fh_size = NFS_FHSIZE;
/* FIXME: Look up export pointer here and verify
* Sun Secure RPC if requested */
- return p + (sizeof(struct knfs_fh) >> 2);
+ return p + (NFS_FHSIZE >> 2);
}
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
- memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
- return p + (sizeof(struct knfs_fh) >> 2);
+ memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
+ return p + (NFS_FHSIZE>> 2);
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c8389381f..06a795841 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/version.h>
+#include <linux/string.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/locks.h>
@@ -92,7 +93,7 @@ static struct raparms * raparm_cache = NULL;
* the check_parent in linux/fs/namei.c.
*/
#define nfsd_check_parent(dir, dentry) \
- ((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
+ ((dir) == (dentry)->d_parent && !d_unhashed(dentry))
/*
* Lock a parent directory following the VFS locking protocol.
@@ -137,7 +138,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
struct dentry *dparent, *dchild;
int err;
- dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name);
+ dprintk("nfsd: nfsd_lookup(fh %s, %s)\n", SVCFH_fmt(fhp), name);
/* Obtain dentry and export. */
err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
@@ -155,7 +156,10 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
err = nfserr_acces;
/* Lookup the name, but don't follow links */
- dchild = lookup_dentry(name, dget(dparent), 0);
+ if (strcmp(name,"..")==0 && dparent->d_covers != dparent)
+ dchild = dget(dparent);
+ else
+ dchild = lookup_dentry(name, dget(dparent), 0);
if (IS_ERR(dchild))
goto out_nfserr;
/*
@@ -187,15 +191,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
* Note: we compose the file handle now, but as the
* dentry may be negative, it may need to be updated.
*/
- fh_compose(resfh, exp, dchild);
- err = nfserr_noent;
- if (dchild->d_inode)
- err = 0;
+ err = fh_compose(resfh, exp, dchild);
+ if (!err && !dchild->d_inode)
+ err = nfserr_noent;
out:
return err;
out_nfserr:
- err = nfserrno(-PTR_ERR(dchild));
+ err = nfserrno(PTR_ERR(dchild));
goto out;
}
@@ -261,8 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
/* The size case is special. It changes the file as well as the attributes. */
if (iap->ia_valid & ATTR_SIZE) {
-if (!S_ISREG(inode->i_mode))
-printk("nfsd_setattr: size change??\n");
if (iap->ia_size < inode->i_size) {
err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
if (err)
@@ -326,7 +327,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -393,18 +394,19 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
if (map->access & query) {
unsigned int err2;
err2 = nfsd_permission(export, dentry, map->how);
- /* cannot use a "switch" as nfserr_* are variables, even though they are constant :-( */
- if (err2 == 0)
+ switch (err2) {
+ case nfs_ok:
result |= map->access;
+ break;
+
/* the following error codes just mean the access was not allowed,
* rather than an error occurred */
- else if (err2 == nfserr_rofs ||
- err2 == nfserr_acces ||
- err2 == nfserr_perm
- )
+ case nfserr_rofs:
+ case nfserr_acces:
+ case nfserr_perm:
/* simply don't "or" in the access bit. */
- ;
- else {
+ break;
+ default:
error = err2;
goto out;
}
@@ -482,7 +484,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
}
out_nfserr:
if (err)
- err = nfserrno(-err);
+ err = nfserrno(err);
out:
return err;
}
@@ -587,7 +589,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
goto out_close;
/* Get readahead parameters */
- ra = nfsd_get_raparms(fhp->fh_handle.fh_dev, fhp->fh_handle.fh_ino);
+ ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
if (ra) {
file.f_reada = ra->p_reada;
file.f_ramax = ra->p_ramax;
@@ -618,7 +620,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
*count = err;
err = 0;
} else
- err = nfserrno(-err);
+ err = nfserrno(err);
out_close:
nfsd_close(&file);
out:
@@ -632,7 +634,7 @@ out:
*/
int
nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- char *buf, unsigned long cnt, int stable)
+ char *buf, unsigned long cnt, int *stablep)
{
struct svc_export *exp;
struct file file;
@@ -640,6 +642,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
struct inode *inode;
mm_segment_t oldfs;
int err = 0;
+ int stable = *stablep;
#ifdef CONFIG_QUOTA
uid_t saved_euid;
#endif
@@ -666,10 +669,12 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
* flushing the data to disk is handled separately below.
*/
#ifdef CONFIG_NFSD_V3
- if (rqstp->rq_vers == 2)
- stable = EX_ISSYNC(exp);
- else if (file.f_op->fsync == 0)
- stable = 1;
+ if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+ stable = 2;
+ *stablep = 2; /* FILE_SYNC */
+ }
+ if (!EX_ISSYNC(exp))
+ stable = 0;
if (stable && !EX_WGATHER(exp))
file.f_flags |= O_SYNC;
#else
@@ -749,7 +754,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (err >= 0)
err = 0;
else
- err = nfserrno(-err);
+ err = nfserrno(err);
out_close:
nfsd_close(&file);
out:
@@ -774,11 +779,12 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
return err;
-
- if (file.f_op && file.f_op->fsync) {
- nfsd_sync(&file);
- } else {
- err = nfserr_notsupp;
+ if (EX_ISSYNC(fhp->fh_export)) {
+ if (file.f_op && file.f_op->fsync) {
+ nfsd_sync(&file);
+ } else {
+ err = nfserr_notsupp;
+ }
}
nfsd_close(&file);
@@ -827,11 +833,13 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = PTR_ERR(dchild);
if (IS_ERR(dchild))
goto out_nfserr;
- fh_compose(resfhp, fhp->fh_export, dchild);
/* Lock the parent and check for errors ... */
err = fh_lock_parent(fhp, dchild);
if (err)
goto out;
+ err = fh_compose(resfhp, fhp->fh_export, dchild);
+ if (err)
+ goto out;
} else {
/* called from nfsd_proc_create */
dchild = resfhp->fh_dentry;
@@ -888,10 +896,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
write_inode_now(dchild->d_inode);
}
- /*
- * Update the file handle to get the new inode info.
- */
- fh_update(resfhp);
/* Set file attributes. Mode has already been set and
* setting uid/gid works only for root. Irix appears to
@@ -901,11 +905,16 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = 0;
if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
err = nfsd_setattr(rqstp, resfhp, iap);
+ /*
+ * Update the file handle to get the new inode info.
+ */
+ if (!err)
+ err = fh_update(resfhp);
out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -947,22 +956,20 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = PTR_ERR(dchild);
if(IS_ERR(dchild))
goto out_nfserr;
- fh_compose(resfhp, fhp->fh_export, dchild);
/*
* We must lock the directory before we check for the inode.
*/
err = fh_lock_parent(fhp, dchild);
if (err)
- goto out;
+ goto out;
+ err = fh_compose(resfhp, fhp->fh_export, dchild);
+ if (err)
+ goto out;
if (dchild->d_inode) {
err = 0;
- if (resfhp->fh_handle.fh_ino == 0)
- /* inode might have been instantiated while we slept */
- fh_update(resfhp);
-
switch (createmode) {
case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode))
@@ -997,8 +1004,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
/*
* Update the filehandle to get the new inode info.
*/
- fh_update(resfhp);
- err = 0;
+ err = fh_update(resfhp);
+ if (err)
+ goto out;
if (createmode == NFS3_CREATE_EXCLUSIVE) {
/* Cram the verifier into atime/mtime */
@@ -1021,7 +1029,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
#endif /* CONFIG_NFSD_V3 */
@@ -1067,7 +1075,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1083,7 +1091,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct iattr *iap)
{
struct dentry *dentry, *dnew;
- int err;
+ int err, cerr;
err = nfserr_noent;
if (!flen || !plen)
@@ -1122,17 +1130,18 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
}
} else
- err = nfserrno(-err);
+ err = nfserrno(err);
fh_unlock(fhp);
/* Compose the fh so the dentry will be freed ... */
out_compose:
- fh_compose(resfhp, fhp->fh_export, dnew);
+ cerr = fh_compose(resfhp, fhp->fh_export, dnew);
+ if (err==0) err = cerr;
out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1186,7 +1195,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
if (err == -EXDEV && rqstp->rq_vers == 2)
err = nfserr_acces;
else
- err = nfserrno(-err);
+ err = nfserrno(err);
}
fh_unlock(ffhp);
@@ -1196,7 +1205,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1318,7 +1327,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1356,47 +1365,21 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
goto out;
}
-
- if (type != S_IFDIR) {
- /* It's UNLINK */
-
- err = fh_lock_parent(fhp, rdentry);
- if (err)
- goto out;
-
- err = vfs_unlink(dirp, rdentry);
-
- fh_unlock(fhp);
-
+ err = fh_lock_parent(fhp, rdentry);
+ if (err) {
dput(rdentry);
+ goto out;
+ }
- } else {
- /* It's RMDIR */
- /* See comments in fs/namei.c:do_rmdir */
-
- rdentry->d_count++;
- nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
-#ifdef CONFIG_NFSD_V3
- fill_pre_wcc(fhp);
-#else
- fhp->fh_locked = 1;
-#endif /* CONFIG_NFSD_V3 */
+ if (type != S_IFDIR) { /* It's UNLINK */
+ err = vfs_unlink(dirp, rdentry);
+ } else { /* It's RMDIR */
+ err = vfs_rmdir(dirp, rdentry);
+ }
- err = -ENOENT;
- if (nfsd_check_parent(dentry, rdentry))
- err = vfs_rmdir(dirp, rdentry);
+ fh_unlock(fhp);
- rdentry->d_count--;
-#ifdef CONFIG_NFSD_V3
- fill_post_wcc(fhp);
-#else
- fhp->fh_locked = 0;
-#endif /* CONFIG_NFSD_V3 */
- nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
- dput(rdentry);
- }
+ dput(rdentry);
if (err)
goto out_nfserr;
@@ -1409,7 +1392,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out;
}
@@ -1499,7 +1482,7 @@ out:
return err;
out_nfserr:
- err = nfserrno(-err);
+ err = nfserrno(err);
goto out_close;
}
@@ -1510,29 +1493,9 @@ out_nfserr:
int
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statfs *stat)
{
- struct dentry *dentry;
- struct inode *inode;
- struct super_block *sb;
- mm_segment_t oldfs;
- int err;
-
- err = fh_verify(rqstp, fhp, 0, MAY_NOP);
- if (err)
- goto out;
- dentry = fhp->fh_dentry;
- inode = dentry->d_inode;
-
- err = nfserr_io;
- if (!(sb = inode->i_sb) || !sb->s_op->statfs)
- goto out;
-
- oldfs = get_fs();
- set_fs (KERNEL_DS);
- sb->s_op->statfs(sb, stat, sizeof(*stat));
- set_fs (oldfs);
- err = 0;
-
-out:
+ int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
+ err = nfserr_io;
return err;
}
@@ -1617,7 +1580,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (current->fsuid != 0)
current->cap_effective = saved_cap;
- return err? nfserrno(-err) : 0;
+ return err? nfserrno(err) : 0;
}
void