diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs3proc.c | 5 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 52 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 7 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 16 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 10 |
5 files changed, 63 insertions, 27 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 3e132a75b..5396a784f 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -339,8 +339,10 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, argp->tname, argp->tlen, &newfh); - if (nfserr) + if (!nfserr) { + argp->attrs.ia_valid &= ~ATTR_SIZE; nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs); + } fh_put(&argp->ffh); fh_put(&newfh); @@ -362,6 +364,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, SVCFH_INO(&argp->fh), argp->name); + argp->attrs.ia_valid &= ~ATTR_SIZE; nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, &argp->attrs, S_IFDIR, 0, &resp->fh); fh_put(&argp->fh); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 0a3cc3f8b..6f6b4a733 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -13,6 +13,7 @@ #include <linux/string.h> #include <linux/stat.h> #include <linux/dcache.h> +#include <asm/pgtable.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> @@ -235,7 +236,7 @@ retry: /* * Search for a path entry for the specified (dev, inode). */ -struct nfsd_path *get_path_entry(kdev_t dev, ino_t ino) +static struct nfsd_path *get_path_entry(kdev_t dev, ino_t ino) { struct nfsd_path *pe; struct list_head *tmp; @@ -713,7 +714,6 @@ printk("find_dentry_by_ino: getting root dentry for %s\n", kdevname(dev)); dentry = dget(fhe->dentry); goto out; } - /* * Search the path cache ... */ @@ -859,6 +859,34 @@ static struct dentry *nfsd_cached_lookup(struct knfs_fh *fh) return NULL; } +void +expire_all(void) +{ + if (time_after_eq(jiffies, nfsd_next_expire)) { + expire_old(NFSD_FILE_CACHE, 5*HZ); + expire_old(NFSD_DIR_CACHE , 60*HZ); + nfsd_next_expire = jiffies + 5*HZ; + } +} + +/* + * Free cache after unlink/rmdir. + */ +void +expire_by_dentry(struct dentry *dentry) +{ + struct fh_entry *fhe; + + fhe = find_fhe(dentry, NFSD_FILE_CACHE, NULL); + if (fhe) { + expire_fhe(fhe, NFSD_FILE_CACHE); + } + fhe = find_fhe(dentry, NFSD_DIR_CACHE, NULL); + if (fhe) { + expire_fhe(fhe, NFSD_DIR_CACHE); + } +} + /* * The is the basic lookup mechanism for turning an NFS file handle * into a dentry. There are several levels to the search: @@ -997,15 +1025,8 @@ out: add_to_lookup_cache(dentry, fh); } - /* - * Perform any needed housekeeping ... - * N.B. move this into one of the daemons ... - */ - if (time_after_eq(jiffies, nfsd_next_expire)) { - expire_old(NFSD_FILE_CACHE, 5*HZ); - expire_old(NFSD_DIR_CACHE , 60*HZ); - nfsd_next_expire = jiffies + 5*HZ; - } + expire_all(); + return dentry; } @@ -1133,7 +1154,7 @@ dprintk("fh_verify: no root_squashed access.\n"); #ifdef NFSD_PARANOIA if (error) printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, access, error); +dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24)); #endif out: return error; @@ -1260,11 +1281,8 @@ static int nfsd_d_validate(struct dentry *dentry) goto bad_addr; if ((dent_addr & ~align_mask) != dent_addr) goto bad_align; - /* XXX: Should test here, whether the address doesn't belong to - a physical memory hole on sparc32/sparc64. Then it is not - safe to dereference it. On the other side, the previous - use of num_physpages instead of max_mapnr caused the same - to happen, plus some valid addresses could get rejected. -jj */ + if (!kern_addr_valid(dent_addr)) + goto bad_addr; /* * Looks safe enough to dereference ... */ diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 8b115ed3a..7c3e24817 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -382,8 +382,10 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp, nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, argp->tname, argp->tlen, &newfh); - if (!nfserr) + if (!nfserr) { + argp->attrs.ia_valid &= ~ATTR_SIZE; nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs); + } fh_put(&argp->ffh); fh_put(&newfh); @@ -407,6 +409,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, "nfsd_proc_mkdir: response already verified??\n"); } + argp->attrs.ia_valid &= ~ATTR_SIZE; nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, &argp->attrs, S_IFDIR, 0, &resp->fh); fh_put(&argp->fh); @@ -515,7 +518,7 @@ struct svc_procedure nfsd_procedures2[18] = { PROC(symlink, symlinkargs, void, none, RC_REPLSTAT), PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF), PROC(rmdir, diropargs, void, none, RC_REPLSTAT), - PROC(readdir, readdirargs, readdirres, none, RC_REPLSTAT), + PROC(readdir, readdirargs, readdirres, none, RC_REPLBUFF), PROC(statfs, fhandle, statfsres, none, RC_NOCACHE), }; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index ff1608a82..b7fa534e0 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -101,7 +101,7 @@ static void nfsd(struct svc_rqst *rqstp) { struct svc_serv *serv = rqstp->rq_server; - int oldumask, err; + int oldumask, err, first = 0; /* Lock module and set up kernel thread */ MOD_INC_USE_COUNT; @@ -115,8 +115,10 @@ nfsd(struct svc_rqst *rqstp) oldumask = current->fs->umask; /* Set umask to 0. */ current->fs->umask = 0; - if (!nfsd_active++) + if (!nfsd_active++) { nfssvc_boot = xtime; /* record boot time */ + first = 1; + } lockd_up(); /* start lockd */ /* @@ -133,8 +135,14 @@ nfsd(struct svc_rqst *rqstp) * Find a socket with data available and call its * recvfrom routine. */ - while ((err = svc_recv(serv, rqstp, MAX_SCHEDULE_TIMEOUT)) == -EAGAIN) - ; + while ((err = svc_recv(serv, rqstp, + first?5*HZ:MAX_SCHEDULE_TIMEOUT)) == -EAGAIN) { + if (first && 1) { + exp_readlock(); + expire_all(); + exp_unlock(); + } + } if (err < 0) break; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 109ed75ec..4ef61fe45 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -11,7 +11,7 @@ * So if you notice code paths that apparently fail to dput() the * dentry, don't worry--they have been taken care of. * - * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> + * Copyright (C) 1995-1999 Olaf Kirch <okir@monad.swb.de> */ #include <linux/config.h> @@ -734,7 +734,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, * directories via NFS. */ err = 0; - if ((iap->ia_valid &= (ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) + if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) err = nfsd_setattr(rqstp, resfhp, iap); out: return err; @@ -959,7 +959,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, goto out_unlock; err = nfserr_perm; - if (IS_IMMUTABLE(dest) /* || IS_APPEND(dest) */ ) + if (IS_IMMUTABLE(dest) || IS_APPEND(dest)) goto out_unlock; if (!dirp->i_op || !dirp->i_op->link) goto out_unlock; @@ -1139,8 +1139,11 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, goto out; } + expire_by_dentry(rdentry); + if (type != S_IFDIR) { /* It's UNLINK */ + err = fh_lock_parent(fhp, rdentry); if (err) goto out; @@ -1155,6 +1158,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, } 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); if (!fhp->fh_pre_mtime) |