diff --git a/SOURCES/0001-Fix-some-building-errors.patch b/SOURCES/0001-Fix-some-building-errors.patch
deleted file mode 100644
index 16cf5cf..0000000
--- a/SOURCES/0001-Fix-some-building-errors.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 83b3de7795d2a421eb6ae4ab97656a250bb898ea Mon Sep 17 00:00:00 2001
-From: Xiao Ni <xni@redhat.com>
-Date: Fri, 23 Apr 2021 14:01:30 +0800
-Subject: [PATCH 1/2] Fix some building errors
-
-There are some building errors if treating warning as errors.
-Fix them in this patch.
-
-Signed-off-by: Xiao Ni <xni@redhat.com>
-Signed-off-by: Jes Sorensen <jsorensen@fb.com>
----
- super-intel.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/super-intel.c b/super-intel.c
-index be0313d..5469912 100644
---- a/super-intel.c
-+++ b/super-intel.c
-@@ -3192,7 +3192,7 @@ static int imsm_create_metadata_checkpoint_update(
- 	}
- 	(*u)->type = update_general_migration_checkpoint;
- 	(*u)->curr_migr_unit = current_migr_unit(super->migr_rec);
--	dprintf("prepared for %llu\n", (*u)->curr_migr_unit);
-+	dprintf("prepared for %llu\n", (unsigned long long)(*u)->curr_migr_unit);
- 
- 	return update_memory_size;
- }
-@@ -11127,7 +11127,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
- 			skipped_disks++;
- 			continue;
- 		}
--		if (read(dl_disk->fd, buf, unit_len) != unit_len) {
-+		if (read(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
- 			pr_err("Cannot read copy area block: %s\n",
- 			       strerror(errno));
- 			skipped_disks++;
-@@ -11139,7 +11139,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
- 			skipped_disks++;
- 			continue;
- 		}
--		if (write(dl_disk->fd, buf, unit_len) != unit_len) {
-+		if (write(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
- 			pr_err("Cannot restore block: %s\n",
- 			       strerror(errno));
- 			skipped_disks++;
--- 
-2.7.5
-
diff --git a/SOURCES/0001-imsm-change-wrong-size-verification.patch b/SOURCES/0001-imsm-change-wrong-size-verification.patch
new file mode 100644
index 0000000..e1731cb
--- /dev/null
+++ b/SOURCES/0001-imsm-change-wrong-size-verification.patch
@@ -0,0 +1,39 @@
+From ff904202a4a6232e0f0dfea31a7c4a34ab08f76e Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Wed, 21 Apr 2021 16:50:08 +0200
+Subject: [PATCH 01/15] imsm: change wrong size verification
+
+Expectation that size is always rounded is incorrect.
+Just confirm that size is smaller to be certain that update is safe.
+
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super-intel.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/super-intel.c b/super-intel.c
+index 876e077..be0313d 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -11823,12 +11823,12 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index)
+ 		if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR)
+ 			continue;
+ 
+-		/* There is a difference, verify that imsm_dev_size is
+-		 * rounded correctly and push update.
++		/* There is a difference, confirm that imsm_dev_size is
++		 * smaller and push update.
+ 		 */
+-		if (d_size != round_size_to_mb(d_size, disc_count)) {
+-			dprintf("imsm: Size of volume %d is not rounded correctly\n",
+-				 i);
++		if (d_size > calc_size) {
++			pr_err("imsm: dev size of subarray %d is incorrect\n",
++				i);
+ 			goto exit;
+ 		}
+ 		memset(&geo, 0, sizeof(struct geo_params));
+-- 
+2.7.5
+
diff --git a/SOURCES/0002-Fix-some-building-errors.patch b/SOURCES/0002-Fix-some-building-errors.patch
new file mode 100644
index 0000000..cff64c9
--- /dev/null
+++ b/SOURCES/0002-Fix-some-building-errors.patch
@@ -0,0 +1,48 @@
+From 83b3de7795d2a421eb6ae4ab97656a250bb898ea Mon Sep 17 00:00:00 2001
+From: Xiao Ni <xni@redhat.com>
+Date: Fri, 23 Apr 2021 14:01:30 +0800
+Subject: [PATCH 02/15] Fix some building errors
+
+There are some building errors if treating warning as errors.
+Fix them in this patch.
+
+Signed-off-by: Xiao Ni <xni@redhat.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super-intel.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/super-intel.c b/super-intel.c
+index be0313d..5469912 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -3192,7 +3192,7 @@ static int imsm_create_metadata_checkpoint_update(
+ 	}
+ 	(*u)->type = update_general_migration_checkpoint;
+ 	(*u)->curr_migr_unit = current_migr_unit(super->migr_rec);
+-	dprintf("prepared for %llu\n", (*u)->curr_migr_unit);
++	dprintf("prepared for %llu\n", (unsigned long long)(*u)->curr_migr_unit);
+ 
+ 	return update_memory_size;
+ }
+@@ -11127,7 +11127,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
+ 			skipped_disks++;
+ 			continue;
+ 		}
+-		if (read(dl_disk->fd, buf, unit_len) != unit_len) {
++		if (read(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
+ 			pr_err("Cannot read copy area block: %s\n",
+ 			       strerror(errno));
+ 			skipped_disks++;
+@@ -11139,7 +11139,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
+ 			skipped_disks++;
+ 			continue;
+ 		}
+-		if (write(dl_disk->fd, buf, unit_len) != unit_len) {
++		if (write(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
+ 			pr_err("Cannot restore block: %s\n",
+ 			       strerror(errno));
+ 			skipped_disks++;
+-- 
+2.7.5
+
diff --git a/SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch b/SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch
deleted file mode 100644
index 0a052e0..0000000
--- a/SOURCES/0002-Prevent-user-from-using-stop-with-ambiguous-args.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 0530e2e0d8c9ecb5171e70bc48e1a6566f317378 Mon Sep 17 00:00:00 2001
-From: Norbert Szulc <norbert.szulc@intel.com>
-Date: Wed, 5 May 2021 13:01:02 +0200
-Subject: [PATCH 2/2] Prevent user from using --stop with ambiguous args
-
-When both --scan and device name is passed to --stop action,
-then is executed only for given device. Scan is ignored.
-
-Block the operation when both --scan and device name are passed.
-
-Signed-off-by: Norbert Szulc <norbert.szulc@intel.com>
-Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
-Signed-off-by: Jes Sorensen <jsorensen@fb.com>
----
- mdadm.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/mdadm.c b/mdadm.c
-index 9a4317d..dcc26ba 100644
---- a/mdadm.c
-+++ b/mdadm.c
-@@ -2041,6 +2041,11 @@ static int misc_list(struct mddev_dev *devlist,
- 				rv |= Manage_run(dv->devname, mdfd, c);
- 				break;
- 			case 'S':
-+				if (c->scan) {
-+					pr_err("--stop not meaningful with both a --scan assembly and a device name.\n");
-+					rv |= 1;
-+					break;
-+				}
- 				rv |= Manage_stop(dv->devname, mdfd, c->verbose, 0);
- 				break;
- 			case 'o':
--- 
-2.7.5
-
diff --git a/SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch b/SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch
new file mode 100644
index 0000000..02e3a9b
--- /dev/null
+++ b/SOURCES/0003-Prevent-user-from-using-stop-with-ambiguous-args.patch
@@ -0,0 +1,36 @@
+From 0530e2e0d8c9ecb5171e70bc48e1a6566f317378 Mon Sep 17 00:00:00 2001
+From: Norbert Szulc <norbert.szulc@intel.com>
+Date: Wed, 5 May 2021 13:01:02 +0200
+Subject: [PATCH 03/15] Prevent user from using --stop with ambiguous args
+
+When both --scan and device name is passed to --stop action,
+then is executed only for given device. Scan is ignored.
+
+Block the operation when both --scan and device name are passed.
+
+Signed-off-by: Norbert Szulc <norbert.szulc@intel.com>
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ mdadm.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/mdadm.c b/mdadm.c
+index 9a4317d..dcc26ba 100644
+--- a/mdadm.c
++++ b/mdadm.c
+@@ -2041,6 +2041,11 @@ static int misc_list(struct mddev_dev *devlist,
+ 				rv |= Manage_run(dv->devname, mdfd, c);
+ 				break;
+ 			case 'S':
++				if (c->scan) {
++					pr_err("--stop not meaningful with both a --scan assembly and a device name.\n");
++					rv |= 1;
++					break;
++				}
+ 				rv |= Manage_stop(dv->devname, mdfd, c->verbose, 0);
+ 				break;
+ 			case 'o':
+-- 
+2.7.5
+
diff --git a/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch b/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch
new file mode 100644
index 0000000..565826c
--- /dev/null
+++ b/SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch
@@ -0,0 +1,327 @@
+From 7c798f870900f6f4d4647dd3c88318524d7ccee4 Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Mon, 17 May 2021 16:39:00 +0200
+Subject: [PATCH 04/15] imsm: add generic method to resolve "device" links
+
+Each virtual device is linked with parent by "device". This patch adds
+possibility to get previous device in sysfs tree.
+
+Depending on device type, there is a different amount of virutal
+layers. The best we can do is allow to directly specify how many
+"device" links need to be resolved. This approach also allows to get
+previous virtual device, which may contain some attributes.
+
+Simplify fd2devname, this function doesn't require new functionality and
+shall use generic fd2kname.
+
+For nvme drives represented via nvme-subystem when path to block
+device if requested, then return it without translation.
+
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ platform-intel.c | 75 ++++++++++++++++++++++++++++++++++++++------------------
+ platform-intel.h |  4 +--
+ super-intel.c    | 63 ++++++++++++++++++-----------------------------
+ 3 files changed, 77 insertions(+), 65 deletions(-)
+
+diff --git a/platform-intel.c b/platform-intel.c
+index 2da152f..2ed63ed 100644
+--- a/platform-intel.c
++++ b/platform-intel.c
+@@ -712,28 +712,61 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path)
+ 	return rp;
+ }
+ 
+-char *devt_to_devpath(dev_t dev)
++/* Description: Return part or whole realpath for the dev
++ * Parameters:
++ *	dev - the device to be quered
++ *	dev_level - level of "/device" entries. It allows to caller to access
++ *		    virtual or physical devices which are on "path" to quered
++ *		    one.
++ *	buf - optional, must be PATH_MAX size. If set, then will be used.
++ */
++char *devt_to_devpath(dev_t dev, int dev_level, char *buf)
+ {
+-	char device[46];
+-	char *rp;
+-	char *buf;
++	char device[PATH_MAX];
++	char *hw_path;
++	int i;
++	unsigned long device_free_len = sizeof(device) - 1;
++	char dev_str[] = "/device";
++	unsigned long dev_str_len = strlen(dev_str);
++
++	snprintf(device, sizeof(device), "/sys/dev/block/%d:%d", major(dev),
++		 minor(dev));
++
++	/* If caller wants block device, return path to it even if it is exposed
++	 * via virtual layer.
++	 */
++	if (dev_level == 0)
++		return realpath(device, buf);
+ 
+-	sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev));
++	device_free_len -= strlen(device);
++	for (i = 0; i < dev_level; i++) {
++		if (device_free_len < dev_str_len)
++			return NULL;
+ 
+-	rp = realpath(device, NULL);
+-	if (!rp)
+-		return NULL;
++		strncat(device, dev_str, device_free_len);
+ 
+-	buf = get_nvme_multipath_dev_hw_path(rp);
+-	if (buf) {
+-		free(rp);
+-		return buf;
++		/* Resolve nvme-subsystem abstraction if needed
++		 */
++		device_free_len -= dev_str_len;
++		if (i == 0) {
++			char rp[PATH_MAX];
++
++			if (!realpath(device, rp))
++				return NULL;
++			hw_path = get_nvme_multipath_dev_hw_path(rp);
++			if (hw_path) {
++				strcpy(device, hw_path);
++				device_free_len = sizeof(device) -
++						  strlen(device) - 1;
++				free(hw_path);
++			}
++		}
+ 	}
+ 
+-	return rp;
++	return realpath(device, buf);
+ }
+ 
+-char *diskfd_to_devpath(int fd)
++char *diskfd_to_devpath(int fd, int dev_level, char *buf)
+ {
+ 	/* return the device path for a disk, return NULL on error or fd
+ 	 * refers to a partition
+@@ -745,7 +778,7 @@ char *diskfd_to_devpath(int fd)
+ 	if (!S_ISBLK(st.st_mode))
+ 		return NULL;
+ 
+-	return devt_to_devpath(st.st_rdev);
++	return devt_to_devpath(st.st_rdev, dev_level, buf);
+ }
+ 
+ int path_attached_to_hba(const char *disk_path, const char *hba_path)
+@@ -770,7 +803,7 @@ int path_attached_to_hba(const char *disk_path, const char *hba_path)
+ 
+ int devt_attached_to_hba(dev_t dev, const char *hba_path)
+ {
+-	char *disk_path = devt_to_devpath(dev);
++	char *disk_path = devt_to_devpath(dev, 1, NULL);
+ 	int rc = path_attached_to_hba(disk_path, hba_path);
+ 
+ 	if (disk_path)
+@@ -781,7 +814,7 @@ int devt_attached_to_hba(dev_t dev, const char *hba_path)
+ 
+ int disk_attached_to_hba(int fd, const char *hba_path)
+ {
+-	char *disk_path = diskfd_to_devpath(fd);
++	char *disk_path = diskfd_to_devpath(fd, 1, NULL);
+ 	int rc = path_attached_to_hba(disk_path, hba_path);
+ 
+ 	if (disk_path)
+@@ -862,15 +895,9 @@ int imsm_is_nvme_supported(int disk_fd, int verbose)
+  */
+ int is_multipath_nvme(int disk_fd)
+ {
+-	char path_buf[PATH_MAX];
+ 	char ns_path[PATH_MAX];
+-	char *kname = fd2kname(disk_fd);
+-
+-	if (!kname)
+-		return 0;
+-	sprintf(path_buf, "/sys/block/%s", kname);
+ 
+-	if (!realpath(path_buf, ns_path))
++	if (!diskfd_to_devpath(disk_fd, 0, ns_path))
+ 		return 0;
+ 
+ 	if (strncmp(ns_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) == 0)
+diff --git a/platform-intel.h b/platform-intel.h
+index 8396a0f..f93add5 100644
+--- a/platform-intel.h
++++ b/platform-intel.h
+@@ -237,7 +237,7 @@ static inline char *guid_str(char *buf, struct efi_guid guid)
+ }
+ 
+ char *get_nvme_multipath_dev_hw_path(const char *dev_path);
+-char *diskfd_to_devpath(int fd);
++char *diskfd_to_devpath(int fd, int dev_level, char *buf);
+ __u16 devpath_to_vendor(const char *dev_path);
+ struct sys_dev *find_driver_devices(const char *bus, const char *driver);
+ struct sys_dev *find_intel_devices(void);
+@@ -245,7 +245,7 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba);
+ const struct imsm_orom *find_imsm_orom(void);
+ int disk_attached_to_hba(int fd, const char *hba_path);
+ int devt_attached_to_hba(dev_t dev, const char *hba_path);
+-char *devt_to_devpath(dev_t dev);
++char *devt_to_devpath(dev_t dev, int dev_level, char *buf);
+ int path_attached_to_hba(const char *disk_path, const char *hba_path);
+ const char *get_sys_dev_type(enum sys_dev_type);
+ const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
+diff --git a/super-intel.c b/super-intel.c
+index 5469912..cff8550 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -694,7 +694,7 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
+ 	if (fd < 0)
+ 		disk_path  = (char *) devname;
+ 	else
+-		disk_path = diskfd_to_devpath(fd);
++		disk_path = diskfd_to_devpath(fd, 1, NULL);
+ 
+ 	if (!disk_path)
+ 		return 0;
+@@ -2253,7 +2253,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 
+ 		if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
+ 			continue;
+-		path = devt_to_devpath(makedev(major, minor));
++		path = devt_to_devpath(makedev(major, minor), 1, NULL);
+ 		if (!path)
+ 			continue;
+ 		if (!path_attached_to_hba(path, hba_path)) {
+@@ -2407,7 +2407,7 @@ static int print_nvme_info(struct sys_dev *hba)
+ 				continue;
+ 			}
+ 
+-			device_path = diskfd_to_devpath(fd);
++			device_path = diskfd_to_devpath(fd, 1, NULL);
+ 			if (!device_path) {
+ 				close(fd);
+ 				continue;
+@@ -4015,28 +4015,13 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
+ 
+ static void fd2devname(int fd, char *name)
+ {
+-	struct stat st;
+-	char path[256];
+-	char dname[PATH_MAX];
+ 	char *nm;
+-	int rv;
+-
+-	name[0] = '\0';
+-	if (fstat(fd, &st) != 0)
+-		return;
+-	sprintf(path, "/sys/dev/block/%d:%d",
+-		major(st.st_rdev), minor(st.st_rdev));
+ 
+-	rv = readlink(path, dname, sizeof(dname)-1);
+-	if (rv <= 0)
++	nm = fd2kname(fd);
++	if (!nm)
+ 		return;
+ 
+-	dname[rv] = '\0';
+-	nm = strrchr(dname, '/');
+-	if (nm) {
+-		nm++;
+-		snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
+-	}
++	snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
+ }
+ 
+ static int nvme_get_serial(int fd, void *buf, size_t buf_len)
+@@ -5941,29 +5926,23 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 		free(dd);
+ 		abort();
+ 	}
++
+ 	if (super->hba && ((super->hba->type == SYS_DEV_NVME) ||
+ 	   (super->hba->type == SYS_DEV_VMD))) {
+ 		int i;
+-		char *devpath = diskfd_to_devpath(fd);
+-		char controller_path[PATH_MAX];
+-		char *controller_name;
++		char cntrl_path[PATH_MAX];
++		char *cntrl_name;
++		char pci_dev_path[PATH_MAX];
+ 
+-		if (!devpath) {
+-			pr_err("failed to get devpath, aborting\n");
++		if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
++		    !diskfd_to_devpath(fd, 1, cntrl_path)) {
++			pr_err("failed to get dev_path, aborting\n");
+ 			if (dd->devname)
+ 				free(dd->devname);
+ 			free(dd);
+ 			return 1;
+ 		}
+ 
+-		snprintf(controller_path, PATH_MAX-1, "%s/device", devpath);
+-
+-		controller_name = basename(devpath);
+-		if (is_multipath_nvme(fd))
+-			pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", controller_name);
+-
+-		free(devpath);
+-
+ 		if (!imsm_is_nvme_supported(dd->fd, 1)) {
+ 			if (dd->devname)
+ 				free(dd->devname);
+@@ -5971,7 +5950,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 			return 1;
+ 		}
+ 
+-		if (devpath_to_vendor(controller_path) == 0x8086) {
++		cntrl_name = basename(cntrl_path);
++		if (is_multipath_nvme(fd))
++			pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n",
++			       cntrl_name);
++
++		if (devpath_to_vendor(pci_dev_path) == 0x8086) {
+ 			/*
+ 			 * If Intel's NVMe drive has serial ended with
+ 			 * "-A","-B","-1" or "-2" it means that this is "x8"
+@@ -6985,7 +6969,7 @@ get_devices(const char *hba_path)
+ 		char *path = NULL;
+ 		if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
+ 			continue;
+-		path = devt_to_devpath(makedev(major, minor));
++		path = devt_to_devpath(makedev(major, minor), 1, NULL);
+ 		if (!path)
+ 			continue;
+ 		if (!path_attached_to_hba(path, hba_path)) {
+@@ -10648,7 +10632,7 @@ int validate_container_imsm(struct mdinfo *info)
+ 	struct sys_dev *hba = NULL;
+ 	struct sys_dev *intel_devices = find_intel_devices();
+ 	char *dev_path = devt_to_devpath(makedev(info->disk.major,
+-									info->disk.minor));
++						 info->disk.minor), 1, NULL);
+ 
+ 	for (idev = intel_devices; idev; idev = idev->next) {
+ 		if (dev_path && strstr(dev_path, idev->path)) {
+@@ -10669,7 +10653,8 @@ int validate_container_imsm(struct mdinfo *info)
+ 	struct mdinfo *dev;
+ 
+ 	for (dev = info->next; dev; dev = dev->next) {
+-		dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor));
++		dev_path = devt_to_devpath(makedev(dev->disk.major,
++						   dev->disk.minor), 1, NULL);
+ 
+ 		struct sys_dev *hba2 = NULL;
+ 		for (idev = intel_devices; idev; idev = idev->next) {
+@@ -11181,7 +11166,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
+ 		struct sys_dev* hba;
+ 		char *path;
+ 
+-		path = devt_to_devpath(st.st_rdev);
++		path = devt_to_devpath(st.st_rdev, 1, NULL);
+ 		if (path == NULL)
+ 			return "unknown";
+ 		hba = find_disk_attached_hba(-1, path);
+-- 
+2.7.5
+
diff --git a/SOURCES/0005-imsm-add-devpath_to_char-method.patch b/SOURCES/0005-imsm-add-devpath_to_char-method.patch
new file mode 100644
index 0000000..53a5ecc
--- /dev/null
+++ b/SOURCES/0005-imsm-add-devpath_to_char-method.patch
@@ -0,0 +1,157 @@
+From fcebeb77b18842876295b1a0dbc22d173a709434 Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Mon, 17 May 2021 16:39:01 +0200
+Subject: [PATCH 05/15] imsm: add devpath_to_char method
+
+Add method for reading sysfs attributes and propagate it across IMSM code.
+
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ platform-intel.c | 23 +++++++++++++++++++++++
+ platform-intel.h |  2 ++
+ super-intel.c    | 33 +++++++++++++++------------------
+ 3 files changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/platform-intel.c b/platform-intel.c
+index 2ed63ed..9401784 100644
+--- a/platform-intel.c
++++ b/platform-intel.c
+@@ -239,6 +239,29 @@ __u16 devpath_to_vendor(const char *dev_path)
+ 	return id;
+ }
+ 
++/* Description: Read text value of dev_path/entry field
++ * Parameters:
++ *	dev_path - sysfs path to the device
++ *	entry - entry to be read
++ *	buf - buffer for read value
++ *	len - size of buf
++ *	verbose - error logging level
++ */
++int devpath_to_char(const char *dev_path, const char *entry, char *buf, int len,
++		    int verbose)
++{
++	char path[PATH_MAX];
++
++	snprintf(path, sizeof(path), "%s/%s", dev_path, entry);
++	if (load_sys(path, buf, len)) {
++		if (verbose)
++			pr_err("Cannot read %s, aborting\n", path);
++		return 1;
++	}
++
++	return 0;
++}
++
+ struct sys_dev *find_intel_devices(void)
+ {
+ 	struct sys_dev *ahci, *isci, *nvme;
+diff --git a/platform-intel.h b/platform-intel.h
+index f93add5..45d98cd 100644
+--- a/platform-intel.h
++++ b/platform-intel.h
+@@ -238,6 +238,8 @@ static inline char *guid_str(char *buf, struct efi_guid guid)
+ 
+ char *get_nvme_multipath_dev_hw_path(const char *dev_path);
+ char *diskfd_to_devpath(int fd, int dev_level, char *buf);
++int devpath_to_char(const char *dev_path, const char *entry, char *buf,
++		    int len, int verbose);
+ __u16 devpath_to_vendor(const char *dev_path);
+ struct sys_dev *find_driver_devices(const char *bus, const char *driver);
+ struct sys_dev *find_intel_devices(void);
+diff --git a/super-intel.c b/super-intel.c
+index cff8550..c352f50 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -2246,7 +2246,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 		char vendor[64];
+ 		char buf[1024];
+ 		int major, minor;
+-		char *device;
++		char device[PATH_MAX];
+ 		char *c;
+ 		int port;
+ 		int type;
+@@ -2262,20 +2262,15 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 			continue;
+ 		}
+ 
+-		/* retrieve the scsi device type */
+-		if (asprintf(&device, "/sys/dev/block/%d:%d/device/xxxxxxx", major, minor) < 0) {
++		/* retrieve the scsi device */
++		if (!devt_to_devpath(makedev(major, minor), 1, device)) {
+ 			if (verbose > 0)
+-				pr_err("failed to allocate 'device'\n");
++				pr_err("failed to get device\n");
+ 			err = 2;
+ 			break;
+ 		}
+-		sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor);
+-		if (load_sys(device, buf, sizeof(buf)) != 0) {
+-			if (verbose > 0)
+-				pr_err("failed to read device type for %s\n",
+-					path);
++		if (devpath_to_char(device, "type", buf, sizeof(buf), 0)) {
+ 			err = 2;
+-			free(device);
+ 			break;
+ 		}
+ 		type = strtoul(buf, NULL, 10);
+@@ -2284,8 +2279,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 		if (!(type == 0 || type == 7 || type == 14)) {
+ 			vendor[0] = '\0';
+ 			model[0] = '\0';
+-			sprintf(device, "/sys/dev/block/%d:%d/device/vendor", major, minor);
+-			if (load_sys(device, buf, sizeof(buf)) == 0) {
++
++			if (devpath_to_char(device, "vendor", buf,
++					    sizeof(buf), 0) == 0) {
+ 				strncpy(vendor, buf, sizeof(vendor));
+ 				vendor[sizeof(vendor) - 1] = '\0';
+ 				c = (char *) &vendor[sizeof(vendor) - 1];
+@@ -2293,8 +2289,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 					*c-- = '\0';
+ 
+ 			}
+-			sprintf(device, "/sys/dev/block/%d:%d/device/model", major, minor);
+-			if (load_sys(device, buf, sizeof(buf)) == 0) {
++
++			if (devpath_to_char(device, "model", buf,
++					    sizeof(buf), 0) == 0) {
+ 				strncpy(model, buf, sizeof(model));
+ 				model[sizeof(model) - 1] = '\0';
+ 				c = (char *) &model[sizeof(model) - 1];
+@@ -2319,7 +2316,6 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 				}
+ 		} else
+ 			buf[0] = '\0';
+-		free(device);
+ 
+ 		/* chop device path to 'host%d' and calculate the port number */
+ 		c = strchr(&path[hba_len], '/');
+@@ -4026,7 +4022,7 @@ static void fd2devname(int fd, char *name)
+ 
+ static int nvme_get_serial(int fd, void *buf, size_t buf_len)
+ {
+-	char path[60];
++	char path[PATH_MAX];
+ 	char *name = fd2kname(fd);
+ 
+ 	if (!name)
+@@ -4035,9 +4031,10 @@ static int nvme_get_serial(int fd, void *buf, size_t buf_len)
+ 	if (strncmp(name, "nvme", 4) != 0)
+ 		return 1;
+ 
+-	snprintf(path, sizeof(path) - 1, "/sys/block/%s/device/serial", name);
++	if (!diskfd_to_devpath(fd, 1, path))
++		return 1;
+ 
+-	return load_sys(path, buf, buf_len);
++	return devpath_to_char(path, "serial", buf, buf_len, 0);
+ }
+ 
+ extern int scsi_get_serial(int fd, void *buf, size_t buf_len);
+-- 
+2.7.5
+
diff --git a/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch b/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch
new file mode 100644
index 0000000..7fecc91
--- /dev/null
+++ b/SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch
@@ -0,0 +1,329 @@
+From 8662f92d71f1f88589061272606b8b673d31de05 Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Mon, 17 May 2021 16:39:02 +0200
+Subject: [PATCH 06/15] imsm: Limit support to the lowest namespace
+
+First namespace existence is not quaranted by NVMe specification.
+Instead first the smallest one shall be chosen.
+
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ platform-intel.c |  81 ++++++++++++++++++++++++++----------
+ platform-intel.h |   2 +-
+ super-intel.c    | 124 +++++++++++++++++++++++++++----------------------------
+ 3 files changed, 123 insertions(+), 84 deletions(-)
+
+diff --git a/platform-intel.c b/platform-intel.c
+index 9401784..5a8729e 100644
+--- a/platform-intel.c
++++ b/platform-intel.c
+@@ -879,36 +879,75 @@ char *vmd_domain_to_controller(struct sys_dev *hba, char *buf)
+ 	closedir(dir);
+ 	return NULL;
+ }
+-/* Verify that NVMe drive is supported by IMSM
++
++/* Scan over all controller's namespaces and compare nsid value to verify if
++ * current one is supported. The routine doesn't check IMSM capabilities for
++ * namespace. Only one nvme namespace is supported by IMSM.
++ * Paramteres:
++ *	fd - open descriptor to the nvme namespace
++ *	verbose - error logging level
+  * Returns:
+- *	0 - not supported
+- *	1 - supported
++ *	1 - if namespace is supported
++ *	0 - otherwise
+  */
+-int imsm_is_nvme_supported(int disk_fd, int verbose)
++int imsm_is_nvme_namespace_supported(int fd, int verbose)
+ {
+-	char nsid_path[PATH_MAX];
+-	char buf[PATH_MAX];
+-	struct stat stb;
++	DIR *dir = NULL;
++	struct dirent *ent;
++	char cntrl_path[PATH_MAX];
++	char ns_path[PATH_MAX];
++	unsigned long long lowest_nsid = ULLONG_MAX;
++	unsigned long long this_nsid;
++	int rv = 0;
+ 
+-	if (disk_fd < 0)
+-		return 0;
+ 
+-	if (fstat(disk_fd, &stb))
+-		return 0;
++	if (!diskfd_to_devpath(fd, 1, cntrl_path) ||
++	    !diskfd_to_devpath(fd, 0, ns_path)) {
++		if (verbose)
++			pr_err("Cannot get device paths\n");
++		goto abort;
++	}
+ 
+-	snprintf(nsid_path, PATH_MAX-1, "/sys/dev/block/%d:%d/nsid",
+-		 major(stb.st_rdev), minor(stb.st_rdev));
+ 
+-	if (load_sys(nsid_path, buf, sizeof(buf))) {
+-		pr_err("Cannot read %s, rejecting drive\n", nsid_path);
+-		return 0;
+-	}
+-	if (strtoll(buf, NULL, 10) != 1) {
++	if (devpath_to_ll(ns_path, "nsid", &this_nsid)) {
+ 		if (verbose)
+-			pr_err("Only first namespace is supported by IMSM, aborting\n");
+-		return 0;
++			pr_err("Cannot read nsid value for %s",
++			       basename(ns_path));
++		goto abort;
+ 	}
+-	return 1;
++
++	dir = opendir(cntrl_path);
++	if (!dir)
++		goto abort;
++
++	/* The lowest nvme namespace is supported */
++	for (ent = readdir(dir); ent; ent = readdir(dir)) {
++		unsigned long long curr_nsid;
++		char curr_ns_path[PATH_MAX + 256];
++
++		if (!strstr(ent->d_name, "nvme"))
++			continue;
++
++		snprintf(curr_ns_path, sizeof(curr_ns_path), "%s/%s",
++			 cntrl_path, ent->d_name);
++
++		if (devpath_to_ll(curr_ns_path, "nsid", &curr_nsid))
++			goto abort;
++
++		if (lowest_nsid > curr_nsid)
++			lowest_nsid = curr_nsid;
++	}
++
++	if (this_nsid == lowest_nsid)
++		rv = 1;
++	else if (verbose)
++		pr_err("IMSM is supported on the lowest NVMe namespace\n");
++
++abort:
++	if (dir)
++		closedir(dir);
++
++	return rv;
+ }
+ 
+ /* Verify if multipath is supported by NVMe controller
+diff --git a/platform-intel.h b/platform-intel.h
+index 45d98cd..6238d23 100644
+--- a/platform-intel.h
++++ b/platform-intel.h
+@@ -254,6 +254,6 @@ const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
+ const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
+ struct sys_dev *device_by_id(__u16 device_id);
+ struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path);
+-int imsm_is_nvme_supported(int disk_fd, int verbose);
+ int is_multipath_nvme(int disk_fd);
++int imsm_is_nvme_namespace_supported(int disk_fd, int verbose);
+ char *vmd_domain_to_controller(struct sys_dev *hba, char *buf);
+diff --git a/super-intel.c b/super-intel.c
+index c352f50..fdcefb6 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -2381,49 +2381,51 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
+ 
+ static int print_nvme_info(struct sys_dev *hba)
+ {
+-	char buf[1024];
+-	char *device_path;
+ 	struct dirent *ent;
+ 	DIR *dir;
+-	int fd;
+ 
+ 	dir = opendir("/sys/block/");
+ 	if (!dir)
+ 		return 1;
+ 
+ 	for (ent = readdir(dir); ent; ent = readdir(dir)) {
+-		if (strstr(ent->d_name, "nvme")) {
+-			fd = open_dev(ent->d_name);
+-			if (fd < 0)
+-				continue;
++		char ns_path[PATH_MAX];
++		char cntrl_path[PATH_MAX];
++		char buf[PATH_MAX];
++		int fd = -1;
+ 
+-			if (!imsm_is_nvme_supported(fd, 0)) {
+-				if (fd >= 0)
+-					close(fd);
+-				continue;
+-			}
++		if (!strstr(ent->d_name, "nvme"))
++			goto skip;
+ 
+-			device_path = diskfd_to_devpath(fd, 1, NULL);
+-			if (!device_path) {
+-				close(fd);
+-				continue;
+-			}
++		fd = open_dev(ent->d_name);
++		if (fd < 0)
++			goto skip;
+ 
+-			if (path_attached_to_hba(device_path, hba->path)) {
+-				fd2devname(fd, buf);
+-				if (hba->type == SYS_DEV_VMD)
+-					printf(" NVMe under VMD : %s", buf);
+-				else if (hba->type == SYS_DEV_NVME)
+-					printf("    NVMe Device : %s", buf);
+-				if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
+-						      sizeof(buf)))
+-					printf(" (%s)\n", buf);
+-				else
+-					printf("()\n");
+-			}
+-			free(device_path);
++		if (!diskfd_to_devpath(fd, 0, ns_path) ||
++		    !diskfd_to_devpath(fd, 1, cntrl_path))
++			goto skip;
++
++		if (!path_attached_to_hba(cntrl_path, hba->path))
++			goto skip;
++
++		if (!imsm_is_nvme_namespace_supported(fd, 0))
++			goto skip;
++
++		fd2devname(fd, buf);
++		if (hba->type == SYS_DEV_VMD)
++			printf(" NVMe under VMD : %s", buf);
++		else if (hba->type == SYS_DEV_NVME)
++			printf("    NVMe Device : %s", buf);
++
++		if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
++				      sizeof(buf)))
++			printf(" (%s)\n", buf);
++		else
++			printf("()\n");
++
++skip:
++		if (fd > -1)
+ 			close(fd);
+-		}
+ 	}
+ 
+ 	closedir(dir);
+@@ -5933,14 +5935,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 
+ 		if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
+ 		    !diskfd_to_devpath(fd, 1, cntrl_path)) {
+-			pr_err("failed to get dev_path, aborting\n");
+-			if (dd->devname)
+-				free(dd->devname);
+-			free(dd);
+-			return 1;
+-		}
++			pr_err("failed to get dev paths, aborting\n");
+ 
+-		if (!imsm_is_nvme_supported(dd->fd, 1)) {
+ 			if (dd->devname)
+ 				free(dd->devname);
+ 			free(dd);
+@@ -6665,7 +6661,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
+ {
+ 	int fd;
+ 	unsigned long long ldsize;
+-	struct intel_super *super;
++	struct intel_super *super = NULL;
+ 	int rv = 0;
+ 
+ 	if (level != LEVEL_CONTAINER)
+@@ -6680,24 +6676,18 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
+ 				dev, strerror(errno));
+ 		return 0;
+ 	}
+-	if (!get_dev_size(fd, dev, &ldsize)) {
+-		close(fd);
+-		return 0;
+-	}
++	if (!get_dev_size(fd, dev, &ldsize))
++		goto exit;
+ 
+ 	/* capabilities retrieve could be possible
+ 	 * note that there is no fd for the disks in array.
+ 	 */
+ 	super = alloc_super();
+-	if (!super) {
+-		close(fd);
+-		return 0;
+-	}
+-	if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
+-		close(fd);
+-		free_imsm(super);
+-		return 0;
+-	}
++	if (!super)
++		goto exit;
++
++	if (!get_dev_sector_size(fd, NULL, &super->sector_size))
++		goto exit;
+ 
+ 	rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
+ 	if (rv != 0) {
+@@ -6708,32 +6698,42 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
+ 			fd, str, super->orom, rv, raiddisks);
+ #endif
+ 		/* no orom/efi or non-intel hba of the disk */
+-		close(fd);
+-		free_imsm(super);
+-		return 0;
++		rv = 0;
++		goto exit;
+ 	}
+-	close(fd);
+ 	if (super->orom) {
+ 		if (raiddisks > super->orom->tds) {
+ 			if (verbose)
+ 				pr_err("%d exceeds maximum number of platform supported disks: %d\n",
+ 					raiddisks, super->orom->tds);
+-			free_imsm(super);
+-			return 0;
++			goto exit;
+ 		}
+ 		if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
+ 		    (ldsize >> 9) >> 32 > 0) {
+ 			if (verbose)
+ 				pr_err("%s exceeds maximum platform supported size\n", dev);
+-			free_imsm(super);
+-			return 0;
++			goto exit;
++		}
++
++		if (super->hba->type == SYS_DEV_VMD ||
++		    super->hba->type == SYS_DEV_NVME) {
++			if (!imsm_is_nvme_namespace_supported(fd, 1)) {
++				if (verbose)
++					pr_err("NVMe namespace %s is not supported by IMSM\n",
++						basename(dev));
++				goto exit;
++			}
+ 		}
+ 	}
+ 
+ 	*freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
+-	free_imsm(super);
++	rv = 1;
++exit:
++	if (super)
++		free_imsm(super);
++	close(fd);
+ 
+-	return 1;
++	return rv;
+ }
+ 
+ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
+-- 
+2.7.5
+
diff --git a/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch b/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch
new file mode 100644
index 0000000..ea25ff7
--- /dev/null
+++ b/SOURCES/0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch
@@ -0,0 +1,107 @@
+From 1f5d54a06df01ca3032ca2d29159584cab7d7509 Mon Sep 17 00:00:00 2001
+From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Date: Mon, 17 May 2021 16:39:03 +0200
+Subject: [PATCH 07/15] Manage: Call validate_geometry when adding drive to
+ external container
+
+When adding drive to container call validate_geometry to verify whether
+drive is supported and can be addded to container.
+
+Remove unused parameters from validate_geometry_imsm_container().
+There is no need to pass them.
+Don't calculate freesize if it is not mandatory. Make it configurable.
+
+Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ Manage.c      |  7 +++++++
+ super-ddf.c   |  9 +++++----
+ super-intel.c | 19 +++++++------------
+ 3 files changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/Manage.c b/Manage.c
+index 0a5f09b..f789e0c 100644
+--- a/Manage.c
++++ b/Manage.c
+@@ -992,6 +992,13 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
+ 			return -1;
+ 		}
+ 
++		/* Check if metadata handler is able to accept the drive */
++		if (!tst->ss->validate_geometry(tst, LEVEL_CONTAINER, 0, 1, NULL,
++		    0, 0, dv->devname, NULL, 0, 1)) {
++			close(container_fd);
++			return -1;
++		}
++
+ 		Kill(dv->devname, NULL, 0, -1, 0);
+ 		dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
+ 		if (tst->ss->add_to_super(tst, &disc, dfd,
+diff --git a/super-ddf.c b/super-ddf.c
+index 2314762..80a40f8 100644
+--- a/super-ddf.c
++++ b/super-ddf.c
+@@ -3475,10 +3475,11 @@ validate_geometry_ddf_container(struct supertype *st,
+ 		return 0;
+ 	}
+ 	close(fd);
+-
+-	*freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS);
+-	if (*freesize == 0)
+-		return 0;
++	if (freesize) {
++		*freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS);
++		if (*freesize == 0)
++			return 0;
++	}
+ 
+ 	return 1;
+ }
+diff --git a/super-intel.c b/super-intel.c
+index fdcefb6..fe45d93 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -6652,8 +6652,7 @@ static int store_super_imsm(struct supertype *st, int fd)
+ }
+ 
+ static int validate_geometry_imsm_container(struct supertype *st, int level,
+-					    int layout, int raiddisks, int chunk,
+-					    unsigned long long size,
++					    int raiddisks,
+ 					    unsigned long long data_offset,
+ 					    char *dev,
+ 					    unsigned long long *freesize,
+@@ -6725,8 +6724,8 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
+ 			}
+ 		}
+ 	}
+-
+-	*freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
++	if (freesize)
++		*freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
+ 	rv = 1;
+ exit:
+ 	if (super)
+@@ -7586,15 +7585,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
+ 	 * if given unused devices create a container
+ 	 * if given given devices in a container create a member volume
+ 	 */
+-	if (level == LEVEL_CONTAINER) {
++	if (level == LEVEL_CONTAINER)
+ 		/* Must be a fresh device to add to a container */
+-		return validate_geometry_imsm_container(st, level, layout,
+-							raiddisks,
+-							*chunk,
+-							size, data_offset,
+-							dev, freesize,
+-							verbose);
+-	}
++		return validate_geometry_imsm_container(st, level, raiddisks,
++							data_offset, dev,
++							freesize, verbose);
+ 
+ 	/*
+ 	 * Size is given in sectors.
+-- 
+2.7.5
+
diff --git a/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch b/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch
new file mode 100644
index 0000000..25080d2
--- /dev/null
+++ b/SOURCES/0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch
@@ -0,0 +1,31 @@
+From f421731c7e1de6608f8fafb551d199ff5f1d6b97 Mon Sep 17 00:00:00 2001
+From: Xiao Ni <xni@redhat.com>
+Date: Wed, 2 Jun 2021 09:17:19 +0800
+Subject: [PATCH 08/15] mdadm/super1: It needs to specify int32 for
+ bitmap_offset
+
+For super1.0 bitmap offset is -16. So it needs to use int type for bitmap offset.
+
+Fixes: 1fe2e1007310 (mdadm/bitmap: locate bitmap calcuate bitmap position wrongly)
+Signed-off-by: Xiao Ni <xni@redhat.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super1.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/super1.c b/super1.c
+index c05e623..a12a5bc 100644
+--- a/super1.c
++++ b/super1.c
+@@ -2631,7 +2631,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num)
+ 	else
+ 		ret = -1;
+ 
+-	offset = __le64_to_cpu(sb->super_offset) + __le32_to_cpu(sb->bitmap_offset);
++	offset = __le64_to_cpu(sb->super_offset) + (int32_t)__le32_to_cpu(sb->bitmap_offset);
+ 	if (node_num) {
+ 		bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ 		bm_sectors_per_node = calc_bitmap_size(bms, 4096) >> 9;
+-- 
+2.7.5
+
diff --git a/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch b/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch
new file mode 100644
index 0000000..e356085
--- /dev/null
+++ b/SOURCES/0009-Use-dev_open-in-validate-geometry-container.patch
@@ -0,0 +1,48 @@
+From dca80fcd5d15c37ecbd82763e6fe4aee8c077bf9 Mon Sep 17 00:00:00 2001
+From: Blazej Kucman <blazej.kucman@intel.com>
+Date: Tue, 15 Jun 2021 16:45:39 +0200
+Subject: [PATCH 09/15] Use dev_open in validate geometry container
+
+Fix regression caused by the patch 1f5d54a06
+("Manage: Call validate_geometry when adding drive to external container")
+- mdmonitor passes to Manage() routine dev name as min:mjr.
+The open() used in validate_geometry_container()
+in both ddf and imsm requires path, replace open calls by dev_open,
+which allows to use dev path and min:mjr.
+
+Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super-ddf.c   | 2 +-
+ super-intel.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/super-ddf.c b/super-ddf.c
+index 80a40f8..dc8e512 100644
+--- a/super-ddf.c
++++ b/super-ddf.c
+@@ -3463,7 +3463,7 @@ validate_geometry_ddf_container(struct supertype *st,
+ 	if (!dev)
+ 		return 1;
+ 
+-	fd = open(dev, O_RDONLY|O_EXCL, 0);
++	fd = dev_open(dev, O_RDONLY|O_EXCL);
+ 	if (fd < 0) {
+ 		if (verbose)
+ 			pr_err("ddf: Cannot open %s: %s\n",
+diff --git a/super-intel.c b/super-intel.c
+index fe45d93..5356ca5 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -6668,7 +6668,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
+ 	if (!dev)
+ 		return 1;
+ 
+-	fd = open(dev, O_RDONLY|O_EXCL, 0);
++	fd = dev_open(dev, O_RDONLY|O_EXCL);
+ 	if (fd < 0) {
+ 		if (verbose > 0)
+ 			pr_err("imsm: Cannot open %s: %s\n",
+-- 
+2.7.5
+
diff --git a/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch b/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch
new file mode 100644
index 0000000..8972e90
--- /dev/null
+++ b/SOURCES/0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch
@@ -0,0 +1,30 @@
+From 7d8935cbb0fdb2b776b736bffc00323a04e5f788 Mon Sep 17 00:00:00 2001
+From: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Date: Fri, 18 Jun 2021 15:53:30 +0200
+Subject: [PATCH 10/15] imsm: correct offset for 4k disks in --examine output
+
+"Sector Offset" field in Examine output was always printed in 512
+byte sectors. Update it to support 4096 sector size.
+
+Signed-off-by: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super-intel.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/super-intel.c b/super-intel.c
+index 5356ca5..88636e0 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -1663,7 +1663,7 @@ static void print_imsm_dev(struct intel_super *super,
+ 		   (unsigned long long)sz * 512 / super->sector_size,
+ 	       human_size(sz * 512));
+ 	printf("  Sector Offset : %llu\n",
+-		pba_of_lba0(map));
++		pba_of_lba0(map) * 512 / super->sector_size);
+ 	printf("    Num Stripes : %llu\n",
+ 		num_data_stripes(map));
+ 	printf("     Chunk Size : %u KiB",
+-- 
+2.7.5
+
diff --git a/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch b/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch
new file mode 100644
index 0000000..695113a
--- /dev/null
+++ b/SOURCES/0011-Remove-Spare-drives-line-from-details-for-external-m.patch
@@ -0,0 +1,35 @@
+From 8d69bf147ec77447c5d45c17bed7dc017808cc44 Mon Sep 17 00:00:00 2001
+From: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Date: Fri, 18 Jun 2021 15:53:31 +0200
+Subject: [PATCH 11/15] Remove Spare drives line from details for external
+ metadata
+
+Arrays with external metadata do not have spare disks directly
+assigned to volumes; spare disks belong to containers and are
+moved to arrays when the array is degraded/reshaping.
+Thus, the display of zero spare disks in volume details is
+incorrect and can be confusing.
+
+Signed-off-by: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ Detail.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Detail.c b/Detail.c
+index cd26fb0..ad56344 100644
+--- a/Detail.c
++++ b/Detail.c
+@@ -548,7 +548,8 @@ int Detail(char *dev, struct context *c)
+ 			       array.working_disks);
+ 		if (array.raid_disks) {
+ 			printf("    Failed Devices : %d\n", array.failed_disks);
+-			printf("     Spare Devices : %d\n", array.spare_disks);
++			if (!external)
++				printf("     Spare Devices : %d\n", array.spare_disks);
+ 		}
+ 		printf("\n");
+ 		if (array.level == 5) {
+-- 
+2.7.5
+
diff --git a/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch b/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch
new file mode 100644
index 0000000..1d1c128
--- /dev/null
+++ b/SOURCES/0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch
@@ -0,0 +1,173 @@
+From 601ffa784f03cea843b9b732e561ffea0b8c036f Mon Sep 17 00:00:00 2001
+From: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Date: Fri, 18 Jun 2021 15:53:32 +0200
+Subject: [PATCH 12/15] Don't associate spares with other arrays during RAID
+ Examine
+
+Spares in imsm belong to containers, not volumes, and must go into
+a separate container when assembling the RAID.
+Remove association spares with other arrays and make Examine print
+separate containers for spares.
+Auto assemble without config file already works like this. So make
+creating a config file and assembling from it consistent with auto
+assemble.
+With this change, mdadm -Es will add this line to output if spares
+are found:
+ARRAY metadata=imsm UUID=00000000:00000000:00000000:00000000
+
+Signed-off-by: Oleksandr Shchirskyi <oleksandr.shchirskyi@linux.intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ Examine.c     |  2 +-
+ super-intel.c | 74 +++++++++++++++--------------------------------------------
+ 2 files changed, 20 insertions(+), 56 deletions(-)
+
+diff --git a/Examine.c b/Examine.c
+index 4381cd5..9574a3c 100644
+--- a/Examine.c
++++ b/Examine.c
+@@ -166,7 +166,7 @@ int Examine(struct mddev_dev *devlist,
+ 			int newline = 0;
+ 
+ 			ap->st->ss->brief_examine_super(ap->st, c->verbose > 0);
+-			if (ap->spares)
++			if (ap->spares && !ap->st->ss->external)
+ 				newline += printf("   spares=%d", ap->spares);
+ 			if (c->verbose > 0) {
+ 				newline += printf("   devices");
+diff --git a/super-intel.c b/super-intel.c
+index 88636e0..aeea137 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -2123,12 +2123,6 @@ static void brief_examine_super_imsm(struct supertype *st, int verbose)
+ 	/* We just write a generic IMSM ARRAY entry */
+ 	struct mdinfo info;
+ 	char nbuf[64];
+-	struct intel_super *super = st->sb;
+-
+-	if (!super->anchor->num_raid_devs) {
+-		printf("ARRAY metadata=imsm\n");
+-		return;
+-	}
+ 
+ 	getinfo_super_imsm(st, &info, NULL);
+ 	fname_from_uuid(st, &info, nbuf, ':');
+@@ -3911,12 +3905,9 @@ static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src)
+ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
+ 			      int verbose)
+ {
+-	/*
+-	 * return:
++	/*  return:
+ 	 *  0 same, or first was empty, and second was copied
+-	 *  1 second had wrong number
+-	 *  2 wrong uuid
+-	 *  3 wrong other info
++	 *  1 sb are different
+ 	 */
+ 	struct intel_super *first = st->sb;
+ 	struct intel_super *sec = tst->sb;
+@@ -3926,31 +3917,30 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
+ 		tst->sb = NULL;
+ 		return 0;
+ 	}
++
+ 	/* in platform dependent environment test if the disks
+ 	 * use the same Intel hba
+-	 * If not on Intel hba at all, allow anything.
++	 * if not on Intel hba at all, allow anything.
++	 * doesn't check HBAs if num_raid_devs is not set, as it means
++	 * it is a free floating spare, and all spares regardless of HBA type
++	 * will fall into separate container during the assembly
+ 	 */
+-	if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) {
++	if (first->hba && sec->hba && first->anchor->num_raid_devs != 0) {
+ 		if (first->hba->type != sec->hba->type) {
+ 			if (verbose)
+ 				pr_err("HBAs of devices do not match %s != %s\n",
+ 				       get_sys_dev_type(first->hba->type),
+ 				       get_sys_dev_type(sec->hba->type));
+-			return 3;
++			return 1;
+ 		}
+-
+ 		if (first->orom != sec->orom) {
+ 			if (verbose)
+ 				pr_err("HBAs of devices do not match %s != %s\n",
+ 				       first->hba->pci_id, sec->hba->pci_id);
+-			return 3;
++			return 1;
+ 		}
+-
+ 	}
+ 
+-	/* if an anchor does not have num_raid_devs set then it is a free
+-	 * floating spare
+-	 */
+ 	if (first->anchor->num_raid_devs > 0 &&
+ 	    sec->anchor->num_raid_devs > 0) {
+ 		/* Determine if these disks might ever have been
+@@ -3962,7 +3952,7 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
+ 
+ 		if (memcmp(first->anchor->sig, sec->anchor->sig,
+ 			   MAX_SIGNATURE_LENGTH) != 0)
+-			return 3;
++			return 1;
+ 
+ 		if (first_family == 0)
+ 			first_family = first->anchor->family_num;
+@@ -3970,43 +3960,17 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
+ 			sec_family = sec->anchor->family_num;
+ 
+ 		if (first_family != sec_family)
+-			return 3;
++			return 1;
+ 
+ 	}
+ 
+-	/* if 'first' is a spare promote it to a populated mpb with sec's
+-	 * family number
+-	 */
+-	if (first->anchor->num_raid_devs == 0 &&
+-	    sec->anchor->num_raid_devs > 0) {
+-		int i;
+-		struct intel_dev *dv;
+-		struct imsm_dev *dev;
+-
+-		/* we need to copy raid device info from sec if an allocation
+-		 * fails here we don't associate the spare
+-		 */
+-		for (i = 0; i < sec->anchor->num_raid_devs; i++) {
+-			dv = xmalloc(sizeof(*dv));
+-			dev = xmalloc(sizeof_imsm_dev(get_imsm_dev(sec, i), 1));
+-			dv->dev = dev;
+-			dv->index = i;
+-			dv->next = first->devlist;
+-			first->devlist = dv;
+-		}
+-		if (i < sec->anchor->num_raid_devs) {
+-			/* allocation failure */
+-			free_devlist(first);
+-			pr_err("imsm: failed to associate spare\n");
+-			return 3;
+-		}
+-		first->anchor->num_raid_devs = sec->anchor->num_raid_devs;
+-		first->anchor->orig_family_num = sec->anchor->orig_family_num;
+-		first->anchor->family_num = sec->anchor->family_num;
+-		memcpy(first->anchor->sig, sec->anchor->sig, MAX_SIGNATURE_LENGTH);
+-		for (i = 0; i < sec->anchor->num_raid_devs; i++)
+-			imsm_copy_dev(get_imsm_dev(first, i), get_imsm_dev(sec, i));
+-	}
++	/* if an anchor does not have num_raid_devs set then it is a free
++	* floating spare. don't assosiate spare with any array, as during assembly
++	* spares shall fall into separate container, from which they can be moved
++	* when necessary
++	*/
++	if (first->anchor->num_raid_devs ^ sec->anchor->num_raid_devs)
++		return 1;
+ 
+ 	return 0;
+ }
+-- 
+2.7.5
+
diff --git a/SOURCES/0013-mdadm-Fix-building-errors.patch b/SOURCES/0013-mdadm-Fix-building-errors.patch
new file mode 100644
index 0000000..b953afd
--- /dev/null
+++ b/SOURCES/0013-mdadm-Fix-building-errors.patch
@@ -0,0 +1,49 @@
+From ccd61ebfd97fde43768497c79e3d361b484b1520 Mon Sep 17 00:00:00 2001
+From: Xiao Ni <xni@redhat.com>
+Date: Tue, 22 Jun 2021 23:15:55 +0800
+Subject: [PATCH 13/15] mdadm: Fix building errors
+
+In util.c, there is a building error:
+'/md/metadata_version' directive writing 20 bytes into a
+region of size between 0 and 255 [-Werror=format-overflow=]
+
+In mapfile.c
+It declares the fouth argument as 'int *' in map_update,
+but in mdadm.h it's previously declared as an array 'int[4]'
+
+Signed-off-by: Xiao Ni <xni@redhat.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ mapfile.c | 2 +-
+ util.c    | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/mapfile.c b/mapfile.c
+index 8d7acb3..6b2207d 100644
+--- a/mapfile.c
++++ b/mapfile.c
+@@ -215,7 +215,7 @@ void map_free(struct map_ent *map)
+ }
+ 
+ int map_update(struct map_ent **mpp, char *devnm, char *metadata,
+-	       int *uuid, char *path)
++	       int uuid[4], char *path)
+ {
+ 	struct map_ent *map, *mp;
+ 	int rv;
+diff --git a/util.c b/util.c
+index 5879694..cdf1da2 100644
+--- a/util.c
++++ b/util.c
+@@ -1543,7 +1543,7 @@ int open_container(int fd)
+ 	/* 'fd' is a block device.  Find out if it is in use
+ 	 * by a container, and return an open fd on that container.
+ 	 */
+-	char path[256];
++	char path[288];
+ 	char *e;
+ 	DIR *dir;
+ 	struct dirent *de;
+-- 
+2.7.5
+
diff --git a/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch b/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch
new file mode 100644
index 0000000..0387a8a
--- /dev/null
+++ b/SOURCES/0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch
@@ -0,0 +1,142 @@
+From 3a85bf0e417d0977136efbade7c7ea269e24bc21 Mon Sep 17 00:00:00 2001
+From: Mateusz Grzonka <mateusz.grzonka@intel.com>
+Date: Mon, 28 Jun 2021 14:15:04 +0200
+Subject: [PATCH 14/15] imsm: Fix possible memory leaks and refactor freeing
+ struct dl
+
+Free memory allocated by structs dl and intel_super.
+Allow __free_imsm_disk to decide if fd has to be closed and propagate it
+across code instead of direct struct dl freeing.
+
+Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ super-intel.c | 39 +++++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 20 deletions(-)
+
+diff --git a/super-intel.c b/super-intel.c
+index aeea137..da37625 100644
+--- a/super-intel.c
++++ b/super-intel.c
+@@ -4499,9 +4499,9 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd
+ 	return err;
+ }
+ 
+-static void __free_imsm_disk(struct dl *d)
++static void __free_imsm_disk(struct dl *d, int close_fd)
+ {
+-	if (d->fd >= 0)
++	if (close_fd && d->fd > -1)
+ 		close(d->fd);
+ 	if (d->devname)
+ 		free(d->devname);
+@@ -4518,17 +4518,17 @@ static void free_imsm_disks(struct intel_super *super)
+ 	while (super->disks) {
+ 		d = super->disks;
+ 		super->disks = d->next;
+-		__free_imsm_disk(d);
++		__free_imsm_disk(d, 1);
+ 	}
+ 	while (super->disk_mgmt_list) {
+ 		d = super->disk_mgmt_list;
+ 		super->disk_mgmt_list = d->next;
+-		__free_imsm_disk(d);
++		__free_imsm_disk(d, 1);
+ 	}
+ 	while (super->missing) {
+ 		d = super->missing;
+ 		super->missing = d->next;
+-		__free_imsm_disk(d);
++		__free_imsm_disk(d, 1);
+ 	}
+ 
+ }
+@@ -5243,10 +5243,13 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
+ 	free_super_imsm(st);
+ 
+ 	super = alloc_super();
+-	if (!get_dev_sector_size(fd, NULL, &super->sector_size))
+-		return 1;
+ 	if (!super)
+ 		return 1;
++
++	if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
++		free_imsm(super);
++		return 1;
++	}
+ 	/* Load hba and capabilities if they exist.
+ 	 * But do not preclude loading metadata in case capabilities or hba are
+ 	 * non-compliant and ignore_hw_compat is set.
+@@ -5884,9 +5887,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 	rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN);
+ 	if (rv) {
+ 		pr_err("failed to retrieve scsi serial, aborting\n");
+-		if (dd->devname)
+-			free(dd->devname);
+-		free(dd);
++		__free_imsm_disk(dd, 0);
+ 		abort();
+ 	}
+ 
+@@ -5900,10 +5901,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 		if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
+ 		    !diskfd_to_devpath(fd, 1, cntrl_path)) {
+ 			pr_err("failed to get dev paths, aborting\n");
+-
+-			if (dd->devname)
+-				free(dd->devname);
+-			free(dd);
++			__free_imsm_disk(dd, 0);
+ 			return 1;
+ 		}
+ 
+@@ -5939,15 +5937,16 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
+ 		    !imsm_orom_has_tpv_support(super->orom)) {
+ 			pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n"
+ 			       "\tPlease refer to Intel(R) RSTe/VROC user guide.\n");
+-			free(dd->devname);
+-			free(dd);
++			__free_imsm_disk(dd, 0);
+ 			return 1;
+ 		}
+ 	}
+ 
+ 	get_dev_size(fd, NULL, &size);
+-	if (!get_dev_sector_size(fd, NULL, &member_sector_size))
++	if (!get_dev_sector_size(fd, NULL, &member_sector_size)) {
++		__free_imsm_disk(dd, 0);
+ 		return 1;
++	}
+ 
+ 	if (super->sector_size == 0) {
+ 		/* this a first device, so sector_size is not set yet */
+@@ -9260,7 +9259,7 @@ static int remove_disk_super(struct intel_super *super, int major, int minor)
+ 			else
+ 				super->disks = dl->next;
+ 			dl->next = NULL;
+-			__free_imsm_disk(dl);
++			__free_imsm_disk(dl, 1);
+ 			dprintf("removed %x:%x\n", major, minor);
+ 			break;
+ 		}
+@@ -9310,7 +9309,7 @@ static int add_remove_disk_update(struct intel_super *super)
+ 				}
+ 			}
+ 			/* release allocate disk structure */
+-			__free_imsm_disk(disk_cfg);
++			__free_imsm_disk(disk_cfg, 1);
+ 		}
+ 	}
+ 	return check_degraded;
+@@ -10511,7 +10510,7 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
+ 		struct dl *dl = *dlp;
+ 
+ 		*dlp = (*dlp)->next;
+-		__free_imsm_disk(dl);
++		__free_imsm_disk(dl, 1);
+ 	}
+ }
+ 
+-- 
+2.7.5
+
diff --git a/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch b/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch
new file mode 100644
index 0000000..22d9628
--- /dev/null
+++ b/SOURCES/0015-Add-error-handling-for-chunk-size-in-RAID1.patch
@@ -0,0 +1,32 @@
+From 5b30a34aa4b5ea7a8202314c1d737ec4a481c127 Mon Sep 17 00:00:00 2001
+From: Mateusz Grzonka <mateusz.grzonka@intel.com>
+Date: Thu, 15 Jul 2021 12:25:23 +0200
+Subject: [PATCH 15/15] Add error handling for chunk size in RAID1
+
+Print error if chunk size is set as it is not supported.
+
+Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
+Signed-off-by: Jes Sorensen <jsorensen@fb.com>
+---
+ Create.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/Create.c b/Create.c
+index 18b5e64..f5d57f8 100644
+--- a/Create.c
++++ b/Create.c
+@@ -254,9 +254,8 @@ int Create(struct supertype *st, char *mddev,
+ 	case LEVEL_MULTIPATH:
+ 	case LEVEL_CONTAINER:
+ 		if (s->chunk) {
+-			s->chunk = 0;
+-			if (c->verbose > 0)
+-				pr_err("chunk size ignored for this level\n");
++			pr_err("specifying chunk size is forbidden for this level\n");
++			return 1;
+ 		}
+ 		break;
+ 	default:
+-- 
+2.7.5
+
diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec
index 285484e..1de075b 100644
--- a/SPECS/mdadm.spec
+++ b/SPECS/mdadm.spec
@@ -2,7 +2,7 @@ Summary:     The mdadm program controls Linux md devices (software RAID arrays)
 Name:        mdadm
 Version:     4.2
 %define subversion rc1
-Release:     rc1_2%{?dist}
+Release:     rc1_3%{?dist}
 Source:      http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}-%{subversion}.tar.xz
 Source1:     mdmonitor.init
 Source2:     raid-check
