diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
commit | ba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch) | |
tree | 78670a0139bf4d5ace617b29b7eba82bbc74d602 /fs/nfsd | |
parent | b77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff) |
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 53 | ||||
-rw-r--r-- | fs/nfsd/nfscache.c | 27 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 4 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 86 |
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; |