Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help
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;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199505111045.TAA00285>