diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 12 | ||||
-rw-r--r-- | fs/nfsd/lockd.c | 17 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 182 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 37 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 66 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 201 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 148 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 65 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 201 |
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 |