From owner-freebsd-bugs Sat Jan 22 1:15:45 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from gidora.zeta.org.au (gidora.zeta.org.au [203.26.10.25]) by hub.freebsd.org (Postfix) with SMTP id 1DC43154F8 for ; Sat, 22 Jan 2000 01:15:04 -0800 (PST) (envelope-from bde@zeta.org.au) Received: (qmail 20231 invoked from network); 22 Jan 2000 09:15:00 -0000 Received: from bde.zeta.org.au (203.2.228.102) by gidora.zeta.org.au with SMTP; 22 Jan 2000 09:15:00 -0000 Date: Sat, 22 Jan 2000 20:14:59 +1100 (EST) From: Bruce Evans X-Sender: bde@alphplex.bde.org To: freebsd-bugs@FreeBSD.ORG Subject: Re: kern/15611: EIDE Large Disk Support, Newfs problem, File system corruption,IBM-DPTA-353750 In-Reply-To: <200001220900.BAA69068@freefall.freebsd.org> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org Please review the patch, especially the details for extended partitions, um, slices. Range checking for extended slices (the containers, not the contents) is still not done, but invalid sizes normally cause a read error. Bruce On Sat, 22 Jan 2000, Bruce Evans wrote: > The following reply was made to PR kern/15611; it has been noted by GNATS. > > From: Bruce Evans > To: rjbubon@bigi.com > Cc: freebsd-gnats-submit@FreeBSD.ORG > Subject: Re: kern/15611: EIDE Large Disk Support, Newfs problem, File system > corruption,IBM-DPTA-353750 > Date: Sat, 22 Jan 2000 19:58:14 +1100 (EST) > > On Tue, 21 Dec 1999 rjbubon@bigi.com wrote: > > > If I split the drive down the middle, 2 partitions, Strange things happen. > > I can load the first partition down with data. If I start writing to the 2nd > > partition, I corrupt the first. It's like the sector indexing in the OS > > is broke at some large number. Maybe an overflow. > > Addressing is broken in CHS mode for cylinder numbers >= 65536, since > cylinder numbers are blindly truncated mod 65536. > > The following patches give proper brokenness for -current. Large > disks are truncated to 65536 cylinders (normally 33.8GB). This is > simple in wd.c. Unfortunately, dsinit() "helpfully" enlarges the disk > if necessary to cover the slice entries in the MBR. This was once > necessary to support MFM disks with > 1024 cylinders, but it is wrong > for disks that report their size. > > Index: i386/isa/wd.c > =================================================================== > RCS file: /home/ncvs/src/sys/i386/isa/wd.c,v > retrieving revision 1.217 > diff -c -2 -r1.217 wd.c > *** i386/isa/wd.c 1999/12/10 09:40:29 1.217 > --- i386/isa/wd.c 2000/01/22 08:22:07 > *************** > *** 1761,1764 **** > --- 1761,1772 ---- > du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl; > } > + if (du->dk_dd.d_ncylinders > 0x10000 && !(du->cfg_flags & WDOPT_LBA)) { > + du->dk_dd.d_ncylinders = 0x10000; > + du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * > + du->dk_dd.d_ncylinders; > + printf( > + "wd%d: cannot handle %d total sectors; truncating to %lu\n", > + du->dk_lunit, wp->wdp_lbasize, du->dk_dd.d_secperunit); > + } > #if 0 > du->dk_dd.d_partitions[RAW_PART].p_size = du->dk_dd.d_secperunit; > Index: kern/subr_diskmbr.c > =================================================================== > RCS file: /home/ncvs/src/sys/kern/subr_diskmbr.c,v > retrieving revision 1.42 > diff -c -2 -r1.42 subr_diskmbr.c > *** kern/subr_diskmbr.c 1999/11/09 21:35:10 1.42 > --- kern/subr_diskmbr.c 2000/01/22 08:21:43 > *************** > *** 73,76 **** > --- 73,79 ---- > u_long ext_size, u_long base_ext_offset, > int nsectors, int ntracks, u_long mbr_offset)); > + static int dssetslice __P((char *sname, struct disklabel *lp, > + struct diskslice *sp, struct dos_partition *dp, > + u_long br_offset)); > > static int > *************** > *** 295,306 **** > --- 298,321 ---- > secpercyl = (u_long)max_nsectors * max_ntracks; > if (secpercyl != 0) { > + #if 0 > u_long secperunit; > + #endif > > lp->d_nsectors = max_nsectors; > lp->d_ntracks = max_ntracks; > lp->d_secpercyl = secpercyl; > + /* > + * Temporarily, don't even consider adjusting the drive's > + * size, since the adjusted size may exceed the hardware's > + * addressing capabilities. The adjustment helped mainly > + * for ancient MFM drives with > 1024 cylinders, but now > + * breaks at least IDE drives with 63*16*65536 sectors if > + * they are controlled by the wd driver in CHS mode. > + */ > + #if 0 > secperunit = secpercyl * max_ncyls; > if (lp->d_secperunit < secperunit) > lp->d_secperunit = secperunit; > + #endif > lp->d_ncylinders = lp->d_secperunit / secpercyl; > } > *************** > *** 320,335 **** > sp = &ssp->dss_slices[BASE_SLICE]; > for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) { > ! sp->ds_offset = mbr_offset + dp->dp_start; > ! sp->ds_size = dp->dp_size; > ! sp->ds_type = dp->dp_typ; > ! #ifdef PC98_ATCOMPAT > ! /* Fake FreeBSD(98). */ > ! if (sp->ds_type == DOSPTYP_386BSD) > ! sp->ds_type = 0x94; > ! #endif > ! #if 0 > ! lp->d_subtype |= (lp->d_subtype & 3) | dospart > ! | DSTYPE_INDOSPART; > ! #endif > } > ssp->dss_nslices = BASE_SLICE + NDOSPART; > --- 335,341 ---- > sp = &ssp->dss_slices[BASE_SLICE]; > for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) { > ! sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart, > ! RAW_PART, partname); > ! (void)dssetslice(sname, lp, sp, dp, mbr_offset); > } > ssp->dss_nslices = BASE_SLICE + NDOSPART; > *************** > *** 435,446 **** > continue; > } > ! sp->ds_offset = ext_offset + dp->dp_start; > ! sp->ds_size = dp->dp_size; > ! sp->ds_type = dp->dp_typ; > ! #ifdef PC98_ATCOMPAT > ! /* Fake FreeBSD(98). */ > ! if (sp->ds_type == DOSPTYP_386BSD) > ! sp->ds_type = 0x94; > ! #endif > ssp->dss_nslices++; > slice++; > --- 441,446 ---- > continue; > } > ! if (dssetslice(sname, lp, sp, dp, ext_offset) != 0) > ! continue; > ssp->dss_nslices++; > slice++; > *************** > *** 459,462 **** > --- 459,501 ---- > bp->b_flags |= B_INVAL | B_AGE; > brelse(bp); > + } > + > + static int > + dssetslice(sname, lp, sp, dp, br_offset) > + char *sname; > + struct disklabel *lp; > + struct diskslice *sp; > + struct dos_partition *dp; > + u_long br_offset; > + { > + u_long offset; > + u_long size; > + > + offset = br_offset + dp->dp_start; > + if (offset > lp->d_secperunit || offset < br_offset) { > + printf( > + "%s: slice starts beyond end of the disk: rejecting it\n", > + sname); > + return (1); > + } > + size = lp->d_secperunit - offset; > + if (size >= dp->dp_size) > + size = dp->dp_size; > + else > + printf( > + "%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n", > + sname, (u_long)dp->dp_size, size); > + sp->ds_offset = offset; > + sp->ds_size = size; > + sp->ds_type = dp->dp_typ; > + #ifdef PC98_ATCOMPAT > + /* Fake FreeBSD(98). */ > + if (sp->ds_type == DOSPTYP_386BSD) > + sp->ds_type = 0x94; > + #endif > + #if 0 > + lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART; > + #endif > + return (0); > } > > Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message