summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs3proc.c5
-rw-r--r--fs/nfsd/nfsfh.c52
-rw-r--r--fs/nfsd/nfsproc.c7
-rw-r--r--fs/nfsd/nfssvc.c16
-rw-r--r--fs/nfsd/vfs.c10
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)