Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Jan 2012 17:56:46 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r229301 - in stable/9: sbin/geom/class/raid sys/geom/raid
Message-ID:  <201201021756.q02HukTK078721@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Jan  2 17:56:45 2012
New Revision: 229301
URL: http://svn.freebsd.org/changeset/base/229301

Log:
  MFC r226816:
  Clarify disks/volumes above 2TiB support in geom_raid:
   - add support for volumes above 2TiB with Promise metadata format;
   - enforse and document other limitations:
     - Intel and Promise metadata formats do not support disks above 2TiB;
     - NVIDIA metadata format does not support volumes above 2TiB.
  
  Sponsored by:   iXsystems, Inc.

Modified:
  stable/9/sbin/geom/class/raid/graid.8
  stable/9/sys/geom/raid/md_intel.c
  stable/9/sys/geom/raid/md_nvidia.c
  stable/9/sys/geom/raid/md_promise.c
Directory Properties:
  stable/9/sbin/geom/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/amd64/include/xen/   (props changed)
  stable/9/sys/boot/   (props changed)
  stable/9/sys/boot/i386/efi/   (props changed)
  stable/9/sys/boot/ia64/efi/   (props changed)
  stable/9/sys/boot/ia64/ski/   (props changed)
  stable/9/sys/boot/powerpc/boot1.chrp/   (props changed)
  stable/9/sys/boot/powerpc/ofw/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)
  stable/9/sys/conf/   (props changed)
  stable/9/sys/contrib/dev/acpica/   (props changed)
  stable/9/sys/contrib/octeon-sdk/   (props changed)
  stable/9/sys/contrib/pf/   (props changed)
  stable/9/sys/contrib/x86emu/   (props changed)

Modified: stable/9/sbin/geom/class/raid/graid.8
==============================================================================
--- stable/9/sbin/geom/class/raid/graid.8	Mon Jan  2 17:40:20 2012	(r229300)
+++ stable/9/sbin/geom/class/raid/graid.8	Mon Jan  2 17:56:45 2012	(r229301)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 22, 2011
+.Dd October 26, 2011
 .Dt GRAID 8
 .Os
 .Sh NAME
@@ -250,6 +250,9 @@ If you started migration using BIOS or i
 complete it there.
 Do not run GEOM RAID class on migrating volumes under pain of possible data
 corruption!
+.Sh 2TiB BARRIERS
+Intel and Promise metadata formats do not support disks above 2TiB.
+NVIDIA metadata format does not support volumes above 2TiB.
 .Sh EXIT STATUS
 Exit status is 0 on success, and non-zero if the command fails.
 .Sh SEE ALSO

