diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/Makefile | 1 | ||||
-rw-r--r-- | fs/nfsd/export.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 71 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 17 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 7 | ||||
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 32 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 57 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 53 |
12 files changed, 159 insertions, 99 deletions
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile index ce341dc76d5e..9b118ee20193 100644 --- a/fs/nfsd/Makefile +++ b/fs/nfsd/Makefile @@ -11,4 +11,3 @@ nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ nfs4acl.o nfs4callback.o nfs4recover.o -nfsd-objs := $(nfsd-y) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6f24768272a1..79bd03b8bbf8 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -469,6 +469,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) nd.dentry = NULL; exp.ex_path = NULL; + /* fs locations */ + exp.ex_fslocs.locations = NULL; + exp.ex_fslocs.locations_count = 0; + exp.ex_fslocs.migrated = 0; + + exp.ex_uuid = NULL; + if (mesg[mlen-1] != '\n') return -EINVAL; mesg[mlen-1] = 0; @@ -509,13 +516,6 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) if (exp.h.expiry_time == 0) goto out; - /* fs locations */ - exp.ex_fslocs.locations = NULL; - exp.ex_fslocs.locations_count = 0; - exp.ex_fslocs.migrated = 0; - - exp.ex_uuid = NULL; - /* flags */ err = get_int(&mesg, &an_int); if (err == -ENOENT) diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 7f5bad0393b1..eac82830bfd7 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -177,7 +177,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, if (max_blocksize < resp->count) resp->count = max_blocksize; - svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); + svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); fh_copy(&resp->fh, &argp->fh); nfserr = nfsd_read(rqstp, &resp->fh, NULL, diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 7e4bb0af24d7..10f6e7dcf633 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -239,7 +239,7 @@ static __be32 * encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct dentry *dentry = fhp->fh_dentry; - if (dentry && dentry->d_inode != NULL) { + if (dentry && dentry->d_inode) { int err; struct kstat stat; @@ -300,9 +300,9 @@ int nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_sattrargs *args) { - if (!(p = decode_fh(p, &args->fh)) - || !(p = decode_sattr3(p, &args->attrs))) + if (!(p = decode_fh(p, &args->fh))) return 0; + p = decode_sattr3(p, &args->attrs); if ((args->check_guard = ntohl(*p++)) != 0) { struct timespec time; @@ -343,9 +343,9 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, int v,pn; u32 max_blocksize = svc_max_payload(rqstp); - if (!(p = decode_fh(p, &args->fh)) - || !(p = xdr_decode_hyper(p, &args->offset))) + if (!(p = decode_fh(p, &args->fh))) return 0; + p = xdr_decode_hyper(p, &args->offset); len = args->count = ntohl(*p++); @@ -369,28 +369,44 @@ int nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_writeargs *args) { - unsigned int len, v, hdr; + unsigned int len, v, hdr, dlen; u32 max_blocksize = svc_max_payload(rqstp); - if (!(p = decode_fh(p, &args->fh)) - || !(p = xdr_decode_hyper(p, &args->offset))) + if (!(p = decode_fh(p, &args->fh))) return 0; + p = xdr_decode_hyper(p, &args->offset); args->count = ntohl(*p++); args->stable = ntohl(*p++); len = args->len = ntohl(*p++); + /* + * The count must equal the amount of data passed. + */ + if (args->count != args->len) + return 0; + /* + * Check to make sure that we got the right number of + * bytes. + */ hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; - if (rqstp->rq_arg.len < hdr || - rqstp->rq_arg.len - hdr < len) + dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len + - hdr; + /* + * Round the length of the data which was specified up to + * the next multiple of XDR units and then compare that + * against the length which was actually received. + */ + if (dlen != XDR_QUADLEN(len)*4) return 0; + if (args->count > max_blocksize) { + args->count = max_blocksize; + len = args->len = max_blocksize; + } rqstp->rq_vec[0].iov_base = (void*)p; rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; - - if (len > max_blocksize) - len = max_blocksize; - v= 0; + v = 0; while (len > rqstp->rq_vec[v].iov_len) { len -= rqstp->rq_vec[v].iov_len; v++; @@ -398,9 +414,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, rqstp->rq_vec[v].iov_len = PAGE_SIZE; } rqstp->rq_vec[v].iov_len = len; - args->vlen = v+1; - - return args->count == args->len && rqstp->rq_vec[0].iov_len > 0; + args->vlen = v + 1; + return 1; } int @@ -414,8 +429,7 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, switch (args->createmode = ntohl(*p++)) { case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_GUARDED: - if (!(p = decode_sattr3(p, &args->attrs))) - return 0; + p = decode_sattr3(p, &args->attrs); break; case NFS3_CREATE_EXCLUSIVE: args->verf = p; @@ -431,10 +445,10 @@ int nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_createargs *args) { - if (!(p = decode_fh(p, &args->fh)) - || !(p = decode_filename(p, &args->name, &args->len)) - || !(p = decode_sattr3(p, &args->attrs))) + if (!(p = decode_fh(p, &args->fh)) || + !(p = decode_filename(p, &args->name, &args->len))) return 0; + p = decode_sattr3(p, &args->attrs); return xdr_argsize_check(rqstp, p); } @@ -448,11 +462,12 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, char *old, *new; struct kvec *vec; - if (!(p = decode_fh(p, &args->ffh)) - || !(p = decode_filename(p, &args->fname, &args->flen)) - || !(p = decode_sattr3(p, &args->attrs)) + if (!(p = decode_fh(p, &args->ffh)) || + !(p = decode_filename(p, &args->fname, &args->flen)) ) return 0; + p = decode_sattr3(p, &args->attrs); + /* now decode the pathname, which might be larger than the first page. * As we have to check for nul's anyway, we copy it into a new page * This page appears in the rq_res.pages list, but as pages_len is always @@ -502,10 +517,8 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p, args->ftype = ntohl(*p++); if (args->ftype == NF3BLK || args->ftype == NF3CHR - || args->ftype == NF3SOCK || args->ftype == NF3FIFO) { - if (!(p = decode_sattr3(p, &args->attrs))) - return 0; - } + || args->ftype == NF3SOCK || args->ftype == NF3FIFO) + p = decode_sattr3(p, &args->attrs); if (args->ftype == NF3BLK || args->ftype == NF3CHR) { args->major = ntohl(*p++); diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 673a53c014a3..cc3b7badd486 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -137,7 +137,6 @@ struct ace_container { static short ace2type(struct nfs4_ace *); static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); -void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); struct nfs4_acl * nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, @@ -785,21 +784,6 @@ nfs4_acl_new(int n) return acl; } -void -nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, - int whotype, uid_t who) -{ - struct nfs4_ace *ace = acl->aces + acl->naces; - - ace->type = type; - ace->flag = flag; - ace->access_mask = access_mask; - ace->whotype = whotype; - ace->who = who; - - acl->naces++; -} - static struct { char *string; int stringlen; @@ -851,6 +835,5 @@ nfs4_acl_write_who(int who, char *p) } EXPORT_SYMBOL(nfs4_acl_new); -EXPORT_SYMBOL(nfs4_acl_add_ace); EXPORT_SYMBOL(nfs4_acl_get_whotype); EXPORT_SYMBOL(nfs4_acl_write_who); diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index fb14d68eacab..32ffea033c7a 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -315,16 +315,13 @@ out: /* * RPC procedure tables */ -#ifndef MAX -# define MAX(a, b) (((a) > (b))? (a) : (b)) -#endif - #define PROC(proc, call, argtype, restype) \ [NFSPROC4_CLNT_##proc] = { \ .p_proc = NFSPROC4_CB_##call, \ .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \ .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \ - .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \ + .p_arglen = NFS4_##argtype##_sz, \ + .p_replen = NFS4_##restype##_sz, \ .p_statidx = NFSPROC4_CB_##call, \ .p_name = #proc, \ } diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index e4a83d727afd..45aa21ce6784 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -46,7 +46,6 @@ #include <linux/nfs4.h> #include <linux/nfs_fs.h> #include <linux/nfs_page.h> -#include <linux/smp_lock.h> #include <linux/sunrpc/cache.h> #include <linux/nfsd_idmap.h> #include <linux/list.h> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index af360705e551..3cc8ce422ab1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -50,6 +50,7 @@ #include <linux/nfsd/xdr4.h> #include <linux/namei.h> #include <linux/mutex.h> +#include <linux/lockd/bind.h> #define NFSDDBG_FACILITY NFSDDBG_PROC @@ -1325,8 +1326,6 @@ do_recall(void *__dp) { struct nfs4_delegation *dp = __dp; - daemonize("nfsv4-recall"); - nfsd4_cb_recall(dp); return 0; } @@ -2657,6 +2656,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct file_lock conflock; __be32 status = 0; unsigned int strhashval; + unsigned int cmd; int err; dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", @@ -2739,10 +2739,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, case NFS4_READ_LT: case NFS4_READW_LT: file_lock.fl_type = F_RDLCK; + cmd = F_SETLK; break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: file_lock.fl_type = F_WRLCK; + cmd = F_SETLK; break; default: status = nfserr_inval; @@ -2769,9 +2771,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, /* XXX?: Just to divert the locks_release_private at the start of * locks_copy_lock: */ - conflock.fl_ops = NULL; - conflock.fl_lmops = NULL; - err = posix_lock_file_conf(filp, &file_lock, &conflock); + locks_init_lock(&conflock); + err = vfs_lock_file(filp, cmd, &file_lock, &conflock); switch (-err) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); @@ -2788,7 +2789,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfserr_deadlock; break; default: - dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",err); + dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err); status = nfserr_resource; break; } @@ -2813,7 +2814,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct inode *inode; struct file file; struct file_lock file_lock; - struct file_lock conflock; + int error; __be32 status; if (nfs4_in_grace()) @@ -2869,18 +2870,23 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfs4_transform_lock_offset(&file_lock); - /* posix_test_lock uses the struct file _only_ to resolve the inode. + /* vfs_test_lock uses the struct file _only_ to resolve the inode. * since LOCKT doesn't require an OPEN, and therefore a struct - * file may not exist, pass posix_test_lock a struct file with + * file may not exist, pass vfs_test_lock a struct file with * only the dentry:inode set. */ memset(&file, 0, sizeof (struct file)); file.f_path.dentry = cstate->current_fh.fh_dentry; status = nfs_ok; - if (posix_test_lock(&file, &file_lock, &conflock)) { + error = vfs_test_lock(&file, &file_lock); + if (error) { + status = nfserrno(error); + goto out; + } + if (file_lock.fl_type != F_UNLCK) { status = nfserr_denied; - nfs4_set_lock_denied(&conflock, &lockt->lt_denied); + nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); } out: nfs4_unlock_state(); @@ -2933,9 +2939,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, /* * Try to unlock the file in the VFS. */ - err = posix_lock_file(filp, &file_lock); + err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); if (err) { - dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); + dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); goto out_nfserr; } /* diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5d090f11f2be..15809dfd88a5 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -44,7 +44,6 @@ #include <linux/param.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/namei.h> #include <linux/vfs.h> diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 8d995bcef806..6ca2d24fc216 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -10,7 +10,6 @@ */ #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/unistd.h> #include <linux/string.h> @@ -324,7 +323,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, * */ - u8 version = 1; + u8 version; u8 fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; @@ -342,15 +341,59 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, * the reference filehandle (if it is in the same export) * or the export options. */ + retry: + version = 1; if (ref_fh && ref_fh->fh_export == exp) { version = ref_fh->fh_handle.fh_version; - if (version == 0xca) + fsid_type = ref_fh->fh_handle.fh_fsid_type; + + if (ref_fh == fhp) + fh_put(ref_fh); + ref_fh = NULL; + + switch (version) { + case 0xca: fsid_type = FSID_DEV; - else - fsid_type = ref_fh->fh_handle.fh_fsid_type; - /* We know this version/type works for this export - * so there is no need for further checks. + break; + case 1: + break; + default: + goto retry; + } + + /* Need to check that this type works for this + * export point. As the fsid -> filesystem mapping + * was guided by user-space, there is no guarantee + * that the filesystem actually supports that fsid + * type. If it doesn't we loop around again without + * ref_fh set. */ + switch(fsid_type) { + case FSID_DEV: + if (!old_valid_dev(ex_dev)) + goto retry; + /* FALL THROUGH */ + case FSID_MAJOR_MINOR: + case FSID_ENCODE_DEV: + if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags + & FS_REQUIRES_DEV)) + goto retry; + break; + case FSID_NUM: + if (! (exp->ex_flags & NFSEXP_FSID)) + goto retry; + break; + case FSID_UUID8: + case FSID_UUID16: + if (!root_export) + goto retry; + /* fall through */ + case FSID_UUID4_INUM: + case FSID_UUID16_INUM: + if (exp->ex_uuid == NULL) + goto retry; + break; + } } else if (exp->ex_uuid) { if (fhp->fh_maxsize >= 64) { if (root_export) diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 5cc2eec981b8..b2c7147aa921 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -155,7 +155,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, argp->count); argp->count = NFSSVC_MAXBLKSIZE_V2; } - svc_reserve(rqstp, (19<<2) + argp->count + 4); + svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); resp->count = argp->count; nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL, diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 0c24b9e24fe8..cb3e7fadb772 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -231,9 +231,10 @@ int nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_sattrargs *args) { - if (!(p = decode_fh(p, &args->fh)) - || !(p = decode_sattr(p, &args->attrs))) + p = decode_fh(p, &args->fh); + if (!p) return 0; + p = decode_sattr(p, &args->attrs); return xdr_argsize_check(rqstp, p); } @@ -284,8 +285,9 @@ int nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_writeargs *args) { - unsigned int len; + unsigned int len, hdr, dlen; int v; + if (!(p = decode_fh(p, &args->fh))) return 0; @@ -293,11 +295,30 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, args->offset = ntohl(*p++); /* offset */ p++; /* totalcount */ len = args->len = ntohl(*p++); - rqstp->rq_vec[0].iov_base = (void*)p; - rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - - (((void*)p) - rqstp->rq_arg.head[0].iov_base); + /* + * The protocol specifies a maximum of 8192 bytes. + */ if (len > NFSSVC_MAXBLKSIZE_V2) - len = NFSSVC_MAXBLKSIZE_V2; + return 0; + + /* + * Check to make sure that we got the right number of + * bytes. + */ + hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; + dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len + - hdr; + + /* + * Round the length of the data which was specified up to + * the next multiple of XDR units and then compare that + * against the length which was actually received. + */ + if (dlen != XDR_QUADLEN(len)*4) + return 0; + + rqstp->rq_vec[0].iov_base = (void*)p; + rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; v = 0; while (len > rqstp->rq_vec[v].iov_len) { len -= rqstp->rq_vec[v].iov_len; @@ -306,18 +327,18 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, rqstp->rq_vec[v].iov_len = PAGE_SIZE; } rqstp->rq_vec[v].iov_len = len; - args->vlen = v+1; - return rqstp->rq_vec[0].iov_len > 0; + args->vlen = v + 1; + return 1; } int nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_createargs *args) { - if (!(p = decode_fh(p, &args->fh)) - || !(p = decode_filename(p, &args->name, &args->len)) - || !(p = decode_sattr(p, &args->attrs))) + if ( !(p = decode_fh(p, &args->fh)) + || !(p = decode_filename(p, &args->name, &args->len))) return 0; + p = decode_sattr(p, &args->attrs); return xdr_argsize_check(rqstp, p); } @@ -361,11 +382,11 @@ int nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_symlinkargs *args) { - if (!(p = decode_fh(p, &args->ffh)) - || !(p = decode_filename(p, &args->fname, &args->flen)) - || !(p = decode_pathname(p, &args->tname, &args->tlen)) - || !(p = decode_sattr(p, &args->attrs))) + if ( !(p = decode_fh(p, &args->ffh)) + || !(p = decode_filename(p, &args->fname, &args->flen)) + || !(p = decode_pathname(p, &args->tname, &args->tlen))) return 0; + p = decode_sattr(p, &args->attrs); return xdr_argsize_check(rqstp, p); } |