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-stable
mailing list