Modified: stable/9/sys/geom/raid/md_intel.c
==============================================================================
--- stable/9/sys/geom/raid/md_intel.c	Mon Jan  2 17:40:20 2012	(r229300)
+++ stable/9/sys/geom/raid/md_intel.c	Mon Jan  2 17:56:45 2012	(r229301)
@@ -1172,15 +1172,18 @@ g_raid_md_taste_intel(struct g_raid_md_o
 	g_access(cp, -1, 0, 0);
 	if (meta == NULL) {
 		if (g_raid_aggressive_spare) {
-			if (vendor == 0x8086) {
+			if (vendor != 0x8086) {
+				G_RAID_DEBUG(1,
+				    "Intel vendor mismatch 0x%04x != 0x8086",
+				    vendor);
+			} else if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
+				G_RAID_DEBUG(1,
+				    "Intel disk '%s' is too big.", pp->name);
+			} else {
 				G_RAID_DEBUG(1,
 				    "No Intel metadata, forcing spare.");
 				spare = 2;
 				goto search;
-			} else {
-				G_RAID_DEBUG(1,
-				    "Intel vendor mismatch 0x%04x != 0x8086",
-				    vendor);
 			}
 		}
 		return (G_RAID_MD_TASTE_FAIL);
@@ -1194,9 +1197,9 @@ g_raid_md_taste_intel(struct g_raid_md_o
 	}
 	if (meta->disk[disk_pos].sectors !=
 	    (pp->mediasize / pp->sectorsize)) {
-		G_RAID_DEBUG(1, "Intel size mismatch %u != %u",
-		    meta->disk[disk_pos].sectors,
-		    (u_int)(pp->mediasize / pp->sectorsize));
+		G_RAID_DEBUG(1, "Intel size mismatch %ju != %ju",
+		    (off_t)meta->disk[disk_pos].sectors,
+		    (off_t)(pp->mediasize / pp->sectorsize));
 		goto fail1;
 	}
 
@@ -1449,6 +1452,13 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 			cp->private = disk;
 			g_topology_unlock();
 
+			if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
+				gctl_error(req,
+				    "Disk '%s' is too big.", diskname);
+				error = -8;
+				break;
+			}
+
 			error = g_raid_md_get_label(cp,
 			    &pd->pd_disk_meta.serial[0], INTEL_SERIAL_LEN);
 			if (error != 0) {
@@ -1940,6 +1950,14 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 			pp = cp->provider;
 			g_topology_unlock();
 
+			if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
+				gctl_error(req,
+				    "Disk '%s' is too big.", diskname);
+				g_raid_kill_consumer(sc, cp);
+				error = -8;
+				break;
+			}
+
 			/* Read disk serial. */
 			error = g_raid_md_get_label(cp,
 			    &serial[0], INTEL_SERIAL_LEN);

Modified: stable/9/sys/geom/raid/md_nvidia.c
==============================================================================
--- stable/9/sys/geom/raid/md_nvidia.c	Mon Jan  2 17:40:20 2012	(r229300)
+++ stable/9/sys/geom/raid/md_nvidia.c	Mon Jan  2 17:56:45 2012	(r229301)
@@ -1033,7 +1033,7 @@ g_raid_md_ctl_nvidia(struct g_raid_md_ob
 	char arg[16];
 	const char *verb, *volname, *levelname, *diskname;
 	int *nargs, *force;
-	off_t size, sectorsize, strip;
+	off_t size, sectorsize, strip, volsize;
 	intmax_t *sizearg, *striparg;
 	int numdisks, i, len, level, qual, update;
 	int error;
@@ -1182,7 +1182,20 @@ g_raid_md_ctl_nvidia(struct g_raid_md_ob
 			gctl_error(req, "Size too small.");
 			return (-13);
 		}
-		if (size > 0xffffffffffffllu * sectorsize) {
+
+		if (level == G_RAID_VOLUME_RL_RAID0 ||
+		    level == G_RAID_VOLUME_RL_CONCAT ||
+		    level == G_RAID_VOLUME_RL_SINGLE)
+			volsize = size * numdisks;
+		else if (level == G_RAID_VOLUME_RL_RAID1)
+			volsize = size;
+		else if (level == G_RAID_VOLUME_RL_RAID5)
+			volsize = size * (numdisks - 1);
+		else { /* RAID1E */
+			volsize = ((size * numdisks) / strip / 2) *
+			    strip;
+		}
+		if (volsize > 0xffffffffllu * sectorsize) {
 			gctl_error(req, "Size too big.");
 			return (-14);
 		}
@@ -1196,18 +1209,7 @@ g_raid_md_ctl_nvidia(struct g_raid_md_ob
 		vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
 		vol->v_strip_size = strip;
 		vol->v_disks_count = numdisks;
-		if (level == G_RAID_VOLUME_RL_RAID0 ||
-		    level == G_RAID_VOLUME_RL_CONCAT ||
-		    level == G_RAID_VOLUME_RL_SINGLE)
-			vol->v_mediasize = size * numdisks;
-		else if (level == G_RAID_VOLUME_RL_RAID1)
-			vol->v_mediasize = size;
-		else if (level == G_RAID_VOLUME_RL_RAID5)
-			vol->v_mediasize = size * (numdisks - 1);
-		else { /* RAID1E */
-			vol->v_mediasize = ((size * numdisks) / strip / 2) *
-			    strip;
-		}
+		vol->v_mediasize = volsize;
 		vol->v_sectorsize = sectorsize;
 		g_raid_start_volume(vol);
 

Modified: stable/9/sys/geom/raid/md_promise.c
==============================================================================
--- stable/9/sys/geom/raid/md_promise.c	Mon Jan  2 17:40:20 2012	(r229300)
+++ stable/9/sys/geom/raid/md_promise.c	Mon Jan  2 17:56:45 2012	(r229301)
@@ -121,7 +121,8 @@ struct promise_raid_conf {
 	uint64_t	rebuild_lba64;	/* Per-volume rebuild position. */
 	uint32_t	magic_4;
 	uint32_t	magic_5;
-	uint32_t	filler3[325];
+	uint32_t	total_sectors_high;
+	uint32_t	filler3[324];
 	uint32_t	checksum;
 } __packed;
 
@@ -213,6 +214,7 @@ g_raid_md_promise_print(struct promise_r
 	printf("rebuild_lba64       %ju\n", meta->rebuild_lba64);
 	printf("magic_4             0x%08x\n", meta->magic_4);
 	printf("magic_5             0x%08x\n", meta->magic_5);
+	printf("total_sectors_high  0x%08x\n", meta->total_sectors_high);
 	printf("=================================================\n");
 }
 
@@ -867,6 +869,9 @@ g_raid_md_promise_start(struct g_raid_vo
 	vol->v_strip_size = 512 << meta->stripe_shift; //ZZZ
 	vol->v_disks_count = meta->total_disks;
 	vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
+	if (meta->total_sectors_high < 256) /* If value looks sane. */
+		vol->v_mediasize |=
+		    ((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
 	vol->v_sectorsize = 512; //ZZZ
 	for (i = 0; i < vol->v_disks_count; i++) {
 		sd = &vol->v_subdisks[i];
@@ -1318,6 +1323,13 @@ g_raid_md_ctl_promise(struct g_raid_md_o
 			cp->private = disk;
 			g_topology_unlock();
 
+			if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
+				gctl_error(req,
+				    "Disk '%s' is too big.", diskname);
+				error = -8;
+				break;
+			}
+
 			/* Read kernel dumping information. */
 			disk->d_kd.offset = 0;
 			disk->d_kd.length = OFF_MAX;
@@ -1609,8 +1621,17 @@ g_raid_md_ctl_promise(struct g_raid_md_o
 				error = -4;
 				break;
 			}
+			pp = cp->provider;
 			g_topology_unlock();
 
+			if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
+				gctl_error(req,
+				    "Disk '%s' is too big.", diskname);
+				g_raid_kill_consumer(sc, cp);
+				error = -8;
+				break;
+			}
+
 			pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
 
 			disk = g_raid_create_disk(sc);
@@ -1716,6 +1737,8 @@ g_raid_md_write_promise(struct g_raid_md
 			meta->array_width /= 2;
 		meta->array_number = vol->v_global_id;
 		meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
+		meta->total_sectors_high =
+		    (vol->v_mediasize / vol->v_sectorsize) >> 32;
 		meta->cylinders = meta->total_sectors / (255 * 63) - 1;
 		meta->heads = 254;
 		meta->sectors = 63;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201021756.q02HukTK078721>