diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 67 | ||||
-rw-r--r-- | fs/nfsd/nfs4idmap.c | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 8 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 21 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 45 | ||||
-rw-r--r-- | fs/nfsd/nfscache.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 27 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/stats.c | 10 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 15 |
12 files changed, 106 insertions, 98 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 3eec30000f3..01bc68c628a 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -126,7 +126,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) if (*ep) goto out; dprintk("found fsidtype %d\n", fsidtype); - if (fsidtype > 2) + if (key_len(fsidtype)==0) /* invalid type */ goto out; if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) goto out; diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index dbaf3f93f32..8583d99ee74 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -33,7 +33,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/list.h> #include <linux/inet.h> @@ -376,16 +375,28 @@ nfsd4_probe_callback(struct nfs4_client *clp) { struct sockaddr_in addr; struct nfs4_callback *cb = &clp->cl_callback; - struct rpc_timeout timeparms; - struct rpc_xprt * xprt; + struct rpc_timeout timeparms = { + .to_initval = (NFSD_LEASE_TIME/4) * HZ, + .to_retries = 5, + .to_maxval = (NFSD_LEASE_TIME/2) * HZ, + .to_exponential = 1, + }; struct rpc_program * program = &cb->cb_program; - struct rpc_stat * stat = &cb->cb_stat; - struct rpc_clnt * clnt; + struct rpc_create_args args = { + .protocol = IPPROTO_TCP, + .address = (struct sockaddr *)&addr, + .addrsize = sizeof(addr), + .timeout = &timeparms, + .servername = clp->cl_name.data, + .program = program, + .version = nfs_cb_version[1]->number, + .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ + .flags = (RPC_CLNT_CREATE_NOPING), + }; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, }; - char hostname[32]; int status; if (atomic_read(&cb->cb_set)) @@ -397,51 +408,27 @@ nfsd4_probe_callback(struct nfs4_client *clp) addr.sin_port = htons(cb->cb_port); addr.sin_addr.s_addr = htonl(cb->cb_addr); - /* Initialize timeout */ - timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ; - timeparms.to_retries = 0; - timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ; - timeparms.to_exponential = 1; - - /* Create RPC transport */ - xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms); - if (IS_ERR(xprt)) { - dprintk("NFSD: couldn't create callback transport!\n"); - goto out_err; - } - /* Initialize rpc_program */ program->name = "nfs4_cb"; program->number = cb->cb_prog; program->nrvers = ARRAY_SIZE(nfs_cb_version); program->version = nfs_cb_version; - program->stats = stat; + program->stats = &cb->cb_stat; /* Initialize rpc_stat */ - memset(stat, 0, sizeof(struct rpc_stat)); - stat->program = program; - - /* Create RPC client - * - * XXX AUTH_UNIX only - need AUTH_GSS.... - */ - sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); - clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); - if (IS_ERR(clnt)) { + memset(program->stats, 0, sizeof(cb->cb_stat)); + program->stats->program = program; + + /* Create RPC client */ + cb->cb_client = rpc_create(&args); + if (!cb->cb_client) { dprintk("NFSD: couldn't create callback client\n"); goto out_err; } - clnt->cl_intr = 0; - clnt->cl_softrtry = 1; /* Kick rpciod, put the call on the wire. */ - - if (rpciod_up() != 0) { - dprintk("nfsd: couldn't start rpciod for callbacks!\n"); + if (rpciod_up() != 0) goto out_clnt; - } - - cb->cb_client = clnt; /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); @@ -449,7 +436,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) msg.rpc_cred = nfsd4_lookupcred(clp,0); if (IS_ERR(msg.rpc_cred)) goto out_rpciod; - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); + status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); put_rpccred(msg.rpc_cred); if (status != 0) { @@ -463,7 +450,7 @@ out_rpciod: rpciod_down(); cb->cb_client = NULL; out_clnt: - rpc_shutdown_client(clnt); + rpc_shutdown_client(cb->cb_client); out_err: dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 4b6aa60dfce..b1902ebaab4 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -34,7 +34,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> @@ -574,10 +573,9 @@ idmap_lookup(struct svc_rqst *rqstp, struct idmap_defer_req *mdr; int ret; - mdr = kmalloc(sizeof(*mdr), GFP_KERNEL); + mdr = kzalloc(sizeof(*mdr), GFP_KERNEL); if (!mdr) return -ENOMEM; - memset(mdr, 0, sizeof(*mdr)); atomic_set(&mdr->count, 1); init_waitqueue_head(&mdr->waitq); mdr->req.defer = idmap_defer; diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index b0e095ea0c0..ee4eff27aed 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -721,6 +721,12 @@ nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) return nfs_ok; } +static inline void nfsd4_increment_op_stats(u32 opnum) +{ + if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP) + nfsdstats.nfs4_opcount[opnum]++; +} + /* * COMPOUND call. @@ -930,6 +936,8 @@ encode_op: /* XXX Ugh, we need to get rid of this kind of special case: */ if (op->opnum == OP_READ && op->u.read.rd_filp) fput(op->u.read.rd_filp); + + nfsd4_increment_op_stats(op->opnum); } out: diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 06da7506363..e35d7e52fde 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -33,7 +33,7 @@ * */ - +#include <linux/err.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> #include <linux/nfs4.h> @@ -87,34 +87,35 @@ int nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) { struct xdr_netobj cksum; - struct crypto_tfm *tfm; + struct hash_desc desc; struct scatterlist sg[1]; int status = nfserr_resource; dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", clname->len, clname->data); - tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); - if (tfm == NULL) - goto out; - cksum.len = crypto_tfm_alg_digestsize(tfm); + desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(desc.tfm)) + goto out_no_tfm; + cksum.len = crypto_hash_digestsize(desc.tfm); cksum.data = kmalloc(cksum.len, GFP_KERNEL); if (cksum.data == NULL) goto out; - crypto_digest_init(tfm); sg[0].page = virt_to_page(clname->data); sg[0].offset = offset_in_page(clname->data); sg[0].length = clname->len; - crypto_digest_update(tfm, sg, 1); - crypto_digest_final(tfm, cksum.data); + if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) + goto out; md5_to_hex(dname, cksum.data); kfree(cksum.data); status = nfs_ok; out: - crypto_free_tfm(tfm); + crypto_free_hash(desc.tfm); +out_no_tfm: return status; } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 96c7578cbe1..ebcf226a9e4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -123,7 +123,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags); */ /* recall_lock protects the del_recall_lru */ -static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(recall_lock); static struct list_head del_recall_lru; static void @@ -339,8 +339,7 @@ alloc_client(struct xdr_netobj name) { struct nfs4_client *clp; - if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) { - memset(clp, 0, sizeof(*clp)); + if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) { if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) { memcpy(clp->cl_name.data, name.data, name.len); clp->cl_name.len = name.len; @@ -529,8 +528,7 @@ move_to_confirmed(struct nfs4_client *clp) dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp); list_del_init(&clp->cl_strhash); - list_del_init(&clp->cl_idhash); - list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); + list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); strhashval = clientstr_hashval(clp->cl_recdir); list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); renew_client(clp); @@ -1007,13 +1005,10 @@ alloc_init_file(struct inode *ino) static void nfsd4_free_slab(kmem_cache_t **slab) { - int status; - if (*slab == NULL) return; - status = kmem_cache_destroy(*slab); + kmem_cache_destroy(*slab); *slab = NULL; - WARN_ON(status); } static void @@ -1238,8 +1233,15 @@ find_file(struct inode *ino) return NULL; } -#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) -#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) +static int access_valid(u32 x) +{ + return (x > 0 && x < 4); +} + +static int deny_valid(u32 x) +{ + return (x >= 0 && x < 5); +} static void set_access(unsigned int *access, unsigned long bmap) { @@ -1746,7 +1748,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf int status; status = nfserr_inval; - if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) + if (!access_valid(open->op_share_access) + || !deny_valid(open->op_share_deny)) goto out; /* * Lookup file; if found, lookup stateid and check open request, @@ -1783,10 +1786,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf } else { /* Stateid was not found, this is a new OPEN */ int flags = 0; + if (open->op_share_access & NFS4_SHARE_ACCESS_READ) + flags |= MAY_READ; if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) - flags = MAY_WRITE; - else - flags = MAY_READ; + flags |= MAY_WRITE; status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); if (status) goto out; @@ -2071,16 +2074,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl if (!stateid->si_fileid) { /* delegation stateid */ if(!(dp = find_delegation_stateid(ino, stateid))) { dprintk("NFSD: delegation stateid not found\n"); - if (nfs4_in_grace()) - status = nfserr_grace; goto out; } stidp = &dp->dl_stateid; } else { /* open or lock stateid */ if (!(stp = find_stateid(stateid, flags))) { dprintk("NFSD: open or lock stateid not found\n"); - if (nfs4_in_grace()) - status = nfserr_grace; goto out; } if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) @@ -2253,8 +2252,9 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs (int)current_fh->fh_dentry->d_name.len, current_fh->fh_dentry->d_name.name); - if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) - goto out; + status = fh_verify(rqstp, current_fh, S_IFREG, 0); + if (status) + return status; nfs4_lock_state(); @@ -2321,7 +2321,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n (int)current_fh->fh_dentry->d_name.len, current_fh->fh_dentry->d_name.name); - if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny)) + if (!access_valid(od->od_share_access) + || !deny_valid(od->od_share_deny)) return nfserr_inval; nfs4_lock_state(); diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index d852ebb538e..fdf7cf3dfad 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -103,8 +103,7 @@ nfsd_cache_shutdown(void) static void lru_put_end(struct svc_cacherep *rp) { - list_del(&rp->c_lru); - list_add_tail(&rp->c_lru, &lru_head); + list_move_tail(&rp->c_lru, &lru_head); } /* diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index a1810e6a93e..7046ac9cf97 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -6,7 +6,6 @@ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */ -#include <linux/config.h> #include <linux/module.h> #include <linux/linkage.h> diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 3f2ec2e6d06..501d8388453 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -188,11 +188,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) } /* Set user creds for this exportpoint */ - error = nfsd_setuser(rqstp, exp); - if (error) { - error = nfserrno(error); + error = nfserrno(nfsd_setuser(rqstp, exp)); + if (error) goto out; - } /* * Look up the dentry using the NFS file handle. @@ -248,9 +246,18 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) dprintk("nfsd: fh_verify - just checking\n"); dentry = fhp->fh_dentry; exp = fhp->fh_export; + /* Set user creds for this exportpoint; necessary even + * in the "just checking" case because this may be a + * filehandle that was created by fh_compose, and that + * is about to be used in another nfsv4 compound + * operation */ + error = nfserrno(nfsd_setuser(rqstp, exp)); + if (error) + goto out; } cache_get(&exp->h); + error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); if (error) goto out; @@ -312,8 +319,8 @@ int fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. - * if it is non-null, then we should compose a filehandle which is - * of the same version, where possible. + * if it is non-null and for the same filesystem, then we should compose + * a filehandle which is of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * @@ -332,7 +339,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); - if (ref_fh) { + if (ref_fh && ref_fh->fh_export == exp) { ref_fh_version = ref_fh->fh_handle.fh_version; if (ref_fh_version == 0xca) ref_fh_fsid_type = 0; @@ -461,7 +468,7 @@ fh_update(struct svc_fh *fhp) } else { int size; if (fhp->fh_handle.fh_fileid_type != 0) - goto out_uptodate; + goto out; datap = fhp->fh_handle.fh_auth+ fhp->fh_handle.fh_size/4 -1; size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; @@ -481,10 +488,6 @@ 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/nfssvc.c b/fs/nfsd/nfssvc.c index 3790727e5df..ec1decf29ba 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -8,7 +8,6 @@ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */ -#include <linux/config.h> #include <linux/module.h> #include <linux/time.h> diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 57265d56380..71944cddf68 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c @@ -72,6 +72,16 @@ static int nfsd_proc_show(struct seq_file *seq, void *v) /* show my rpc info */ svc_seq_show(seq, &nfsd_svcstats); +#ifdef CONFIG_NFSD_V4 + /* Show count for individual nfsv4 operations */ + /* Writing operation numbers 0 1 2 also for maintaining uniformity */ + seq_printf(seq,"proc4ops %u", LAST_NFS4_OP + 1); + for (i = 0; i <= LAST_NFS4_OP; i++) + seq_printf(seq, " %u", nfsdstats.nfs4_opcount[i]); + + seq_putc(seq, '\n'); +#endif + return 0; } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 245eaa1fb59..c9e3b5a8fe0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -16,7 +16,6 @@ * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp> */ -#include <linux/config.h> #include <linux/string.h> #include <linux/time.h> #include <linux/errno.h> @@ -673,7 +672,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, goto out_nfserr; if (access & MAY_WRITE) { - flags = O_WRONLY|O_LARGEFILE; + if (access & MAY_READ) + flags = O_RDWR|O_LARGEFILE; + else + flags = O_WRONLY|O_LARGEFILE; DQUOT_INIT(inode); } @@ -834,7 +836,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (ra && ra->p_set) file->f_ra = ra->p_ra; - if (file->f_op->sendfile) { + if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { svc_pushback_unused_pages(rqstp); err = file->f_op->sendfile(file, &offset, *count, nfsd_read_actor, rqstp); @@ -1517,14 +1519,15 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, err = nfserrno(err); } - fh_unlock(ffhp); dput(dnew); +out_unlock: + fh_unlock(ffhp); out: return err; out_nfserr: err = nfserrno(err); - goto out; + goto out_unlock; } /* @@ -1553,7 +1556,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, tdir = tdentry->d_inode; err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev; - if (fdir->i_sb != tdir->i_sb) + if (ffhp->fh_export != tfhp->fh_export) goto out; err = nfserr_perm; |