patch-2.3.99-pre7 linux/fs/nfsd/vfs.c

Next file: linux/fs/ntfs/Makefile
Previous file: linux/fs/nfsd/nfsctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre6/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -92,7 +92,7 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	 */
 	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 @@
 	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;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)