summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile13
-rw-r--r--platform-intel.h37
-rw-r--r--super-intel.c99
3 files changed, 135 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index afbd712..7f27aa4 100644
--- a/Makefile
+++ b/Makefile
@@ -76,23 +76,28 @@ OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o \
Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \
Incremental.o \
mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \
- restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o
+ restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o \
+ platform-intel.o probe_roms.o
+
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \
Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c \
Incremental.c \
mdopen.c super0.c super1.c super-ddf.c super-intel.c bitmap.c \
- restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c
+ restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c \
+ platform-intel.c probe_roms.c
MON_OBJS = mdmon.o monitor.o managemon.o util.o mdstat.o sysfs.o config.o \
Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \
- super-ddf.o sha1.o crc32.o msg.o Monitor.o bitmap.o
+ super-ddf.o sha1.o crc32.o msg.o Monitor.o bitmap.o \
+ platform-intel.o probe_roms.o
STATICSRC = pwgr.c
STATICOBJS = pwgr.o
ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c \
- super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c
+ super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \
+ platform-intel.c probe_roms.c
ASSEMBLE_AUTO_SRCS := mdopen.c sysfs.c
ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE
ifdef MDASSEMBLE_AUTO
diff --git a/platform-intel.h b/platform-intel.h
index c126482..bbdc9f9 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -17,6 +17,7 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <asm/types.h>
+#include <strings.h>
/* The IMSM OROM Version Table definition */
struct imsm_orom {
@@ -78,6 +79,42 @@ struct imsm_orom {
__u32 reserved2;
} __attribute__((packed));
+static inline int imsm_orom_has_raid0(const struct imsm_orom *orom)
+{
+ return !!(orom->rlc & IMSM_OROM_RLC_RAID0);
+}
+static inline int imsm_orom_has_raid1(const struct imsm_orom *orom)
+{
+ return !!(orom->rlc & IMSM_OROM_RLC_RAID1);
+}
+static inline int imsm_orom_has_raid1e(const struct imsm_orom *orom)
+{
+ return !!(orom->rlc & IMSM_OROM_RLC_RAID1E);
+}
+static inline int imsm_orom_has_raid10(const struct imsm_orom *orom)
+{
+ return !!(orom->rlc & IMSM_OROM_RLC_RAID10);
+}
+static inline int imsm_orom_has_raid5(const struct imsm_orom *orom)
+{
+ return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
+}
+
+/**
+ * imsm_orom_has_chunk - check if the orom supports the given chunk size
+ * @orom: orom pointer from find_imsm_orom
+ * @chunk: chunk size in kibibytes
+ */
+static inline int imsm_orom_has_chunk(const struct imsm_orom *orom, int chunk)
+{
+ int fs = ffs(chunk);
+
+ if (!fs)
+ return 0;
+ fs--; /* bit num to bit index */
+ return !!(orom->sss & (1 << (fs - 1)));
+}
+
struct sys_dev {
char *path;
struct sys_dev *next;
diff --git a/super-intel.c b/super-intel.c
index 7066e8e..abc3206 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -21,6 +21,7 @@
#include "mdadm.h"
#include "mdmon.h"
#include "sha1.h"
+#include "platform-intel.h"
#include <values.h>
#include <scsi/sg.h>
#include <ctype.h>
@@ -230,6 +231,8 @@ struct intel_super {
struct dl *add; /* list of disks to add while mdmon active */
struct dl *missing; /* disks removed while we weren't looking */
struct bbm_log *bbm_log;
+ const char *hba; /* device path of the raid controller for this metadata */
+ const struct imsm_orom *orom; /* platform firmware support */
};
struct extent {
@@ -1505,6 +1508,10 @@ static void __free_imsm(struct intel_super *super, int free_disks)
free(super->dev_tbl[i]);
super->dev_tbl[i] = NULL;
}
+ if (super->hba) {
+ free((void *) super->hba);
+ super->hba = NULL;
+ }
}
static void free_imsm(struct intel_super *super)
@@ -1533,6 +1540,22 @@ static struct intel_super *alloc_super(int creating_imsm)
super->creating_imsm = creating_imsm;
super->current_vol = -1;
super->create_offset = ~((__u32 ) 0);
+ if (!check_env("IMSM_NO_PLATFORM"))
+ super->orom = find_imsm_orom();
+ if (super->orom) {
+ struct sys_dev *list, *ent;
+
+ /* find the first intel ahci controller */
+ list = find_driver_devices("pci", "ahci");
+ for (ent = list; ent; ent = ent->next)
+ if (devpath_to_vendor(ent->path) == 0x8086)
+ break;
+ if (ent) {
+ super->hba = ent->path;
+ ent->path = NULL;
+ }
+ free_sys_dev(&list);
+ }
}
return super;
@@ -1817,9 +1840,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
unsigned long long array_blocks;
size_t size_old, size_new;
- if (mpb->num_raid_devs >= 2) {
+ if (super->orom && mpb->num_raid_devs >= super->orom->vpa) {
fprintf(stderr, Name": This imsm-container already has the "
- "maximum of 2 volumes\n");
+ "maximum of %d volumes\n", super->orom->vpa);
return 0;
}
@@ -2014,6 +2037,16 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
int rv;
struct stat stb;
+ /* if we are on an RAID enabled platform check that the disk is
+ * attached to the raid controller
+ */
+ if (super->hba && !disk_attached_to_hba(fd, super->hba)) {
+ fprintf(stderr,
+ Name ": %s is not attached to the raid controller: %s\n",
+ devname ? : "disk", super->hba);
+ return 1;
+ }
+
if (super->current_vol >= 0)
return add_to_super_imsm_volume(st, dk, fd, devname);
@@ -2282,12 +2315,25 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
{
int fd;
unsigned long long ldsize;
+ const struct imsm_orom *orom;
if (level != LEVEL_CONTAINER)
return 0;
if (!dev)
return 1;
+ if (check_env("IMSM_NO_PLATFORM"))
+ orom = NULL;
+ else
+ orom = find_imsm_orom();
+ if (orom && raiddisks > orom->tds) {
+ if (verbose)
+ fprintf(stderr, Name ": %d exceeds maximum number of"
+ " platform supported disks: %d\n",
+ raiddisks, orom->tds);
+ return 0;
+ }
+
fd = open(dev, O_RDONLY|O_EXCL, 0);
if (fd < 0) {
if (verbose)
@@ -2408,6 +2454,30 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
return maxsize - reserve;
}
+static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
+{
+ if (level < 0 || level == 6 || level == 4)
+ return 0;
+
+ /* if we have an orom prevent invalid raid levels */
+ if (orom)
+ switch (level) {
+ case 0: return imsm_orom_has_raid0(orom);
+ case 1:
+ if (raiddisks > 2)
+ return imsm_orom_has_raid1e(orom);
+ else
+ return imsm_orom_has_raid1(orom);
+ case 10: return imsm_orom_has_raid10(orom);
+ case 5: return imsm_orom_has_raid5(orom);
+ }
+ else
+ return 1; /* not on an Intel RAID platform so anything goes */
+
+ return 0;
+}
+
+#define vprintf(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
/* validate_geometry_imsm_volume - lifted from validate_geometry_ddf_bvd
* FIX ME add ahci details
*/
@@ -2425,19 +2495,28 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
struct extent *e;
int i;
- if (level == LEVEL_CONTAINER)
+ /* We must have the container info already read in. */
+ if (!super)
return 0;
- if (level == 1 && raiddisks > 2) {
- if (verbose)
- fprintf(stderr, Name ": imsm does not support more "
- "than 2 in a raid1 configuration\n");
+ if (!is_raid_level_supported(super->orom, level, raiddisks)) {
+ vprintf(": platform does not support raid level: %d\n", level);
return 0;
}
-
- /* We must have the container info already read in. */
- if (!super)
+ if (super->orom && !imsm_orom_has_chunk(super->orom, chunk)) {
+ vprintf(": platform does not support a chunk size of: %d\n", chunk);
return 0;
+ }
+ if (layout != imsm_level_to_layout(level)) {
+ if (level == 5)
+ vprintf(": imsm raid 5 only supports the left-asymmetric layout\n");
+ else if (level == 10)
+ vprintf(": imsm raid 10 only supports the n2 layout\n");
+ else
+ vprintf(": imsm unknown layout %#x for this raid level %d\n",
+ layout, level);
+ return 0;
+ }
if (!dev) {
/* General test: make sure there is space for