From owner-freebsd-bugs Sat Jan 22 1: 0: 9 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 6510A154D4 for ; Sat, 22 Jan 2000 01:00:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id BAA69068; Sat, 22 Jan 2000 01:00:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Date: Sat, 22 Jan 2000 01:00:02 -0800 (PST) Message-Id: <200001220900.BAA69068@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Bruce Evans Subject: Re: kern/15611: EIDE Large Disk Support, Newfs problem, File system corruption,IBM-DPTA-353750 Reply-To: Bruce Evans Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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