Date: Sat, 22 Jan 2000 20:14:59 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs@FreeBSD.ORG Subject: Re: kern/15611: EIDE Large Disk Support, Newfs problem, File system corruption,IBM-DPTA-353750 Message-ID: <Pine.BSF.4.21.0001222006030.1065-100000@alphplex.bde.org> In-Reply-To: <200001220900.BAA69068@freefall.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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 <bde@zeta.org.au>
> 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0001222006030.1065-100000>
