It appears msdosfs is using a vnode after having released its reference on
it, which could lead to a bad things under high load. I've patched the
OpenBSD errata to apply cleanly to FreeBSD.
--- msdosfs_vnops.c.orig Mon Jun 26 06:10:40 2000
+++ msdosfs_vnops.c Mon Jun 26 07:10:17 2000
@@ -1095,9 +1095,9 @@
newparent = 1;
vrele(fdvp);
if (doingdirectory && newparent) {
if (error) /* write access check above */
- goto bad;
+ goto bad1;
if (xp != NULL)
vput(tvp);
/*
* doscheckpath() vput()'s dp,
@@ -1123,22 +1123,22 @@
*/
if (xp->de_Attributes & ATTR_DIRECTORY) {
if (!dosdirempty(xp)) {
error = ENOTEMPTY;
- goto bad;
+ goto bad1;
}
if (!doingdirectory) {
error = ENOTDIR;
- goto bad;
+ goto bad1;
}
cache_purge(tdvp);
} else if (doingdirectory) {
error = EISDIR;
- goto bad;
+ goto bad1;
}
error = removede(dp, xp);
if (error)
- goto bad;
+ goto bad1;
vput(tvp);
xp = NULL;
}
@@ -1148,9 +1148,9 @@
* file/directory.
*/
error = uniqdosname(VTODE(tdvp), tcnp, toname);
if (error)
- goto abortit;
+ goto bad1;
/*
* Since from wasn't locked at various places above,
* have to do a relookup here.
@@ -1189,9 +1189,8 @@
if (xp != ip) {
if (doingdirectory)
panic("rename: lost dir entry");
vrele(ap->a_fvp);
- VOP_UNLOCK(fvp, 0, p);
if (newparent)
VOP_UNLOCK(fdvp, 0, p);
xp = NULL;
} else {
@@ -1214,9 +1213,8 @@
if (error) {
bcopy(oldname, ip->de_Name, 11);
if (newparent)
VOP_UNLOCK(fdvp, 0, p);
- VOP_UNLOCK(fvp, 0, p);
goto bad;
}
ip->de_refcnt++;
zp->de_fndoffset = from_diroffset;
@@ -1224,9 +1222,8 @@
if (error) {
/* XXX should really panic here, fs is corrupt */
if (newparent)
VOP_UNLOCK(fdvp, 0, p);
- VOP_UNLOCK(fvp, 0, p);
goto bad;
}
if (!doingdirectory) {
error = pcbmap(dp, de_cluster(pmp, to_diroffset), 0,
@@ -1234,9 +1231,8 @@
if (error) {
/* XXX should really panic here, fs is corrupt */
if (newparent)
VOP_UNLOCK(fdvp, 0, p);
- VOP_UNLOCK(fvp, 0, p);
goto bad;
}
if (ip->de_dirclust == MSDOSFSROOT)
ip->de_diroffset = to_diroffset;
@@ -1263,9 +1259,8 @@
NOCRED, &bp);
if (error) {
/* XXX should really panic here, fs is corrupt */
brelse(bp);
- VOP_UNLOCK(fvp, 0, p);
goto bad;
}
dotdotp = (struct direntry *)bp->b_data + 1;
putushort(dotdotp->deStartCluster, dp->de_StartCluster);
@@ -1273,21 +1268,21 @@
putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
error = bwrite(bp);
if (error) {
/* XXX should really panic here, fs is corrupt */
- VOP_UNLOCK(fvp, 0, p);
goto bad;
}
}
- VOP_UNLOCK(fvp, 0, p);
bad:
+ VOP_UNLOCK(fvp, 0, p);
+ vrele(fdvp);
+bad1:
if (xp)
vput(tvp);
vput(tdvp);
out:
ip->de_flag &= ~DE_RENAME;
- vrele(fdvp);
vrele(fvp);
return (error);
}
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message