summaryrefslogtreecommitdiffstats
path: root/sys/fs/cd9660
diff options
context:
space:
mode:
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