svn commit: r245522 - in head: sbin/geom/class/raid sys/geom/raid

Alexander Motin mav at FreeBSD.org
Thu Jan 17 00:50:26 UTC 2013


Author: mav
Date: Thu Jan 17 00:50:25 2013
New Revision: 245522
URL: http://svnweb.freebsd.org/changeset/base/245522

Log:
  For Promise/AMD metadata add support for disks with capacity above 2TiB
  and for volumes with sector size above 512 bytes.

Modified:
  head/sbin/geom/class/raid/graid.8
  head/sys/geom/raid/md_promise.c

Modified: head/sbin/geom/class/raid/graid.8
==============================================================================
--- head/sbin/geom/class/raid/graid.8	Thu Jan 17 00:42:30 2013	(r245521)
+++ head/sbin/geom/class/raid/graid.8	Thu Jan 17 00:50:25 2013	(r245522)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 13, 2012
+.Dd January 16, 2013
 .Dt GRAID 8
 .Os
 .Sh NAME
@@ -274,7 +274,6 @@ complete it there.
 Do not run GEOM RAID class on migrating volumes under pain of possible data
 corruption!
 .Sh 2TiB BARRIERS
-Promise metadata format does not support disks above 2TiB.
 NVIDIA metadata format does not support volumes above 2TiB.
 .Sh SYSCTL VARIABLES
 The following

