From owner-freebsd-bugs Thu May 11 03:46:55 1995 Return-Path: bugs-owner Received: (from majordom@localhost) by freefall.cdrom.com (8.6.10/8.6.6) id DAA26243 for bugs-outgoing; Thu, 11 May 1995 03:46:55 -0700 Received: from jp-gate.wide.ad.jp (jp-gate.wide.ad.jp [133.4.1.1]) by freefall.cdrom.com (8.6.10/8.6.6) with ESMTP id DAA26237 for ; Thu, 11 May 1995 03:46:52 -0700 From: ohki@gssm.otsuka.tsukuba.ac.jp Received: from utogw.gssm.otsuka.tsukuba.ac by jp-gate.wide.ad.jp (8.6.4+2.2W/2.8Wb-jp-gate/1.2) with SMTP id TAA24081; Thu, 11 May 1995 19:46:28 +0900 Received: from [192.50.17.160] by utogw.gssm.otsuka.tsukuba.ac.jp (5.64/6.4J.6-gssm-2.0) id AA09348; Thu, 11 May 95 19:45:27 +0900 Received: from localhost by smri01.gssm.otsuka.tsukuba.ac.jp (8.6.11/SMI-4.1) id TAA00285; Thu, 11 May 1995 19:45:27 +0900 Message-Id: <199505111045.TAA00285@smri01.gssm.otsuka.tsukuba.ac.jp> To: freebsd-bugs@FreeBSD.org Cc: ohki@gssm.otsuka.tsukuba.ac.jp Subject: problem for reading old CD-ROM Mime-Version: 1.0 Content-Type: text/plain;charset="US-ASCII" Date: Thu, 11 May 1995 19:45:26 +0900 Sender: bugs-owner@FreeBSD.org Precedence: bulk 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;