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>