--- mdadm.h | 1 + super-intel.c | 4 ++++ util.c | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+) --- mdadm-3.0.3.orig/mdadm.h +++ mdadm-3.0.3/mdadm.h @@ -820,6 +820,7 @@ extern int enough(int level, int raid_di extern int ask(char *mesg); extern unsigned long long get_component_size(int fd); extern void remove_partitions(int fd); +extern int test_partition(int fd); extern unsigned long long calc_array_size(int level, int raid_disks, int layout, int chunksize, unsigned long long devsize); extern int flush_metadata_updates(struct supertype *st); --- mdadm-3.0.3.orig/super-intel.c +++ mdadm-3.0.3/super-intel.c @@ -2582,6 +2582,10 @@ static int load_super_imsm(struct supert return 0; #endif + if (test_partition(fd)) + /* IMSM not allowed on partitions */ + return 1; + free_super_imsm(st); super = alloc_super(0); --- mdadm-3.0.3.orig/util.c +++ mdadm-3.0.3/util.c @@ -168,6 +168,31 @@ void remove_partitions(int fd) #endif } +int test_partition(int fd) +{ + /* Check if fd is a whole-disk or a partition. + * BLKPG will return EINVAL on a partition, and BLKPG_DEL_PARTITION + * will return ENXIO on an invalid partition number. + */ + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + a.op = BLKPG_DEL_PARTITION; + a.data = (void*)&p; + a.datalen = sizeof(p); + a.flags = 0; + memset(a.data, 0, a.datalen); + p.pno = 1<<30; + if (ioctl(fd, BLKPG, &a) == 0) + /* Very unlikely, but not a partition */ + return 0; + if (errno == ENXIO) + /* not a partition */ + return 0; + + return 1; +} + + int enough(int level, int raid_disks, int layout, int clean, char *avail, int avail_disks) {