Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Jan 2000 01:00:02 -0800 (PST)
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:  <200001220900.BAA69068@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
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?200001220900.BAA69068>