@@ -15,8 +15,21 @@ Source8:     mdadm_event.conf
 Source9:     mdcheck
 Source10:    mdadm_env.sh
 
-Patch001:    0001-Fix-some-building-errors.patch
-Patch002:    0002-Prevent-user-from-using-stop-with-ambiguous-args.patch
+Patch001:    0001-imsm-change-wrong-size-verification.patch
+Patch002:    0002-Fix-some-building-errors.patch
+Patch003:    0003-Prevent-user-from-using-stop-with-ambiguous-args.patch
+Patch004:    0004-imsm-add-generic-method-to-resolve-device-links.patch
+Patch005:    0005-imsm-add-devpath_to_char-method.patch
+Patch006:    0006-imsm-Limit-support-to-the-lowest-namespace.patch
+Patch007:    0007-Manage-Call-validate_geometry-when-adding-drive-to-e.patch
+Patch008:    0008-mdadm-super1-It-needs-to-specify-int32-for-bitmap_of.patch
+Patch009:    0009-Use-dev_open-in-validate-geometry-container.patch
+Patch010:    0010-imsm-correct-offset-for-4k-disks-in-examine-output.patch
+Patch011:    0011-Remove-Spare-drives-line-from-details-for-external-m.patch
+Patch012:    0012-Don-t-associate-spares-with-other-arrays-during-RAID.patch
+Patch013:    0013-mdadm-Fix-building-errors.patch
+Patch014:    0014-imsm-Fix-possible-memory-leaks-and-refactor-freeing-.patch
+Patch015:    0015-Add-error-handling-for-chunk-size-in-RAID1.patch
 
 # RHEL customization patches
 Patch200:    mdadm-3.3-udev.patch
@@ -49,6 +62,20 @@ file can be used to help with some common tasks.
 
 %patch001 -p1 -b .0001
 %patch002 -p1 -b .0002
+%patch003 -p1 -b .0003
+%patch004 -p1 -b .0004
+%patch005 -p1 -b .0005
+%patch006 -p1 -b .0006
+%patch007 -p1 -b .0007
+%patch008 -p1 -b .0008
+%patch009 -p1 -b .0009
+%patch010 -p1 -b .0010
+%patch011 -p1 -b .0011
+%patch012 -p1 -b .0012
+%patch013 -p1 -b .0013
+%patch014 -p1 -b .0014
+%patch015 -p1 -b .0015
+
 # RHEL customization patches
 %patch200 -p1 -b .udev
 %patch201 -p1 -b .static
@@ -119,6 +146,10 @@ rm -rf %{buildroot}
 /usr/lib/mdadm/mdadm_env.sh
 
 %changelog
+* Tue Jul 20 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1-3
+- Fix super1.0 offset problem and super imsm bugs
+- Resolves rhbz#1966712 and rhbz#1975449
+
 * Thu Jun 10 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1-2
 - Fix udev rule syntax error
 - Resolves rhbz#1945780