dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

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

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