Update to 4.3 and add gating test Resolves: RHEL-30530 Signed-off-by: Xiao Ni <xni@redhat.com>
		
			
				
	
	
		
			346 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 191e6ddb1388236c5c54baf5020a87c996be941f Mon Sep 17 00:00:00 2001
 | |
| From: Mateusz Kusiak <mateusz.kusiak@intel.com>
 | |
| Date: Mon, 29 Apr 2024 15:07:16 +0200
 | |
| Subject: [PATCH 55/66] imsm: refactor RAID level handling
 | |
| 
 | |
| Add imsm_level_ops struct for better handling and unifying raid level
 | |
| support. Add helper methods and move "orom_has_raid[...]" methods from
 | |
| header to source file.
 | |
| 
 | |
| RAID 1e is not supported under Linux, remove RAID 1e associated code.
 | |
| 
 | |
| Refactor imsm_analyze_change() and is_raid_level_supported().
 | |
| Remove hardcoded check for 4 drives and make devNumChange a multiplier
 | |
| for RAID 10.
 | |
| 
 | |
| Refactor printing supported raid levels.
 | |
| 
 | |
| Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
 | |
| Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
 | |
| ---
 | |
|  platform-intel.c |  57 ++++++++++++++++++++++++
 | |
|  platform-intel.h |  32 ++++++--------
 | |
|  super-intel.c    | 111 ++++++++++++++++++++++++++++-------------------
 | |
|  3 files changed, 138 insertions(+), 62 deletions(-)
 | |
| 
 | |
| diff --git a/platform-intel.c b/platform-intel.c
 | |
| index ac282bc5..40e8fb82 100644
 | |
| --- a/platform-intel.c
 | |
| +++ b/platform-intel.c
 | |
| @@ -32,6 +32,63 @@
 | |
|  
 | |
|  #define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
 | |
|  
 | |
| +static bool imsm_orom_has_raid0(const struct imsm_orom *orom)
 | |
| +{
 | |
| +	return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID0);
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_has_raid1(const struct imsm_orom *orom)
 | |
| +{
 | |
| +	return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID1);
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_has_raid10(const struct imsm_orom *orom)
 | |
| +{
 | |
| +	return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID10);
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_has_raid5(const struct imsm_orom *orom)
 | |
| +{
 | |
| +	return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID5);
 | |
| +}
 | |
| +
 | |
| +/* IMSM platforms do not define how many disks are allowed for each level,
 | |
| + * but there are some global limitations we need to follow.
 | |
| + */
 | |
| +static bool imsm_orom_support_raid_disks_count_raid0(const int raid_disks)
 | |
