Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Jan 2013 23:00:41 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r245398 - head/sys/geom/raid
Message-ID:  <201301132300.r0DN0fJe028342@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Jan 13 23:00:40 2013
New Revision: 245398
URL: http://svnweb.freebsd.org/changeset/base/245398

Log:
   - Add checks for Intel metadata version and attributes. Ignore disks with
  unsupported metadata types like Intel Smart Response to not corrupt them.
   - Improve setting of these things during metadata writing to protect from
  incapable BIOS'es and other implementations.

Modified:
  head/sys/geom/raid/md_intel.c

Modified: head/sys/geom/raid/md_intel.c
==============================================================================
--- head/sys/geom/raid/md_intel.c	Sun Jan 13 22:46:06 2013	(r245397)
+++ head/sys/geom/raid/md_intel.c	Sun Jan 13 23:00:40 2013	(r245398)
@@ -165,6 +165,11 @@ struct intel_raid_conf {
 #define INTEL_ATTR_RAID1E	0x00000008
 #define INTEL_ATTR_RAID5	0x00000010
 #define INTEL_ATTR_RAIDCNG	0x00000020
+#define INTEL_ATTR_EXT_STRIP	0x00000040
+#define INTEL_ATTR_NVM_CACHE	0x02000000
+#define INTEL_ATTR_2TB_DISK	0x04000000
+#define INTEL_ATTR_BBM		0x08000000
+#define INTEL_ATTR_NVM_CACHE2	0x10000000
 #define INTEL_ATTR_2TB		0x20000000
 #define INTEL_ATTR_PM		0x40000000
 #define INTEL_ATTR_CHECKSUM	0x80000000
@@ -182,6 +187,11 @@ struct intel_raid_conf {
 	/* Here goes total_volumes of struct intel_raid_vol. */
 } __packed;
 
+#define INTEL_ATTR_SUPPORTED	( INTEL_ATTR_RAID0 | INTEL_ATTR_RAID1 |	\
+    INTEL_ATTR_RAID10 | INTEL_ATTR_RAID1E | INTEL_ATTR_RAID5 |		\
+    INTEL_ATTR_RAIDCNG | INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK |	\
+    INTEL_ATTR_2TB | INTEL_ATTR_PM | INTEL_ATTR_CHECKSUM )
+
 #define INTEL_MAX_MD_SIZE(ndisks)				\
     (sizeof(struct intel_raid_conf) +				\
      sizeof(struct intel_raid_disk) * (ndisks - 1) +		\
@@ -554,6 +564,21 @@ badsize:
 
 	g_raid_md_intel_print(meta);
 
+	if (strncmp(meta->version, INTEL_VERSION_1300, 6) > 0) {
+		G_RAID_DEBUG(1, "Intel unsupported version: '%.6s'",
+		    meta->version);
+		free(meta, M_MD_INTEL);
+		return (NULL);
+	}
+
+	if (strncmp(meta->version, INTEL_VERSION_1300, 6) >= 0 &&
+	    (meta->attributes & ~INTEL_ATTR_SUPPORTED) != 0) {
+		G_RAID_DEBUG(1, "Intel unsupported attributes: 0x%08x",
+		    meta->attributes & ~INTEL_ATTR_SUPPORTED);
+		free(meta, M_MD_INTEL);
+		return (NULL);
+	}
+
 	/* Validate disk indexes. */
 	for (i = 0; i < meta->total_volumes; i++) {
 		mvol = intel_get_volume(meta, i);
@@ -2268,6 +2293,8 @@ g_raid_md_write_intel(struct g_raid_md_o
 		if (pd->pd_disk_pos < 0)
 			continue;
 		meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta;
+		if (pd->pd_disk_meta.sectors_hi != 0)
+			meta->attributes |= INTEL_ATTR_2TB_DISK;
 	}
 
 	/* Fill volumes and maps. */
@@ -2297,12 +2324,16 @@ g_raid_md_write_intel(struct g_raid_md_o
 			meta->attributes |= INTEL_ATTR_RAID1;
 		else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
 			meta->attributes |= INTEL_ATTR_RAID5;
-		else
+		else if ((vol->v_disks_count & 1) == 0)
 			meta->attributes |= INTEL_ATTR_RAID10;
+		else
+			meta->attributes |= INTEL_ATTR_RAID1E;
+		if (pv->pv_cng)
+			meta->attributes |= INTEL_ATTR_RAIDCNG;
+		if (vol->v_strip_size > 131072)
+			meta->attributes |= INTEL_ATTR_EXT_STRIP;
 
-		if (meta->attributes & INTEL_ATTR_2TB)
-			cv = INTEL_VERSION_1300;
-		else if (pv->pv_cng)
+		if (pv->pv_cng)
 			cv = INTEL_VERSION_1206;
 		else if (vol->v_disks_count > 4)
 			cv = INTEL_VERSION_1204;
@@ -2310,8 +2341,6 @@ g_raid_md_write_intel(struct g_raid_md_o
 			cv = INTEL_VERSION_1202;
 		else if (vol->v_disks_count > 2)
 			cv = INTEL_VERSION_1201;
-		else if (vi > 0)
-			cv = INTEL_VERSION_1200;
 		else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
 			cv = INTEL_VERSION_1100;
 		else
@@ -2321,6 +2350,8 @@ g_raid_md_write_intel(struct g_raid_md_o
 
 		strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
 		mvol->total_sectors = vol->v_mediasize / sectorsize;
+		mvol->state = (INTEL_ST_READ_COALESCING |
+		    INTEL_ST_WRITE_COALESCING);
 		if (pv->pv_cng) {
 			mvol->state |= INTEL_ST_CLONE_N_GO;
 			if (pv->pv_cng_man_sync)
@@ -2437,7 +2468,10 @@ g_raid_md_write_intel(struct g_raid_md_o
 		vi++;
 	}
 	meta->total_volumes = vi;
-	if (strcmp(version, INTEL_VERSION_1300) != 0)
+	if (vi > 1 || meta->attributes &
+	     (INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | INTEL_ATTR_2TB))
+		version = INTEL_VERSION_1300;
+	if (strcmp(version, INTEL_VERSION_1300) < 0)
 		meta->attributes &= INTEL_ATTR_CHECKSUM;
 	memcpy(&meta->version[0], version, sizeof(INTEL_VERSION_1000) - 1);
 



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