Modified: head/sys/geom/raid/md_promise.c
==============================================================================
--- head/sys/geom/raid/md_promise.c	Thu Jan 17 00:42:30 2013	(r245521)
+++ head/sys/geom/raid/md_promise.c	Thu Jan 17 00:50:25 2013	(r245522)
@@ -84,7 +84,7 @@ struct promise_raid_conf {
 	struct promise_raid_disk	disk;	/* This subdisk info. */
 	uint32_t	disk_offset;		/* Subdisk offset. */
 	uint32_t	disk_sectors;		/* Subdisk size */
-	uint32_t	rebuild_lba;		/* Rebuild position. */
+	uint32_t	disk_rebuild;		/* Rebuild position. */
 	uint16_t	generation;		/* Generation number. */
 	uint8_t		status;			/* Volume status. */
 #define PROMISE_S_VALID		0x01
@@ -123,7 +123,17 @@ struct promise_raid_conf {
 	uint32_t	magic_4;
 	uint32_t	magic_5;
 	uint32_t	total_sectors_high;
-	uint32_t	filler3[324];
+	uint8_t		magic_6;
+	uint8_t		sector_size;
+	uint16_t	magic_7;
+	uint32_t	magic_8[32];
+	uint16_t	magic_9;
+	uint32_t	disk_offset_high;
+	uint32_t	disk_sectors_high;
+	uint32_t	disk_rebuild_high;
+	uint16_t	magic_10;
+	uint32_t	magic_11[3];
+	uint32_t	filler3[284];
 	uint32_t	checksum;
 } __packed;
 
@@ -191,7 +201,7 @@ g_raid_md_promise_print(struct promise_r
 	    meta->disk.device, meta->disk.id);
 	printf("disk_offset         %u\n", meta->disk_offset);
 	printf("disk_sectors        %u\n", meta->disk_sectors);
-	printf("rebuild_lba         %u\n", meta->rebuild_lba);
+	printf("disk_rebuild        %u\n", meta->disk_rebuild);
 	printf("generation          %u\n", meta->generation);
 	printf("status              0x%02x\n", meta->status);
 	printf("type                %u\n", meta->type);
@@ -217,6 +227,10 @@ g_raid_md_promise_print(struct promise_r
 	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("sector_size         %u\n", meta->sector_size);
+	printf("disk_offset_high    0x%08x\n", meta->disk_offset_high);
+	printf("disk_sectors_high   0x%08x\n", meta->disk_sectors_high);
+	printf("disk_rebuild_high   0x%08x\n", meta->disk_rebuild_high);
 	printf("=================================================\n");
 }
 
@@ -244,9 +258,9 @@ promise_meta_find_disk(struct promise_ra
 
 static int
 promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
-    uint32_t sectors, uint32_t *off, uint32_t *size)
+    off_t sectors, off_t *off, off_t *size)
 {
-	uint32_t coff, csize;
+	off_t coff, csize, tmp;
 	int i, j;
 
 	sectors -= 131072;
@@ -257,10 +271,10 @@ promise_meta_unused_range(struct promise
 	i = 0;
 	while (1) {
 		for (j = 0; j < nsd; j++) {
-			if (metaarr[j]->disk_offset >= coff) {
-				csize = MIN(csize,
-				    metaarr[j]->disk_offset - coff);
-			}
+			tmp = ((off_t)metaarr[j]->disk_offset_high << 32) +
+			    metaarr[j]->disk_offset;
+			if (tmp >= coff)
+				csize = MIN(csize, tmp - coff);
 		}
 		if (csize > *size) {
 			*off = coff;
@@ -268,7 +282,10 @@ promise_meta_unused_range(struct promise
 		}
 		if (i >= nsd)
 			break;
-		coff = metaarr[i]->disk_offset + metaarr[i]->disk_sectors;
+		coff = ((off_t)metaarr[i]->disk_offset_high << 32) +
+		     metaarr[i]->disk_offset +
+		    ((off_t)metaarr[i]->disk_sectors_high << 32) +
+		     metaarr[i]->disk_sectors;
 		csize = sectors - coff;
 		i++;
 	};
@@ -369,6 +386,25 @@ next:
 		return (subdisks);
 	}
 
+	/* Remove filler garbage from fields used in newer metadata. */
+	if (meta->disk_offset_high == 0x8b8c8d8e &&
+	    meta->disk_sectors_high == 0x8788898a &&
+	    meta->disk_rebuild_high == 0x83848586) {
+		meta->disk_offset_high = 0;
+		meta->disk_sectors_high = 0;
+		if (meta->disk_rebuild == UINT32_MAX)
+			meta->disk_rebuild_high = UINT32_MAX;
+		else
+			meta->disk_rebuild_high = 0;
+		if (meta->total_sectors_high == 0x15161718) {
+			meta->total_sectors_high = 0;
+			if (meta->rebuild_lba64 == 0x2122232425262728)
+				meta->rebuild_lba64 = UINT64_MAX;
+		}
+	}
+	if (meta->sector_size < 1 || meta->sector_size > 8)
+		meta->sector_size = 1;
+
 	/* Save this part and look for next. */
 	*metaarr = meta;
 	metaarr++;
@@ -386,8 +422,9 @@ promise_meta_write(struct g_consumer *cp
 	struct g_provider *pp;
 	struct promise_raid_conf *meta;
 	char *buf;
+	off_t off, size;
 	int error, i, subdisk, fake;
-	uint32_t checksum, *ptr, off, size;
+	uint32_t checksum, *ptr;
 
 	pp = cp->provider;
 	subdisk = 0;
@@ -409,9 +446,12 @@ next:
 		meta->disk.flags = PROMISE_F_ONLINE | PROMISE_F_VALID;
 		meta->disk.number = 0xff;
 		arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
-		meta->disk_offset = off;
-		meta->disk_sectors = size;
-		meta->rebuild_lba = UINT32_MAX;
+		meta->disk_offset_high = off >> 32;
+		meta->disk_offset = (uint32_t)off;
+		meta->disk_sectors_high = size >> 32;
+		meta->disk_sectors = (uint32_t)size;
+		meta->disk_rebuild_high = UINT32_MAX;
+		meta->disk_rebuild = UINT32_MAX;
 		fake = 1;
 	}
 	if (meta != NULL) {
@@ -464,6 +504,7 @@ static int
 promise_meta_write_spare(struct g_consumer *cp)
 {
 	struct promise_raid_conf *meta;
+	off_t tmp;
 	int error;
 
 	meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -473,9 +514,11 @@ promise_meta_write_spare(struct g_consum
 	meta->disk.flags = PROMISE_F_SPARE | PROMISE_F_ONLINE | PROMISE_F_VALID;
 	meta->disk.number = 0xff;
 	arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
-	meta->disk_sectors = cp->provider->mediasize / cp->provider->sectorsize;
-	meta->disk_sectors -= 131072;
-	meta->rebuild_lba = UINT32_MAX;
+	tmp = cp->provider->mediasize / cp->provider->sectorsize - 131072;
+	meta->disk_sectors_high = tmp >> 32;
+	meta->disk_sectors = (uint32_t)tmp;
+	meta->disk_rebuild_high = UINT32_MAX;
+	meta->disk_rebuild = UINT32_MAX;
 	error = promise_meta_write(cp, &meta, 1);
 	free(meta, M_MD_PROMISE);
 	return (error);
@@ -617,9 +660,8 @@ g_raid_md_promise_start_disk(struct g_ra
 	struct g_raid_md_promise_perdisk *pd;
 	struct g_raid_md_promise_pervolume *pv;
 	struct promise_raid_conf *meta;
-	off_t size;
+	off_t eoff, esize, size;
 	int disk_pos, md_disk_pos, i, resurrection = 0;
-	uint32_t eoff, esize;
 
 	sc = disk->d_softc;
 	pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
@@ -729,8 +771,10 @@ nofit:
 		sd->sd_offset = (off_t)eoff * 512;
 		sd->sd_size = (off_t)esize * 512;
 	} else {
-		sd->sd_offset = (off_t)pd->pd_meta[sdn]->disk_offset * 512;
-		sd->sd_size = (off_t)pd->pd_meta[sdn]->disk_sectors * 512;
+		sd->sd_offset = (((off_t)pd->pd_meta[sdn]->disk_offset_high
+		    << 32) + pd->pd_meta[sdn]->disk_offset) * 512;
+		sd->sd_size = (((off_t)pd->pd_meta[sdn]->disk_sectors_high
+		    << 32) + pd->pd_meta[sdn]->disk_sectors) * 512;
 	}
 
 	if (resurrection) {
@@ -749,7 +793,8 @@ nofit:
 			sd->sd_rebuild_pos = 0;
 		else {
 			sd->sd_rebuild_pos =
-			    (off_t)pd->pd_meta[sdn]->rebuild_lba * 512;
+			    (((off_t)pd->pd_meta[sdn]->disk_rebuild << 32) +
+			     pd->pd_meta[sdn]->disk_rebuild) * 512;
 		}
 	} else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) {
 		/* Rebuilding disk. */
@@ -875,13 +920,15 @@ g_raid_md_promise_start(struct g_raid_vo
 	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 |=
+		vol->v_mediasize +=
 		    ((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
-	vol->v_sectorsize = 512; //ZZZ
+	vol->v_sectorsize = 512 * meta->sector_size;
 	for (i = 0; i < vol->v_disks_count; i++) {
 		sd = &vol->v_subdisks[i];
-		sd->sd_offset = (off_t)meta->disk_offset * 512; //ZZZ
-		sd->sd_size = (off_t)meta->disk_sectors * 512; //ZZZ
+		sd->sd_offset = (((off_t)meta->disk_offset_high << 32) +
+		    meta->disk_offset) * 512;
+		sd->sd_size = (((off_t)meta->disk_sectors_high << 32) +
+		    meta->disk_sectors) * 512;
 	}
 	g_raid_start_volume(vol);
 
@@ -1213,9 +1260,8 @@ g_raid_md_ctl_promise(struct g_raid_md_o
 	const char *nodename, *verb, *volname, *levelname, *diskname;
 	char *tmp;
 	int *nargs, *force;
-	off_t size, sectorsize, strip;
+	off_t esize, offs[PROMISE_MAX_DISKS], size, sectorsize, strip;
 	intmax_t *sizearg, *striparg;
-	uint32_t offs[PROMISE_MAX_DISKS], esize;
 	int numdisks, i, len, level, qual;
 	int error;
 
@@ -1323,13 +1369,6 @@ 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;
-			}
-
 			g_raid_get_disk_info(disk);
 
 			/* Reserve some space for metadata. */
@@ -1394,10 +1433,6 @@ g_raid_md_ctl_promise(struct g_raid_md_o
 			gctl_error(req, "Size too small.");
 			return (-13);
 		}
-		if (size > 0xffffffffllu * sectorsize) {
-			gctl_error(req, "Size too big.");
-			return (-14);
-		}
 
 		/* We have all we need, create things: volume, ... */
 		pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -1629,14 +1664,6 @@ g_raid_md_ctl_promise(struct g_raid_md_o
 			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);
@@ -1733,9 +1760,9 @@ g_raid_md_write_promise(struct g_raid_md
 		    vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
 			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->total_sectors = vol->v_mediasize / 512;
+		meta->total_sectors_high = (vol->v_mediasize / 512) >> 32;
+		meta->sector_size = vol->v_sectorsize / 512;
 		meta->cylinders = meta->total_sectors / (255 * 63) - 1;
 		meta->heads = 254;
 		meta->sectors = 63;
@@ -1828,15 +1855,24 @@ g_raid_md_write_promise(struct g_raid_md
 			pd->pd_meta[j] = promise_meta_copy(meta);
 			pd->pd_meta[j]->disk = meta->disks[pos];
 			pd->pd_meta[j]->disk.number = pos;
+			pd->pd_meta[j]->disk_offset_high =
+			    (sd->sd_offset / 512) >> 32;
 			pd->pd_meta[j]->disk_offset = sd->sd_offset / 512;
+			pd->pd_meta[j]->disk_sectors_high =
+			    (sd->sd_size / 512) >> 32;
 			pd->pd_meta[j]->disk_sectors = sd->sd_size / 512;
 			if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) {
-				pd->pd_meta[j]->rebuild_lba =
+				pd->pd_meta[j]->disk_rebuild_high =
+				    (sd->sd_rebuild_pos / 512) >> 32;
+				pd->pd_meta[j]->disk_rebuild =
 				    sd->sd_rebuild_pos / 512;
-			} else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD)
-				pd->pd_meta[j]->rebuild_lba = 0;
-			else
-				pd->pd_meta[j]->rebuild_lba = UINT32_MAX;
+			} else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) {
+				pd->pd_meta[j]->disk_rebuild_high = 0;
+				pd->pd_meta[j]->disk_rebuild = 0;
+			} else {
+				pd->pd_meta[j]->disk_rebuild_high = UINT32_MAX;
+				pd->pd_meta[j]->disk_rebuild = UINT32_MAX;
+			}
 			pd->pd_updated = 1;
 		}
 	}


More information about the svn-src-head mailing list