| +{
 | |
| +	return true;
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_support_raid_disks_count_raid1(const int raid_disks)
 | |
| +{
 | |
| +	if (raid_disks == 2)
 | |
| +		return true;
 | |
| +	return false;
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
 | |
| +{
 | |
| +	if (raid_disks > 2)
 | |
| +		return true;
 | |
| +	return false;
 | |
| +}
 | |
| +
 | |
| +static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
 | |
| +{
 | |
| +	if (raid_disks == 4)
 | |
| +		return true;
 | |
| +	return false;
 | |
| +}
 | |
| +
 | |
| +struct imsm_level_ops imsm_level_ops[] = {
 | |
| +		{0, imsm_orom_has_raid0, imsm_orom_support_raid_disks_count_raid0, "raid0"},
 | |
| +		{1, imsm_orom_has_raid1, imsm_orom_support_raid_disks_count_raid1, "raid1"},
 | |
| +		{5, imsm_orom_has_raid5, imsm_orom_support_raid_disks_count_raid5, "raid5"},
 | |
| +		{10, imsm_orom_has_raid10, imsm_orom_support_raid_disks_count_raid10, "raid10"},
 | |
| +		{-1, NULL, NULL, NULL}
 | |
| +};
 | |
| +
 | |
|  static int devpath_to_ll(const char *dev_path, const char *entry,
 | |
|  			 unsigned long long *val);
 | |
|  
 | |
| diff --git a/platform-intel.h b/platform-intel.h
 | |
| index 3c2bc595..dcc5aaa7 100644
 | |
| --- a/platform-intel.h
 | |
| +++ b/platform-intel.h
 | |
| @@ -109,25 +109,21 @@ struct imsm_orom {
 | |
|  	#define IMSM_OROM_CAPABILITIES_TPV (1 << 10)
 | |
|  } __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)
 | |
| +/* IMSM metadata requirements for each level */
 | |
| +struct imsm_level_ops {
 | |
| +	int level;
 | |
| +	bool (*is_level_supported)(const struct imsm_orom *);
 | |
| +	bool (*is_raiddisks_count_supported)(const int);
 | |
| +	char *name;
 | |
| +};
 | |
| +
 | |
| +extern struct imsm_level_ops imsm_level_ops[];
 | |
| +
 | |
| +static inline bool imsm_rlc_has_bit(const struct imsm_orom *orom, const unsigned short bit)
 | |
|  {
 | |
| -	return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
 | |
| +	if (orom->rlc & bit)
 | |
| +		return true;
 | |
| +	return false;
 | |
|  }
 | |
|  
 | |
|  /**
 | |
| diff --git a/super-intel.c b/super-intel.c
 | |
| index a7efc8df..da17265d 100644
 | |
| --- a/super-intel.c
 | |
| +++ b/super-intel.c
 | |
| @@ -2681,6 +2681,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
 | |
|  	return host_base;
 | |
|  }
 | |
|  
 | |
| +static void print_imsm_level_capability(const struct imsm_orom *orom)
 | |
| +{
 | |
| +	int idx;
 | |
| +
 | |
| +	for (idx = 0; imsm_level_ops[idx].name; idx++)
 | |
| +		if (imsm_level_ops[idx].is_level_supported(orom))
 | |
| +			printf("%s ", imsm_level_ops[idx].name);
 | |
| +}
 | |
| +
 | |
|  static void print_imsm_capability(const struct imsm_orom *orom)
 | |
|  {
 | |
|  	printf("       Platform : Intel(R) ");
 | |
| @@ -2699,12 +2708,11 @@ static void print_imsm_capability(const struct imsm_orom *orom)
 | |
|  			printf("        Version : %d.%d.%d.%d\n", orom->major_ver,
 | |
|  			       orom->minor_ver, orom->hotfix_ver, orom->build);
 | |
|  	}
 | |
| -	printf("    RAID Levels :%s%s%s%s%s\n",
 | |
| -	       imsm_orom_has_raid0(orom) ? " raid0" : "",
 | |
| -	       imsm_orom_has_raid1(orom) ? " raid1" : "",
 | |
| -	       imsm_orom_has_raid1e(orom) ? " raid1e" : "",
 | |
| -	       imsm_orom_has_raid10(orom) ? " raid10" : "",
 | |
| -	       imsm_orom_has_raid5(orom) ? " raid5" : "");
 | |
| +
 | |
| +	printf("    RAID Levels : ");
 | |
| +	print_imsm_level_capability(orom);
 | |
| +	printf("\n");
 | |
| +
 | |
|  	printf("    Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
 | |
|  	       imsm_orom_has_chunk(orom, 2) ? " 2k" : "",
 | |
|  	       imsm_orom_has_chunk(orom, 4) ? " 4k" : "",
 | |
| @@ -2739,12 +2747,11 @@ static void print_imsm_capability_export(const struct imsm_orom *orom)
 | |
|  	if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
 | |
|  		printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
 | |
|  				orom->hotfix_ver, orom->build);
 | |
| -	printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
 | |
| -			imsm_orom_has_raid0(orom) ? "raid0 " : "",
 | |
| -			imsm_orom_has_raid1(orom) ? "raid1 " : "",
 | |
| -			imsm_orom_has_raid1e(orom) ? "raid1e " : "",
 | |
| -			imsm_orom_has_raid5(orom) ? "raid10 " : "",
 | |
| -			imsm_orom_has_raid10(orom) ? "raid5 " : "");
 | |
| +
 | |
| +	printf("IMSM_SUPPORTED_RAID_LEVELS=");
 | |
| +	print_imsm_level_capability(orom);
 | |
| +	printf("\n");
 | |
| +
 | |
|  	printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
 | |
|  			imsm_orom_has_chunk(orom, 2) ? "2k " : "",
 | |
|  			imsm_orom_has_chunk(orom, 4) ? "4k " : "",
 | |
| @@ -6992,26 +6999,41 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
 | |
|  	return free_size - reservation_size;
 | |
|  }
 | |
|  
 | |
| -static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
 | |
| +/**
 | |
| + * is_raid_level_supported() - check if this count of drives and level is supported by platform.
 | |
| + * @orom: hardware properties, could be NULL.
 | |
| + * @level: requested raid level.
 | |
| + * @raiddisks: requested disk count.
 | |
| + *
 | |
| + * IMSM UEFI/OROM does not provide information about supported count of raid disks
 | |
| + * for particular level. That is why it is hardcoded.
 | |
| + * It is recommended to not allow of usage other levels than supported,
 | |
| + * IMSM code is not tested against different level implementations.
 | |
| + *
 | |
| + * Return: true if supported, false otherwise.
 | |
| + */
 | |
| +static bool is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
 | |
|  {
 | |
| -	if (level < 0 || level == 6 || level == 4)
 | |
| -		return 0;
 | |
| +	int idx;
 | |
|  
 | |
| -	/* 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);
 | |
| -			return imsm_orom_has_raid1(orom) && raiddisks == 2;
 | |
| -		case 10: return imsm_orom_has_raid10(orom) && raiddisks == 4;
 | |
| -		case 5: return imsm_orom_has_raid5(orom) && raiddisks > 2;
 | |
| -		}
 | |
| -	else
 | |
| -		return 1; /* not on an Intel RAID platform so anything goes */
 | |
| +	for (idx = 0; imsm_level_ops[idx].name; idx++) {
 | |
| +		if (imsm_level_ops[idx].level == level)
 | |
| +			break;
 | |
| +	}
 | |
|  
 | |
| -	return 0;
 | |
| +	if (!imsm_level_ops[idx].name)
 | |
| +		return false;
 | |
| +
 | |
| +	if (!imsm_level_ops[idx].is_raiddisks_count_supported(raiddisks))
 | |
| +		return false;
 | |
| +
 | |
| +	if (!orom)
 | |
| +		return true;
 | |
| +
 | |
| +	if (imsm_level_ops[idx].is_level_supported(orom))
 | |
| +		return true;
 | |
| +
 | |
| +	return false;
 | |
|  }
 | |
|  
 | |
|  static int
 | |
| @@ -11962,18 +11984,17 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 | |
|  	int change = -1;
 | |
|  	int check_devs = 0;
 | |
|  	int chunk;
 | |
| -	/* number of added/removed disks in operation result */
 | |
| -	int devNumChange = 0;
 | |
|  	/* imsm compatible layout value for array geometry verification */
 | |
|  	int imsm_layout = -1;
 | |
| +	int raid_disks = geo->raid_disks;
 | |
|  	imsm_status_t rv;
 | |
|  
 | |
|  	getinfo_super_imsm_volume(st, &info, NULL);
 | |
| -	if (geo->level != info.array.level && geo->level >= 0 &&
 | |
| +	if (geo->level != info.array.level && geo->level >= IMSM_T_RAID0 &&
 | |
|  	    geo->level != UnSet) {
 | |
|  		switch (info.array.level) {
 | |
| -		case 0:
 | |
| -			if (geo->level == 5) {
 | |
| +		case IMSM_T_RAID0:
 | |
| +			if (geo->level == IMSM_T_RAID5) {
 | |
|  				change = CH_MIGRATION;
 | |
|  				if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) {
 | |
|  					pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n");
 | |
| @@ -11982,20 +12003,20 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 | |
|  				}
 | |
|  				imsm_layout =  geo->layout;
 | |
|  				check_devs = 1;
 | |
| -				devNumChange = 1; /* parity disk added */
 | |
| -			} else if (geo->level == 10) {
 | |
| +				raid_disks += 1; /* parity disk added */
 | |
| +			} else if (geo->level == IMSM_T_RAID10) {
 | |
|  				change = CH_TAKEOVER;
 | |
|  				check_devs = 1;
 | |
| -				devNumChange = 2; /* two mirrors added */
 | |
| +				raid_disks *= 2; /* mirrors added */
 | |
|  				imsm_layout = 0x102; /* imsm supported layout */
 | |
|  			}
 | |
|  			break;
 | |
| -		case 1:
 | |
| -		case 10:
 | |
| +		case IMSM_T_RAID1:
 | |
| +		case IMSM_T_RAID10:
 | |
|  			if (geo->level == 0) {
 | |
|  				change = CH_TAKEOVER;
 | |
|  				check_devs = 1;
 | |
| -				devNumChange = -(geo->raid_disks/2);
 | |
| +				raid_disks /= 2;
 | |
|  				imsm_layout = 0; /* imsm raid0 layout */
 | |
|  			}
 | |
|  			break;
 | |
| @@ -12011,10 +12032,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 | |
|  	if (geo->layout != info.array.layout &&
 | |
|  	    (geo->layout != UnSet && geo->layout != -1)) {
 | |
|  		change = CH_MIGRATION;
 | |
| -		if (info.array.layout == 0 && info.array.level == 5 &&
 | |
| +		if (info.array.layout == 0 && info.array.level == IMSM_T_RAID5 &&
 | |
|  		    geo->layout == 5) {
 | |
|  			/* reshape 5 -> 4 */
 | |
| -		} else if (info.array.layout == 5 && info.array.level == 5 &&
 | |
| +		} else if (info.array.layout == 5 && info.array.level == IMSM_T_RAID5 &&
 | |
|  			   geo->layout == 0) {
 | |
|  			/* reshape 4 -> 5 */
 | |
|  			geo->layout = 0;
 | |
| @@ -12033,7 +12054,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 | |
|  
 | |
|  	if (geo->chunksize > 0 && geo->chunksize != UnSet &&
 | |
|  	    geo->chunksize != info.array.chunk_size) {
 | |
| -		if (info.array.level == 10) {
 | |
| +		if (info.array.level == IMSM_T_RAID10) {
 | |
|  			pr_err("Error. Chunk size change for RAID 10 is not supported.\n");
 | |
|  			change = -1;
 | |
|  			goto analyse_change_exit;
 | |
| @@ -12058,14 +12079,16 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 | |
|  		rv = imsm_analyze_expand(st, geo, &info, direction);
 | |
|  		if (rv != IMSM_STATUS_OK)
 | |
|  			goto analyse_change_exit;
 | |
| +		raid_disks = geo->raid_disks;
 | |
|  		change = CH_ARRAY_SIZE;
 | |
|  	}
 | |
|  
 | |
|  	chunk = geo->chunksize / 1024;
 | |
| +
 | |
|  	if (!validate_geometry_imsm(st,
 | |
|  				    geo->level,
 | |
|  				    imsm_layout,
 | |
| -				    geo->raid_disks + devNumChange,
 | |
| +				    raid_disks,
 | |
|  				    &chunk,
 | |
|  				    geo->size, INVALID_SECTORS,
 | |
|  				    0, 0, info.consistency_policy, 1))
 | |
| -- 
 | |
| 2.41.0
 | |
| 
 |