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);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to