Blame SOURCES/imsm-use-rounded-size-for-metadata-initialization.patch

dd3a91
commit b53bfba6119d3f6f56eb9e10e5a59da6901af159
dd3a91
Author: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
dd3a91
Date:   Thu Mar 30 16:25:41 2017 +0200
dd3a91
dd3a91
    imsm: use rounded size for metadata initialization
dd3a91
    
dd3a91
    Array size is rounded to the nearest MB, however number of data stripes
dd3a91
    and blocks per disk are calculated using size passed by the user. If
dd3a91
    given size is not aligned, there is a mismatch. It's not possible to
dd3a91
    assemble raid0 migrated to raid5 since raid5 arrays use number of data
dd3a91
    stripes to calculate array size.
dd3a91
    
dd3a91
    Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
dd3a91
    Signed-off-by: Jes Sorensen <Jes.Sorensen@gmail.com>
dd3a91
dd3a91
diff --git a/super-intel.c b/super-intel.c
dd3a91
index 785488a..84dfe2b 100644
dd3a91
--- a/super-intel.c
dd3a91
+++ b/super-intel.c
dd3a91
@@ -264,6 +264,8 @@ struct bbm_log {
dd3a91
 static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
dd3a91
 #endif
dd3a91
 
dd3a91
+#define BLOCKS_PER_KB	(1024/512)
dd3a91
+
dd3a91
 #define RAID_DISK_RESERVED_BLOCKS_IMSM_HI 2209
dd3a91
 
dd3a91
 #define GEN_MIGR_AREA_SIZE 2048 /* General Migration Copy Area size in blocks */
dd3a91
@@ -1324,6 +1326,19 @@ static int is_journal(struct imsm_disk *disk)
dd3a91
 	return (disk->status & JOURNAL_DISK) == JOURNAL_DISK;
dd3a91
 }
dd3a91
 
dd3a91
+/* round array size down to closest MB and ensure it splits evenly
dd3a91
+ * between members
dd3a91
+ */
dd3a91
+static unsigned long long round_size_to_mb(unsigned long long size, unsigned int
dd3a91
+					   disk_count)
dd3a91
+{
dd3a91
+	size /= disk_count;
dd3a91
+	size = (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
dd3a91
+	size *= disk_count;
dd3a91
+
dd3a91
+	return size;
dd3a91
+}
dd3a91
+
dd3a91
 /* try to determine how much space is reserved for metadata from
dd3a91
  * the last get_extents() entry on the smallest active disk,
dd3a91
  * otherwise fallback to the default
dd3a91
@@ -3330,11 +3345,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
dd3a91
 			if (used_disks > 0) {
dd3a91
 				array_blocks = blocks_per_member(map) *
dd3a91
 					used_disks;
dd3a91
-				/* round array size down to closest MB
dd3a91
-				 */
dd3a91
-				info->custom_array_size = (array_blocks
dd3a91
-						>> SECT_PER_MB_SHIFT)
dd3a91
-						<< SECT_PER_MB_SHIFT;
dd3a91
+				info->custom_array_size =
dd3a91
+					round_size_to_mb(array_blocks,
dd3a91
+							 used_disks);
dd3a91
+
dd3a91
 			}
dd3a91
 		}
dd3a91
 		case MIGR_VERIFY:
dd3a91
@@ -5241,6 +5255,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
dd3a91
 	unsigned long long array_blocks;
dd3a91
 	size_t size_old, size_new;
dd3a91
 	unsigned long long num_data_stripes;
dd3a91
+	unsigned int data_disks;
dd3a91
+	unsigned long long size_per_member;
dd3a91
 
dd3a91
 	if (super->orom && mpb->num_raid_devs >= super->orom->vpa) {
dd3a91
 		pr_err("This imsm-container already has the maximum of %d volumes\n", super->orom->vpa);
dd3a91
@@ -5317,9 +5333,11 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
dd3a91
 	strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
dd3a91
 	array_blocks = calc_array_size(info->level, info->raid_disks,
dd3a91
 					       info->layout, info->chunk_size,
dd3a91
-					       s->size * 2);
dd3a91
-	/* round array size down to closest MB */
dd3a91
-	array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
dd3a91
+					       s->size * BLOCKS_PER_KB);
dd3a91
+	data_disks = get_data_disks(info->level, info->layout,
dd3a91
+				    info->raid_disks);
dd3a91
+	array_blocks = round_size_to_mb(array_blocks, data_disks);
dd3a91
+	size_per_member = array_blocks / data_disks;
dd3a91
 
dd3a91
 	dev->size_low = __cpu_to_le32((__u32) array_blocks);
dd3a91
 	dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32));
dd3a91
@@ -5331,7 +5349,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
dd3a91
 	vol->curr_migr_unit = 0;
dd3a91
 	map = get_imsm_map(dev, MAP_0);
dd3a91
 	set_pba_of_lba0(map, super->create_offset);
dd3a91
-	set_blocks_per_member(map, info_to_blocks_per_member(info, s->size));
dd3a91
+	set_blocks_per_member(map, info_to_blocks_per_member(info,
dd3a91
+							     size_per_member /
dd3a91
+							     BLOCKS_PER_KB));
dd3a91
 	map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
dd3a91
 	map->failed_disk_num = ~0;
dd3a91
 	if (info->level > 0)
dd3a91
@@ -5359,7 +5379,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
dd3a91
 		map->num_domains = 1;
dd3a91
 
dd3a91
 	/* info->size is only int so use the 'size' parameter instead */
dd3a91
-	num_data_stripes = (s->size * 2) / info_to_blocks_per_strip(info);
dd3a91
+	num_data_stripes = size_per_member / info_to_blocks_per_strip(info);
dd3a91
 	num_data_stripes /= map->num_domains;
dd3a91
 	set_num_data_stripes(map, num_data_stripes);
dd3a91
 
dd3a91
@@ -7981,9 +8001,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev,
dd3a91
 		array_blocks = new_size;
dd3a91
 	}
dd3a91
 
dd3a91
-	/* round array size down to closest MB
dd3a91
-	 */
dd3a91
-	array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
dd3a91
+	array_blocks = round_size_to_mb(array_blocks, used_disks);
dd3a91
 	dev->size_low = __cpu_to_le32((__u32)array_blocks);
dd3a91
 	dev->size_high = __cpu_to_le32((__u32)(array_blocks >> 32));
dd3a91
 
dd3a91
@@ -8096,11 +8114,9 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
dd3a91
 					array_blocks =
dd3a91
 						blocks_per_member(map) *
dd3a91
 						used_disks;
dd3a91
-					/* round array size down to closest MB
dd3a91
-					 */
dd3a91
-					array_blocks = (array_blocks
dd3a91
-							>> SECT_PER_MB_SHIFT)
dd3a91
-						<< SECT_PER_MB_SHIFT;
dd3a91
+					array_blocks =
dd3a91
+						round_size_to_mb(array_blocks,
dd3a91
+								 used_disks);
dd3a91
 					a->info.custom_array_size = array_blocks;
dd3a91
 					/* encourage manager to update array
dd3a91
 					 * size