summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-05-12 21:05:59 +0000
commitba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch)
tree78670a0139bf4d5ace617b29b7eba82bbc74d602 /fs/nfsd
parentb77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff)
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c53
-rw-r--r--fs/nfsd/nfscache.c27
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/vfs.c86
4 files changed, 96 insertions, 74 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 6e98c1523..b674d1e95 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -150,7 +150,7 @@ exp_export(struct nfsctl_export *nxp)
svc_client *clp;
svc_export *exp, *parent;
svc_export **head;
- struct dentry *dentry = NULL;
+ struct nameidata nd;
struct inode *inode = NULL;
int i, err;
kdev_t dev;
@@ -190,12 +190,13 @@ exp_export(struct nfsctl_export *nxp)
}
/* Look up the dentry */
- err = -EINVAL;
- dentry = lookup_dentry(nxp->ex_path, LOOKUP_POSITIVE);
- if (IS_ERR(dentry))
+ err = 0;
+ if (path_init(nxp->ex_path, LOOKUP_POSITIVE, &nd))
+ err = path_walk(nxp->ex_path, &nd);
+ if (err)
goto out_unlock;
- inode = dentry->d_inode;
+ inode = nd.dentry->d_inode;
err = -EINVAL;
if (inode->i_dev != dev || inode->i_ino != nxp->ex_ino) {
printk(KERN_DEBUG "exp_export: i_dev = %x, dev = %x\n",
@@ -218,12 +219,12 @@ exp_export(struct nfsctl_export *nxp)
goto finish;
}
- if ((parent = exp_child(clp, dev, dentry)) != NULL) {
+ if ((parent = exp_child(clp, dev, nd.dentry)) != NULL) {
dprintk("exp_export: export not valid (Rule 3).\n");
goto finish;
}
/* Is this is a sub-export, must be a proper subset of FS */
- if ((parent = exp_parent(clp, dev, dentry)) != NULL) {
+ if ((parent = exp_parent(clp, dev, nd.dentry)) != NULL) {
dprintk("exp_export: sub-export not valid (Rule 2).\n");
goto finish;
}
@@ -236,7 +237,8 @@ exp_export(struct nfsctl_export *nxp)
strcpy(exp->ex_path, nxp->ex_path);
exp->ex_client = clp;
exp->ex_parent = parent;
- exp->ex_dentry = dentry;
+ exp->ex_dentry = nd.dentry;
+ exp->ex_mnt = nd.mnt;
exp->ex_flags = nxp->ex_flags;
exp->ex_dev = dev;
exp->ex_ino = ino;
@@ -270,7 +272,7 @@ out:
/* Release the dentry */
finish:
- dput(dentry);
+ path_release(&nd);
goto out_unlock;
}
@@ -284,6 +286,7 @@ exp_do_unexport(svc_export *unexp)
svc_export *exp;
svc_client *clp;
struct dentry *dentry;
+ struct vfsmount *mnt;
struct inode *inode;
int i;
@@ -296,10 +299,12 @@ exp_do_unexport(svc_export *unexp)
}
dentry = unexp->ex_dentry;
+ mnt = unexp->ex_mnt;
inode = dentry->d_inode;
if (unexp->ex_dev != inode->i_dev || unexp->ex_ino != inode->i_ino)
printk(KERN_WARNING "nfsd: bad dentry in unexport!\n");
dput(dentry);
+ mntput(mnt);
kfree(unexp);
}
@@ -376,38 +381,40 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
char *path, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
- struct dentry *dentry = NULL;
+ struct nameidata nd;
struct inode *inode;
struct svc_fh fh;
int err;
err = -EPERM;
if (path) {
- if (!(dentry = lookup_dentry(path, 0))) {
+ err = 0;
+ if (path_init(path, LOOKUP_POSITIVE, &nd))
+ err = path_walk(path, &nd);
+ if (err) {
printk("nfsd: exp_rootfh path not found %s", path);
return -EPERM;
}
- dev = dentry->d_inode->i_dev;
- ino = dentry->d_inode->i_ino;
+ dev = nd.dentry->d_inode->i_dev;
+ ino = nd.dentry->d_inode->i_ino;
dprintk("nfsd: exp_rootfh(%s [%p] %s:%x/%ld)\n",
- path, dentry, clp->cl_ident, dev, (long) ino);
- exp = exp_parent(clp, dev, dentry);
+ path, nd.dentry, clp->cl_ident, dev, (long) ino);
+ exp = exp_parent(clp, dev, nd.dentry);
} else {
dprintk("nfsd: exp_rootfh(%s:%x/%ld)\n",
clp->cl_ident, dev, (long) ino);
- if ((exp = exp_get(clp, dev, ino)))
- if (!(dentry = dget(exp->ex_dentry))) {
- printk("exp_rootfh: Aieee, NULL dentry\n");
- return -EPERM;
- }
+ if ((exp = exp_get(clp, dev, ino))) {
+ nd.mnt = mntget(exp->ex_mnt);
+ nd.dentry = dget(exp->ex_dentry);
+ }
}
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
}
- inode = dentry->d_inode;
+ inode = nd.dentry->d_inode;
if (!inode) {
printk("exp_rootfh: Aieee, NULL d_inode\n");
goto out;
@@ -423,7 +430,7 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
* fh must be initialized before calling fh_compose
*/
fh_init(&fh, maxsize);
- if (fh_compose(&fh, exp, dentry))
+ if (fh_compose(&fh, exp, nd.dentry))
err = -EINVAL;
else
err = 0;
@@ -432,7 +439,7 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
return err;
out:
- dput(dentry);
+ path_release(&nd);
return err;
}
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 370411d7c..79ef12a7b 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -34,10 +34,10 @@ struct nfscache_head {
struct svc_cacherep * prev;
};
-static struct nfscache_head hash_list[HASHSIZE];
+static struct nfscache_head * hash_list;
static struct svc_cacherep * lru_head;
static struct svc_cacherep * lru_tail;
-static struct svc_cacherep nfscache[CACHESIZE];
+static struct svc_cacherep * nfscache;
static int cache_initialized = 0;
static int cache_disabled = 1;
@@ -48,11 +48,27 @@ nfsd_cache_init(void)
{
struct svc_cacherep *rp;
struct nfscache_head *rh;
- int i;
+ size_t i;
if (cache_initialized)
return;
+ i = CACHESIZE * sizeof (struct svc_cacherep);
+ nfscache = kmalloc (i, GFP_KERNEL);
+ if (!nfscache) {
+ printk (KERN_ERR "nfsd: cannot allocate %d bytes for reply cache\n", i);
+ return;
+ }
+
+ i = HASHSIZE * sizeof (struct nfscache_head);
+ hash_list = kmalloc (i, GFP_KERNEL);
+ if (!hash_list) {
+ kfree (nfscache);
+ nfscache = NULL;
+ printk (KERN_ERR "nfsd: cannot allocate %d bytes for hash list\n", i);
+ return;
+ }
+
for (i = 0, rh = hash_list; i < HASHSIZE; i++, rh++)
rh->next = rh->prev = (struct svc_cacherep *) rh;
@@ -88,6 +104,11 @@ nfsd_cache_shutdown(void)
cache_initialized = 0;
cache_disabled = 1;
+
+ kfree (nfscache);
+ nfscache = NULL;
+ kfree (hash_list);
+ hash_list = NULL;
}
/*
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 65c70164a..c2607ff2e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -240,7 +240,7 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
if (cmd<0 || cmd > CMD_MAX)
goto done;
err = -EFAULT;
- argsize = sizes[cmd].argsize + sizeof(int); /* int for ca_version */
+ argsize = sizes[cmd].argsize + (int)&((struct nfsctl_arg *)0)->u;
respsize = sizes[cmd].respsize; /* maximum */
if (!access_ok(VERIFY_READ, argp, argsize)
|| (resp && !access_ok(VERIFY_WRITE, resp, respsize))) {
@@ -288,7 +288,7 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
break;
case NFSCTL_GETFS:
err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
- respsize = res->cr_getfs.fh_size+sizeof(int);
+ respsize = res->cr_getfs.fh_size+ (int)&((struct knfsd_fh*)0)->fh_base;
break;
default:
err = -EINVAL;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index cb6134ca1..1110e0938 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -92,7 +92,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
{
struct svc_export *exp;
struct dentry *dparent;
- struct nameidata nd;
+ struct dentry *dentry;
int err;
dprintk("nfsd: nfsd_lookup(fh %s, %s)\n", SVCFH_fmt(fhp), name);
@@ -105,76 +105,72 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
dparent = fhp->fh_dentry;
exp = fhp->fh_export;
-#if 0
- err = nfsd_permission(exp, dparent, MAY_EXEC);
- if (err)
- goto out;
-#endif
err = nfserr_acces;
/* Lookup the name, but don't follow links */
- if (strcmp(name, "..")==0) {
+ if (strcmp(name, ".")==0) {
+ dentry = dget(dparent);
+ } else if (strcmp(name, "..")==0) {
/* checking mountpoint crossing is very different when stepping up */
if (dparent == exp->ex_dentry) {
if (!EX_CROSSMNT(exp))
- nd.dentry = dget(dparent); /* .. == . just like at / */
+ dentry = dget(dparent); /* .. == . just like at / */
else
{
struct svc_export *exp2 = NULL;
struct dentry *dp;
- nd.dentry = dparent->d_covers->d_parent;
- for (dp=nd.dentry;
- exp2 == NULL && dp->d_covers->d_parent != dp;
- dp=dp->d_covers->d_parent)
+ struct vfsmount *mnt = mntget(exp->ex_mnt);
+ dentry = dget(dparent);
+ while(follow_up(&mnt, &dentry))
+ ;
+ dp = dget(dentry->d_parent);
+ dput(dentry);
+ dentry = dp;
+ for ( ; exp2 == NULL && dp->d_parent != dp;
+ dp=dp->d_parent)
exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
- if (exp2==NULL || nd.dentry->d_sb != exp2->ex_dentry->d_sb) {
- nd.dentry = dget(dparent);
+ if (exp2==NULL) {
+ dput(dentry);
+ dentry = dget(dparent);
} else {
- dget(nd.dentry);
exp = exp2;
}
+ mntput(mnt);
}
} else
- nd.dentry = dget(dparent->d_parent);
+ dentry = dget(dparent->d_parent);
} else {
- nd.mnt = NULL;
- nd.dentry = dget(dparent);
- nd.flags = 0;
- err = walk_name(name, &nd);
- if (err)
+ dentry = lookup_one(name, dparent);
+ err = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
goto out_nfserr;
/*
* check if we have crossed a mount point ...
*/
- if (nd.dentry->d_sb != dparent->d_sb) {
+ if (d_mountpoint(dentry)) {
struct svc_export *exp2 = NULL;
+ struct vfsmount *mnt = mntget(exp->ex_mnt);
+ struct dentry *mounts = dget(dentry);
+ while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
+ ;
exp2 = exp_get(rqstp->rq_client,
- nd.dentry->d_inode->i_dev,
- nd.dentry->d_inode->i_ino);
- if (exp2 && EX_CROSSMNT(exp2))
+ mounts->d_inode->i_dev,
+ mounts->d_inode->i_ino);
+ if (exp2 && EX_CROSSMNT(exp2)) {
/* successfully crossed mount point */
exp = exp2;
- else if (nd.dentry->d_covers->d_sb == dparent->d_sb) {
- /* stay in the original filesystem */
- struct dentry *tdentry = dget(nd.dentry->d_covers);
- dput(nd.dentry);
- nd.dentry = tdentry;
- } else {
- /* This cannot possibly happen */
- printk("nfsd_lookup: %s/%s impossible mount point!\n", dparent->d_name.name, nd.dentry->d_name.name);
- dput(nd.dentry);
- err = nfserr_acces;
- goto out;
-
- }
+ dput(dentry);
+ dentry = mounts;
+ } else
+ dput(mounts);
}
}
/*
* Note: we compose the file handle now, but as the
* dentry may be negative, it may need to be updated.
*/
- err = fh_compose(resfh, exp, nd.dentry);
- if (!err && !nd.dentry->d_inode)
+ err = fh_compose(resfh, exp, dentry);
+ if (!err && !dentry->d_inode)
err = nfserr_noent;
out:
return err;
@@ -201,11 +197,9 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
int size_change = 0;
if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
- accmode |= MAY_WRITE;
- if (iap->ia_valid & ATTR_SIZE) {
- accmode |= MAY_OWNER_OVERRIDE;
+ accmode |= MAY_WRITE|MAY_OWNER_OVERRIDE;
+ if (iap->ia_valid & ATTR_SIZE)
ftype = S_IFREG;
- }
/* Get inode */
err = fh_verify(rqstp, fhp, ftype, accmode);
@@ -964,7 +958,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
*/
dchild = lookup_one(fname, dentry);
err = PTR_ERR(dchild);
- if(IS_ERR(dchild))
+ if (IS_ERR(dchild))
goto out_nfserr;
err = fh_compose(resfhp, fhp->fh_export, dchild);
@@ -1051,7 +1045,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
mm_segment_t oldfs;
int err;
- err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ);
+ err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP);
if (err)
goto out;