summaryrefslogtreecommitdiffstats
path: root/sys/fs/cd9660
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-11-04 06:18:55 +0000
committerdillon <dillon@FreeBSD.org>2001-11-04 06:18:55 +0000
commit25ccde64e70426c9f01780231c5af9e5b8920f7a (patch)
tree51a32c1f9f3651c12713bd32a7e8c0bf3f653162 /sys/fs/cd9660
parent27968acc29d3f4c68ae15494f6d6aad76f5d6258 (diff)
downloadFreeBSD-src-25ccde64e70426c9f01780231c5af9e5b8920f7a.zip
FreeBSD-src-25ccde64e70426c9f01780231c5af9e5b8920f7a.tar.gz
Fix a bug in CD9660 when vmiodirenable is turned on. CD9660 was assuming
that a buffer's b_blkno would be valid. This is true when vmiodirenable is turned off because the B_MALLOC'd buffer's data is invalidated when the buffer is destroyed. But when vmiodirenable is turned on a buffer can be reconstituted from its VMIO backing store. The reconstituted buffer will have no knowledge of the physical block translation and the result is serious directory corruption of the CDROM. The solution is to fix cd9660_blkatoff() to always BMAP the buffer if b_lblkno == b_blkno. MFC after: 0 days
Diffstat (limited to 'sys/fs/cd9660')
-rw-r--r--sys/fs/cd9660/cd9660_lookup.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c
index 979c0bd..90dd62b 100644
--- a/sys/fs/cd9660/cd9660_lookup.c
+++ b/sys/fs/cd9660/cd9660_lookup.c
@@ -415,12 +415,34 @@ cd9660_blkatoff(vp, offset, res, bpp)
imp = ip->i_mnt;
lbn = lblkno(imp, offset);
bsize = blksize(imp, ip, lbn);
-
+
if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
brelse(bp);
*bpp = NULL;
return (error);
}
+
+ /*
+ * We must BMAP the buffer because the directory code may use b_blkno
+ * to calculate the inode for certain types of directory entries.
+ * We could get away with not doing it before we VMIO-backed the
+ * directories because the buffers would get freed atomically with
+ * the invalidation of their data. But with VMIO-backed buffers
+ * the buffers may be freed and then later reconstituted - and the
+ * reconstituted buffer will have no knowledge of b_blkno.
+ */
+ if (bp->b_blkno == bp->b_lblkno) {
+ error = VOP_BMAP(vp, bp->b_lblkno, NULL,
+ &bp->b_blkno, NULL, NULL);
+ if (error) {
+ bp->b_error = error;
+ bp->b_flags |= B_ERROR;
+ brelse(bp);
+ *bpp = NULL;
+ return (error);
+ }
+ }
+
if (res)
*res = (char *)bp->b_data + blkoff(imp, offset);
*bpp = bp;
OpenPOWER on IntegriCloud