summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c86
1 files changed, 40 insertions, 46 deletions
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;