svn commit: r192200 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ufs

Konstantin Belousov kib at FreeBSD.org
Sat May 16 17:15:27 UTC 2009


Author: kib
Date: Sat May 16 17:15:26 2009
New Revision: 192200
URL: http://svn.freebsd.org/changeset/base/192200

Log:
  MFC r191137:
  Verify that '..' still exists with the same inode number after
  VFS_VGET() has returned in ufs_lookup().
  
  MFC r191260:
  When verifying '..' after VFS_VGET() in ufs_lookup(), do not return
  error if '..' is still there but changed between lookup and check.
  Start relookup instead.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/ufs/ufs/ufs_lookup.c

Modified: stable/7/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- stable/7/sys/ufs/ufs/ufs_lookup.c	Sat May 16 15:21:08 2009	(r192199)
+++ stable/7/sys/ufs/ufs/ufs_lookup.c	Sat May 16 17:15:26 2009	(r192200)
@@ -77,6 +77,9 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, C
 /* true if old FS format...*/
 #define OFSFMT(vp)	((vp)->v_mount->mnt_maxsymlinklen <= 0)
 
+static int ufs_lookup_(struct vnode *, struct vnode **, struct componentname *,
+    ino_t *);
+
 /*
  * Convert a component of a pathname into a pointer to a locked inode.
  * This is a very central and rather complicated routine.
@@ -130,7 +133,14 @@ ufs_lookup(ap)
 		struct componentname *a_cnp;
 	} */ *ap;
 {
-	struct vnode *vdp;		/* vnode for directory being searched */
+
+	return (ufs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL));
+}
+
+static int
+ufs_lookup_(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
+    ino_t *dd_ino)
+{
 	struct inode *dp;		/* inode for directory being searched */
 	struct buf *bp;			/* a buffer of directory entries */
 	struct direct *ep;		/* the current directory entry */
@@ -150,24 +160,16 @@ ufs_lookup(ap)
 	doff_t enduseful;		/* pointer past last used dir slot */
 	u_long bmask;			/* block offset mask */
 	int namlen, error;
-	struct vnode **vpp = ap->a_vpp;
-	struct componentname *cnp = ap->a_cnp;
 	struct ucred *cred = cnp->cn_cred;
 	int flags = cnp->cn_flags;
 	int nameiop = cnp->cn_nameiop;
 	struct thread *td = cnp->cn_thread;
-	ino_t ino;
+	ino_t ino, ino1;
 	int ltype;
 
-	bp = NULL;
-	slotoffset = -1;
-/*
- *  XXX there was a soft-update diff about this I couldn't merge.
- * I think this was the equiv.
- */
-	*vpp = NULL;
+	if (vpp != NULL)
+		*vpp = NULL;
 
-	vdp = ap->a_dvp;
 	dp = VTOI(vdp);
 
 	/*
@@ -178,6 +180,12 @@ ufs_lookup(ap)
 	 */
 	vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread);
 
+	bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
+
+restart:
+	bp = NULL;
+	slotoffset = -1;
+
 	/*
 	 * We now have a segment name to search for, and a directory to search.
 	 *
@@ -195,7 +203,6 @@ ufs_lookup(ap)
 		slotstatus = NONE;
 		slotneeded = DIRECTSIZ(cnp->cn_namelen);
 	}
-	bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
 
 #ifdef UFS_DIRHASH
 	/*
@@ -364,7 +371,7 @@ foundentry:
 					slotoffset = i_offset;
 					slotsize = ep->d_reclen;
 					enduseful = dp->i_size;
-					ap->a_cnp->cn_flags |= ISWHITEOUT;
+					cnp->cn_flags |= ISWHITEOUT;
 					numdirpasses--;
 					goto notfound;
 				}
@@ -398,8 +405,8 @@ notfound:
 	 */
 	if ((nameiop == CREATE || nameiop == RENAME ||
 	     (nameiop == DELETE &&
-	      (ap->a_cnp->cn_flags & DOWHITEOUT) &&
-	      (ap->a_cnp->cn_flags & ISWHITEOUT))) &&
+	      (cnp->cn_flags & DOWHITEOUT) &&
+	      (cnp->cn_flags & ISWHITEOUT))) &&
 	    (flags & ISLASTCN) && dp->i_effnlink != 0) {
 		/*
 		 * Access for write is interpreted as allowing
@@ -454,7 +461,7 @@ notfound:
 	 * Insert name into cache (as non-existent) if appropriate.
 	 */
 	if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
-		cache_enter(vdp, *vpp, cnp);
+		cache_enter(vdp, NULL, cnp);
 	return (ENOENT);
 
 found:
@@ -480,6 +487,11 @@ found:
 	if ((flags & ISLASTCN) && nameiop == LOOKUP)
 		dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1);
 
+	if (dd_ino != NULL) {
+		*dd_ino = ino;
+		return (0);
+	}
+
 	/*
 	 * If deleting, and at end of pathname, return
 	 * parameters which can be used to remove file.
@@ -581,6 +593,22 @@ found:
 		error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp);
 		if (error)
 			return (error);
+
+		/*
+		 * Recheck that ".." entry in the vdp directory points
+		 * to the inode we looked up before vdp lock was
+		 * dropped.
+		 */
+		error = ufs_lookup_(pdp, NULL, cnp, &ino1);
+		if (error) {
+			vput(tdp);
+			return (error);
+		}
+		if (ino1 != ino) {
+			vput(tdp);
+			goto restart;
+		}
+
 		*vpp = tdp;
 	} else if (dp->i_number == ino) {
 		VREF(vdp);	/* we want ourself, ie "." */


More information about the svn-src-all mailing list