Date: Thu, 11 May 1995 19:45:26 +0900 From: ohki@gssm.otsuka.tsukuba.ac.jp To: freebsd-bugs@FreeBSD.org Cc: ohki@gssm.otsuka.tsukuba.ac.jp Subject: problem for reading old CD-ROM Message-ID: <199505111045.TAA00285@smri01.gssm.otsuka.tsukuba.ac.jp>
index | next in thread | raw e-mail
Dear folks
I have a problem to read my old DOS CD-ROMs with FreeBSD 2.0.
My CD-ROMs are 512-byte logical block size,
and this causes sys/scsi/cd.c to fail reading 512-byte blocks
which are not aligned on 2KB boundaries.
Beside this, routines in sys/isofs/cd9660 do not work correctly,
since my CD-ROMs has directory entries which cross 512-byte block boundaries.
I hacked
i) sys/scsi/cd.c to allow unalinged 512-byte block I/O,
ii) sys/isofs/cd9660 routines to allow directory entries which
cross 512-byte block boundaries if its logical block size is not 2048.
This is done mainly with iso_blkatoff() routine.
I.e. if its logical block size is not 2048,
iso_blkatoff() always read one logical block with
the next 512-byte block.
Following context diffs are patches I make.
I'm sure there will be more smart solutions.
For example, make bread() handle block I/O which is not aligned
for underlaying devices.
#------------------------------------------------------------------------
--- sys/isofs/cd9660/cd9660_lookup.c-ORIG Mon Jan 16 12:14:00 1995
+++ sys/isofs/cd9660/cd9660_lookup.c-ohki Thu May 11 12:37:37 1995
@@ -240,6 +240,19 @@
searchloop:
while (dp->i_offset < endsearch) {
/*
+ * Take care of cross boundaries
+ */
+ if (iso_blkoff(imp, entryoffsetinblock)
+ != entryoffsetinblock) {
+ entryoffsetinblock = iso_blkoff(imp, entryoffsetinblock);
+ if (bp != NULL)
+ brelse(bp);
+ if ((error = iso_blkatoff(dp,
+ dp->i_offset - entryoffsetinblock,
+ &bp)))
+ return (error);
+ }
+ /*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
@@ -262,6 +275,8 @@
/* skip to next block, if any */
dp->i_offset =
roundup(dp->i_offset, imp->logical_block_size);
+ if (entryoffsetinblock == 0)
+ dp->i_offset += imp->logical_block_size;
continue;
}
@@ -269,7 +284,7 @@
/* illegal entry, stop */
break;
- if (entryoffsetinblock + reclen > imp->logical_block_size)
+ if (entryoffsetinblock + reclen > bp->b_bcount)
/* entries are not allowed to cross boundaries */
break;
@@ -461,6 +476,9 @@
int bsize = iso_blksize(imp,ip,lbn);
struct buf *bp;
int error;
+
+ if (offset >= 0 && bsize < ISO_DEFAULT_BLOCK_SIZE)
+ bsize += 512;
if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) {
brelse(bp);
--- sys/isofs/cd9660/cd9660_node.c-ORIG Thu Mar 16 12:16:00 1995
+++ sys/isofs/cd9660/cd9660_node.c-ohki Thu May 11 10:06:26 1995
@@ -267,7 +267,9 @@
default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */
if ((imp->im_flags&ISOFSMNT_EXTATT)
&& isonum_711(isodir->ext_attr_length))
- iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
+ iso_blkatoff(ip,
+ -isonum_711(isodir->ext_attr_length)
+ * imp->logical_block_size,
&bp2);
cd9660_defattr(isodir,ip,bp2,imp->iso_ftype );
cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype );
--- sys/isofs/cd9660/cd9660_vnops.c-ORIG Tue Mar 28 00:14:00 1995
+++ sys/isofs/cd9660/cd9660_vnops.c-ohki Thu May 11 12:39:15 1995
@@ -516,6 +516,19 @@
while (idp->curroff < endsearch) {
/*
+ * Take care of cross boundaries
+ */
+ if (iso_blkoff(imp, entryoffsetinblock)
+ != entryoffsetinblock) {
+ entryoffsetinblock = iso_blkoff(imp, entryoffsetinblock);
+ if (bp != NULL)
+ brelse(bp);
+ if ((error = iso_blkatoff(ip,
+ idp->curroff - entryoffsetinblock,
+ &bp)))
+ return (error);
+ }
+ /*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
@@ -536,12 +549,12 @@
(bp->b_un.b_addr + entryoffsetinblock);
reclen = isonum_711 (ep->length);
- isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
- &ep->date[6]: ep->flags);
if (reclen == 0) {
/* skip to next block, if any */
idp->curroff = roundup (idp->curroff,
imp->logical_block_size);
+ if (entryoffsetinblock == 0)
+ idp->curroff += imp->logical_block_size;
continue;
}
@@ -551,11 +564,13 @@
break;
}
- if (entryoffsetinblock + reclen > imp->logical_block_size) {
+ if (entryoffsetinblock + reclen > bp->b_bcount) {
error = EINVAL;
/* illegal directory, so stop looking */
break;
}
+ isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
+ &ep->date[6]: ep->flags);
/* XXX: be more intelligent if we can */
idp->current.d_type = DT_UNKNOWN;
--- sys/scsi/cd.c-ORIG Thu May 4 02:43:00 1995
+++ sys/scsi/cd.c-ohki Thu May 11 19:12:09 1995
@@ -350,6 +350,47 @@
return (0);
}
+/*
+ * for unaligned I/O
+ */
+static void
+cd_ul_strategy(struct buf *bp, struct scsi_link *sc_link)
+{
+ u_int32 unit = CDUNIT((bp->b_dev));
+ u_int32 blkoff, nblk;
+ struct scsi_data *cd = sc_link->sd;
+
+ struct buf *tbp;
+
+ blkoff = bp->b_blkno % (cd->params.blksize / 512);
+ nblk = (bp->b_bcount + blkoff*512 + (cd->params.blksize - 1))
+ / (cd->params.blksize);
+
+ tbp = malloc(sizeof(struct buf), M_TEMP, M_WAITOK);
+ bzero(tbp, sizeof(struct buf));
+
+ tbp->b_flags = B_INVAL | B_MALLOC | B_READ;
+ tbp->b_blkno = bp->b_blkno - blkoff;
+ tbp->b_dev = bp->b_dev;
+ tbp->b_resid = tbp->b_bcount = tbp->b_bufsize = nblk * cd->params.blksize;
+ tbp->b_un.b_addr = malloc(tbp->b_bufsize, M_TEMP, M_WAITOK);
+
+ cd_strategy(tbp, sc_link);
+ biowait(tbp);
+
+ if ((tbp->b_flags&B_ERROR) == 0 && tbp->b_resid == 0) {
+ bcopy(tbp->b_un.b_addr + blkoff*512, bp->b_un.b_addr, bp->b_bcount);
+ bp->b_resid = 0;
+ } else {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ bp->b_resid = bp->b_bcount;
+ }
+ free(tbp->b_un.b_addr, M_TEMP);
+ free(tbp, M_TEMP);
+ biodone(bp);
+}
+
/*
* Actually translate the requested transfer into one the physical driver can
@@ -395,6 +436,16 @@
bp->b_pblkno = bp->b_blkno;
bp->b_resid = 0;
}
+ /*
+ * take care of unaligned I/O
+ */
+ if (1) {
+ if ( bp->b_blkno % (cd->params.blksize / 512) ) {
+ cd_ul_strategy(bp, sc_link);
+ return;
+ }
+ }
+
opri = SPLCD();
dp = &cd->buf_queue;
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199505111045.TAA00285>
