New upstream release v2.03.11
This commit is contained in:
		
							parent
							
								
									a875f27880
								
							
						
					
					
						commit
						d2cc5b0434
					
				| @ -1,17 +0,0 @@ | |||||||
| -----BEGIN PGP SIGNATURE----- |  | ||||||
| Version: GnuPG v2.0.22 (GNU/Linux) |  | ||||||
| 
 |  | ||||||
| iQIcBAABAgAGBQJfMBQmAAoJELkRJDHlCQOfTCoP/RF9P2RY7NXhXVxfpKbTqqhW |  | ||||||
| Xag1M5HAMmxflbiYI8Lrh1S7NrSHicWWitiHeKkYTwZxiC8E/HVwZq4UJyl5EDcA |  | ||||||
| F7FoZuVKB/NPVCjrnvDTwm9pZGZcYErufqb1sT/8cSCtr+vOvRQB5wAWtiu0lQA6 |  | ||||||
| OgcqAzM6Vvx04DiufKYfGoii+VvvfmICtOcQtMBfXpMmp7MCtOlTVeMYCbyiKYr1 |  | ||||||
| 4YutnoB41lIyfARA6vu0E+VfbpgJX0KwJS01cWV5XES4kDGBdqqFPJVgagMRCCGo |  | ||||||
| ssBETAFybQBWVs1OUipIhiZAn1JGXmoZ10UIBPs1GBfKisz+NOr4UQtQV+hMKLex |  | ||||||
| Wx6fqRzZsof1hOLn/XO8h6626fDcf2YGV5ayIFAyv2IGpMJN0iqBkw4PHOtcP1ft |  | ||||||
| RqkjwWTm56q97eZN5o8clvAnIN6Anyyx8t1BJUWmZ/QTzMYC98CMZTa0/foq7kw4 |  | ||||||
| qBrsqz1PmdKhWL8xtBdrEcwiuDyPaP/hfdfGEDNBiqVN9zVEVIfbJ2OK4xSUfIr5 |  | ||||||
| hdyjYC+gGRQ/CX0o0YC8PQifzxXthw17XDiH15MhlplCrLJk2CwLMQqKLThe9ksE |  | ||||||
| 3OcQnynS59gI2AfQdALVgSIvzUSMBY7V3I2H9kkBGhywJ64Ow2qpNWXd1wF9DDb5 |  | ||||||
| 6F0ElaB5hDrghbwMcFTg |  | ||||||
| =0jtu |  | ||||||
| -----END PGP SIGNATURE----- |  | ||||||
							
								
								
									
										17
									
								
								LVM2.2.03.11.tgz.asc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								LVM2.2.03.11.tgz.asc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | -----BEGIN PGP SIGNATURE----- | ||||||
|  | Version: GnuPG v2.0.22 (GNU/Linux) | ||||||
|  | 
 | ||||||
|  | iQIcBAABAgAGBQJf+CGBAAoJELkRJDHlCQOfbcAQAIky3+aEOxnpeT5T2XFRvsCJ | ||||||
|  | Uk71G70q24JupybEEYvhehf3RmeQkLP3c0TeNMFweqzUwpZBIhpbymglhaNG2AZc | ||||||
|  | 3Bbnl1SAGZ5IzdqacrKfCIas1b/UZMbRAhjcCFQ3oD0SApl+dED2RUacJCnlZxkE | ||||||
|  | NX3+MG4S6po84uQdHwZGtAw2+HQ0G5GwIETjxJHcQ+q8SZdWJRhKU25Z7UC1LI5u | ||||||
|  | 648SmSlsy2KoNIOSM/sWwgz1MXSWnN0y1mBxfBrR7bdnrPW+ExumzTqZrECIuiyl | ||||||
|  | bbD3Me/wEfyk4XZt2SoZF9k0Hf3QcSULeTeJlHOqUfLRGKm9E9ngkR/yfb2De/zP | ||||||
|  | tMzvFyu/tiCfFRXmQbS7K8dFzUzs6KQCHIPuJYnv+BjxOW9gjeyK5JPgBCsOLu// | ||||||
|  | mEf64ttDDKmCx1qOEnMhxTckvSH8YedmbQRov3g0ZXE3syG4OrhT1DHTyAnv69/f | ||||||
|  | fNVhOjd4POAoQx2UQzftgU7f4LiMPrQyRiUnQ0DRxHSEYXnIngpqokaVodfvpJp5 | ||||||
|  | 8YEuce9Xvq9JCplzKc1OXNtZQUHMybeyVzeenPVYvRV11ZbHzMAzwB6Byhwc9xgt | ||||||
|  | iKIuWpxMiPveKih3l/THoGOj19OUAN2XvWcGbOa6hTy6m/wsnoJQ0Xx5b5Ysfc1s | ||||||
|  | U60q2IDLJUS0H2R2raoc | ||||||
|  | =NE9u | ||||||
|  | -----END PGP SIGNATURE----- | ||||||
							
								
								
									
										15
									
								
								lvm2-2_03_12-WHATS_NEW-update.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								lvm2-2_03_12-WHATS_NEW-update.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  |  WHATS_NEW | 2 ++ | ||||||
|  |  1 file changed, 2 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/WHATS_NEW b/WHATS_NEW
 | ||||||
|  | index ffefc9d..3953c7e 100644
 | ||||||
|  | --- a/WHATS_NEW
 | ||||||
|  | +++ b/WHATS_NEW
 | ||||||
|  | @@ -1,5 +1,7 @@
 | ||||||
|  |  Version 2.03.12 -  | ||||||
|  |  =================================== | ||||||
|  | +  Fix problem with wiping of converted LVs.
 | ||||||
|  | +  Fix memleak in scanning  (2.03.11).
 | ||||||
|  |    Fix corner case allocation for thin-pools. | ||||||
|  |   | ||||||
|  |  Version 2.03.11 - 08th January 2021 | ||||||
| @ -0,0 +1,47 @@ | |||||||
|  |  WHATS_NEW               | 10 ++++++++-- | ||||||
|  |  lib/metadata/lv_manip.c | 10 +++++++--- | ||||||
|  |  2 files changed, 11 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/WHATS_NEW b/WHATS_NEW
 | ||||||
|  | index 452a631..fe347f7 100644
 | ||||||
|  | --- a/WHATS_NEW
 | ||||||
|  | +++ b/WHATS_NEW
 | ||||||
|  | @@ -1,3 +1,7 @@
 | ||||||
|  | +Version 2.03.12 - 
 | ||||||
|  | +===================================
 | ||||||
|  | +  Fix corner case allocation for thin-pools.
 | ||||||
|  | +
 | ||||||
|  |  Version 2.03.11 - 08th January 2021 | ||||||
|  |  =================================== | ||||||
|  |    Fix pvck handling MDA at offset different from 4096. | ||||||
|  | diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
 | ||||||
|  | index 7046436..443d32c 100644
 | ||||||
|  | --- a/lib/metadata/lv_manip.c
 | ||||||
|  | +++ b/lib/metadata/lv_manip.c
 | ||||||
|  | @@ -1850,11 +1850,13 @@ static uint32_t _mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint
 | ||||||
|  |   | ||||||
|  |  /* Is there enough total space or should we give up immediately? */ | ||||||
|  |  static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms, | ||||||
|  | -				uint32_t allocated, uint32_t extents_still_needed)
 | ||||||
|  | +				uint32_t allocated, uint32_t log_still_needed,
 | ||||||
|  | +				uint32_t extents_still_needed)
 | ||||||
|  |  { | ||||||
|  |  	uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple; | ||||||
|  |  	uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple; | ||||||
|  | -	uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN + ah->log_len; /* One each */
 | ||||||
|  | +	uint32_t metadata_extents_needed = (ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN) +
 | ||||||
|  | +	    (log_still_needed ? ah->log_len : 0); /* One each */
 | ||||||
|  |  	uint64_t total_extents_needed = (uint64_t)area_extents_needed + parity_extents_needed + metadata_extents_needed; | ||||||
|  |  	uint32_t free_pes = pv_maps_size(pvms); | ||||||
|  |   | ||||||
|  | @@ -3359,7 +3361,9 @@ static int _allocate(struct alloc_handle *ah,
 | ||||||
|  |  		old_allocated = alloc_state.allocated; | ||||||
|  |  		log_debug_alloc("Trying allocation using %s policy.", get_alloc_string(alloc)); | ||||||
|  |   | ||||||
|  | -		if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
 | ||||||
|  | +		if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated,
 | ||||||
|  | +							       alloc_state.log_area_count_still_needed,
 | ||||||
|  | +							       ah->new_extents))
 | ||||||
|  |  			goto_out; | ||||||
|  |   | ||||||
|  |  		_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg, | ||||||
							
								
								
									
										107
									
								
								lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | |||||||
|  |  lib/metadata/cache_manip.c       | 40 ++++++++++++++-------------------------- | ||||||
|  |  lib/metadata/metadata-exported.h |  1 + | ||||||
|  |  tools/lvconvert.c                |  1 + | ||||||
|  |  tools/lvcreate.c                 |  1 + | ||||||
|  |  4 files changed, 17 insertions(+), 26 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
 | ||||||
|  | index 2c4cc92..90ebd94 100644
 | ||||||
|  | --- a/lib/metadata/cache_manip.c
 | ||||||
|  | +++ b/lib/metadata/cache_manip.c
 | ||||||
|  | @@ -204,6 +204,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  			     unsigned attr, | ||||||
|  |  			     uint32_t pool_data_extents, | ||||||
|  |  			     uint32_t *pool_metadata_extents, | ||||||
|  | +			     struct logical_volume *metadata_lv,
 | ||||||
|  |  			     int *chunk_size_calc_method, uint32_t *chunk_size) | ||||||
|  |  { | ||||||
|  |  	uint64_t min_meta_size; | ||||||
|  | @@ -252,39 +253,26 @@ int update_cache_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  	if (!validate_cache_chunk_size(cmd, *chunk_size)) | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | -	min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
 | ||||||
|  | +	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
 | ||||||
|  | +		log_error("Size of %s data volume cannot be smaller than chunk size %s.",
 | ||||||
|  | +			  segtype->name, display_size(cmd, *chunk_size));
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  | -	/* Round up to extent size */
 | ||||||
|  | -	if (min_meta_size % extent_size)
 | ||||||
|  | -		min_meta_size += extent_size - min_meta_size % extent_size;
 | ||||||
|  | +	min_meta_size = _cache_min_metadata_size((uint64_t) pool_data_extents * extent_size, *chunk_size);
 | ||||||
|  | +	min_meta_size = dm_round_up(min_meta_size, extent_size);
 | ||||||
|  |   | ||||||
|  |  	if (!pool_metadata_size) | ||||||
|  |  		pool_metadata_size = min_meta_size; | ||||||
|  |   | ||||||
|  | -	if (pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
 | ||||||
|  | -		pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
 | ||||||
|  | -		if (*pool_metadata_extents)
 | ||||||
|  | -			log_warn("WARNING: Maximum supported pool metadata size is %s.",
 | ||||||
|  | -				 display_size(cmd, pool_metadata_size));
 | ||||||
|  | -	} else if (pool_metadata_size < min_meta_size) {
 | ||||||
|  | -		if (*pool_metadata_extents)
 | ||||||
|  | -			log_warn("WARNING: Minimum required pool metadata size is %s "
 | ||||||
|  | -				 "(needs extra %s).",
 | ||||||
|  | -				 display_size(cmd, min_meta_size),
 | ||||||
|  | -				 display_size(cmd, min_meta_size - pool_metadata_size));
 | ||||||
|  | -		pool_metadata_size = min_meta_size;
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	if (!(*pool_metadata_extents =
 | ||||||
|  | -	      extents_from_size(cmd, pool_metadata_size, extent_size)))
 | ||||||
|  | +	if (!update_pool_metadata_min_max(cmd, extent_size,
 | ||||||
|  | +					  min_meta_size,
 | ||||||
|  | +					  (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE),
 | ||||||
|  | +					  &pool_metadata_size,
 | ||||||
|  | +					  metadata_lv,
 | ||||||
|  | +					  pool_metadata_extents))
 | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | -	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) {
 | ||||||
|  | -		log_error("Size of %s data volume cannot be smaller than chunk size %s.",
 | ||||||
|  | -			  segtype->name, display_size(cmd, *chunk_size));
 | ||||||
|  | -		return 0;
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  |  	log_verbose("Preferred pool metadata size %s.", | ||||||
|  |  		    display_size(cmd, (uint64_t)*pool_metadata_extents * extent_size)); | ||||||
|  |   | ||||||
|  | diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
 | ||||||
|  | index 0e57722..c0fa564 100644
 | ||||||
|  | --- a/lib/metadata/metadata-exported.h
 | ||||||
|  | +++ b/lib/metadata/metadata-exported.h
 | ||||||
|  | @@ -1319,6 +1319,7 @@ int update_cache_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  			     unsigned attr, | ||||||
|  |  			     uint32_t pool_data_extents, | ||||||
|  |  			     uint32_t *pool_metadata_extents, | ||||||
|  | +			     struct logical_volume *metadata_lv,
 | ||||||
|  |  			     int *chunk_size_calc_method, uint32_t *chunk_size); | ||||||
|  |  int validate_lv_cache_chunk_size(struct logical_volume *pool_lv, uint32_t chunk_size); | ||||||
|  |  int validate_lv_cache_create_pool(const struct logical_volume *pool_lv); | ||||||
|  | diff --git a/tools/lvconvert.c b/tools/lvconvert.c
 | ||||||
|  | index ce90279..416e8a7 100644
 | ||||||
|  | --- a/tools/lvconvert.c
 | ||||||
|  | +++ b/tools/lvconvert.c
 | ||||||
|  | @@ -3189,6 +3189,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
 | ||||||
|  |  					      pool_segtype, target_attr, | ||||||
|  |  					      lv->le_count, | ||||||
|  |  					      &meta_extents, | ||||||
|  | +					      metadata_lv,
 | ||||||
|  |  					      &chunk_calc, | ||||||
|  |  					      &chunk_size)) | ||||||
|  |  			goto_bad; | ||||||
|  | diff --git a/tools/lvcreate.c b/tools/lvcreate.c
 | ||||||
|  | index 1ee9e14..1ce561f 100644
 | ||||||
|  | --- a/tools/lvcreate.c
 | ||||||
|  | +++ b/tools/lvcreate.c
 | ||||||
|  | @@ -403,6 +403,7 @@ static int _update_extents_params(struct volume_group *vg,
 | ||||||
|  |  						      lp->segtype, lp->target_attr, | ||||||
|  |  						      lp->extents, | ||||||
|  |  						      &lp->pool_metadata_extents, | ||||||
|  | +						      NULL,
 | ||||||
|  |  						      &lp->thin_chunk_size_calc_policy, | ||||||
|  |  						      &lp->chunk_size)) | ||||||
|  |  				return_0; | ||||||
| @ -0,0 +1,613 @@ | |||||||
|  |  conf/example.conf.in  | 146 +++++++++++++++++++++++++------------------------- | ||||||
|  |  conf/lvmlocal.conf.in |   4 +- | ||||||
|  |  lib/config/config.c   |   2 +- | ||||||
|  |  3 files changed, 76 insertions(+), 76 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/conf/example.conf.in b/conf/example.conf.in
 | ||||||
|  | index d149ed9..cd53147 100644
 | ||||||
|  | --- a/conf/example.conf.in
 | ||||||
|  | +++ b/conf/example.conf.in
 | ||||||
|  | @@ -78,14 +78,14 @@ devices {
 | ||||||
|  |  	# routines to acquire this information. For example, this information | ||||||
|  |  	# is used to drive LVM filtering like MD component detection, multipath | ||||||
|  |  	# component detection, partition detection and others. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   none | ||||||
|  |  	#     No external device information source is used. | ||||||
|  |  	#   udev | ||||||
|  |  	#     Reuse existing udev database records. Applicable only if LVM is | ||||||
|  |  	#     compiled with udev support. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	external_device_info_source = "none" | ||||||
|  |   | ||||||
|  |  	# Configuration option devices/hints. | ||||||
|  | @@ -94,13 +94,13 @@ devices {
 | ||||||
|  |  	# scanning, and will only scan the listed PVs. Removing the hint file | ||||||
|  |  	# will cause lvm to generate a new one. Disable hints if PVs will | ||||||
|  |  	# be copied onto devices using non-lvm commands, like dd. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   all | ||||||
|  |  	#     Use all hints. | ||||||
|  |  	#   none | ||||||
|  |  	#     Use no hints. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# hints = "all" | ||||||
|  |   | ||||||
|  | @@ -118,11 +118,11 @@ devices {
 | ||||||
|  |  	# Prefer the name with the least number of slashes. | ||||||
|  |  	# Prefer a name that is a symlink. | ||||||
|  |  	# Prefer the path with least value in lexicographical order. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] | ||||||
|  | -	# 
 | ||||||
|  | -	# This configuration option has an automatic default value.
 | ||||||
|  | +	#
 | ||||||
|  | +	# This configuration option does not have a default value defined.
 | ||||||
|  |  	# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] | ||||||
|  |   | ||||||
|  |  	# Configuration option devices/filter. | ||||||
|  | @@ -140,7 +140,7 @@ devices {
 | ||||||
|  |  	# then the device is accepted. Be careful mixing 'a' and 'r' patterns, | ||||||
|  |  	# as the combination might produce unexpected results (test changes.) | ||||||
|  |  	# Run vgscan after changing the filter to regenerate the cache. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Accept every block device: | ||||||
|  |  	# filter = [ "a|.*|" ] | ||||||
|  | @@ -152,7 +152,7 @@ devices {
 | ||||||
|  |  	# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ] | ||||||
|  |  	# Use anchors to be very specific: | ||||||
|  |  	# filter = [ "a|^/dev/hda8$|", "r|.*|" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# filter = [ "a|.*|" ] | ||||||
|  |   | ||||||
|  | @@ -170,10 +170,10 @@ devices {
 | ||||||
|  |  	# List of additional acceptable block device types. | ||||||
|  |  	# These are of device type names from /proc/devices, followed by the | ||||||
|  |  	# maximum number of partitions. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# types = [ "fd", 16 ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option is advanced. | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  | @@ -215,7 +215,7 @@ devices {
 | ||||||
|  |  	# Configuration option devices/md_component_checks. | ||||||
|  |  	# The checks LVM should use to detect MD component devices. | ||||||
|  |  	# MD component devices are block devices used by MD software RAID. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   auto | ||||||
|  |  	#     LVM will skip scanning the end of devices when it has other | ||||||
|  | @@ -226,7 +226,7 @@ devices {
 | ||||||
|  |  	#   full | ||||||
|  |  	#     LVM will scan the start and end of devices for MD superblocks. | ||||||
|  |  	#     This requires an extra read at the end of devices. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# md_component_checks = "auto" | ||||||
|  |   | ||||||
|  | @@ -368,7 +368,7 @@ allocation {
 | ||||||
|  |  	# defined here, it will check whether any of them are attached to the | ||||||
|  |  	# PVs concerned and then seek to match those PV tags between existing | ||||||
|  |  	# extents and new extents. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Use the special tag "@*" as a wildcard to match any PV tag: | ||||||
|  |  	# cling_tag_list = [ "@*" ] | ||||||
|  | @@ -376,7 +376,7 @@ allocation {
 | ||||||
|  |  	# PVs are tagged with either @site1 or @site2 to indicate where | ||||||
|  |  	# they are situated: | ||||||
|  |  	# cling_tag_list = [ "@site1", "@site2" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option allocation/maximise_cling. | ||||||
|  | @@ -435,25 +435,25 @@ allocation {
 | ||||||
|  |   | ||||||
|  |  	# Configuration option allocation/cache_metadata_format. | ||||||
|  |  	# Sets default metadata format for new cache. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   0  Automatically detected best available format | ||||||
|  |  	#   1  Original format | ||||||
|  |  	#   2  Improved 2nd. generation format | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# cache_metadata_format = 0 | ||||||
|  |   | ||||||
|  |  	# Configuration option allocation/cache_mode. | ||||||
|  |  	# The default cache mode used for new cache. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   writethrough | ||||||
|  |  	#     Data blocks are immediately written from the cache to disk. | ||||||
|  |  	#   writeback | ||||||
|  |  	#     Data blocks are written from the cache back to disk after some | ||||||
|  |  	#     delay to improve performance. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This setting replaces allocation/cache_pool_cachemode. | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# cache_mode = "writethrough" | ||||||
|  | @@ -502,18 +502,18 @@ allocation {
 | ||||||
|  |   | ||||||
|  |  	# Configuration option allocation/thin_pool_discards. | ||||||
|  |  	# The discards behaviour of thin pool volumes. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   ignore | ||||||
|  |  	#   nopassdown | ||||||
|  |  	#   passdown | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# thin_pool_discards = "passdown" | ||||||
|  |   | ||||||
|  |  	# Configuration option allocation/thin_pool_chunk_size_policy. | ||||||
|  |  	# The chunk size calculation policy for thin pool volumes. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   generic | ||||||
|  |  	#     If thin_pool_chunk_size is defined, use it. Otherwise, calculate | ||||||
|  | @@ -525,7 +525,7 @@ allocation {
 | ||||||
|  |  	#     the chunk size for performance based on device hints exposed in | ||||||
|  |  	#     sysfs - the optimal_io_size. The chunk size is always at least | ||||||
|  |  	#     512KiB. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# thin_pool_chunk_size_policy = "generic" | ||||||
|  |   | ||||||
|  | @@ -962,7 +962,7 @@ global {
 | ||||||
|  |  	# Configuration option global/mirror_segtype_default. | ||||||
|  |  	# The segment type used by the short mirroring option -m. | ||||||
|  |  	# The --type mirror|raid1 option overrides this setting. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   mirror | ||||||
|  |  	#     The original RAID1 implementation from LVM/DM. It is | ||||||
|  | @@ -982,16 +982,16 @@ global {
 | ||||||
|  |  	#     handling a failure. This mirror implementation is not | ||||||
|  |  	#     cluster-aware and cannot be used in a shared (active/active) | ||||||
|  |  	#     fashion in a cluster. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@" | ||||||
|  |   | ||||||
|  |  	# Configuration option global/support_mirrored_mirror_log. | ||||||
|  |  	# Enable mirrored 'mirror' log type for testing. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This type is deprecated to create or convert to but can | ||||||
|  |  	# be enabled to test that activation of existing mirrored | ||||||
|  |  	# logs and conversion to disk/core works. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Not supported for regular operation! | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# support_mirrored_mirror_log = 0 | ||||||
|  | @@ -1002,7 +1002,7 @@ global {
 | ||||||
|  |  	# The --stripes/-i and --mirrors/-m options can both be specified | ||||||
|  |  	# during the creation of a logical volume to use both striping and | ||||||
|  |  	# mirroring for the LV. There are two different implementations. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   raid10 | ||||||
|  |  	#     LVM uses MD's RAID10 personality through DM. This is the | ||||||
|  | @@ -1012,7 +1012,7 @@ global {
 | ||||||
|  |  	#     is done by creating a mirror LV on top of striped sub-LVs, | ||||||
|  |  	#     effectively creating a RAID 0+1 array. The layering is suboptimal | ||||||
|  |  	#     in terms of providing redundancy and performance. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	raid10_segtype_default = "@DEFAULT_RAID10_SEGTYPE@" | ||||||
|  |   | ||||||
|  |  	# Configuration option global/sparse_segtype_default. | ||||||
|  | @@ -1020,7 +1020,7 @@ global {
 | ||||||
|  |  	# The --type snapshot|thin option overrides this setting. | ||||||
|  |  	# The combination of -V and -L options creates a sparse LV. There are | ||||||
|  |  	# two different implementations. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   snapshot | ||||||
|  |  	#     The original snapshot implementation from LVM/DM. It uses an old | ||||||
|  | @@ -1032,7 +1032,7 @@ global {
 | ||||||
|  |  	#     bigger minimal chunk size (64KiB) and uses a separate volume for | ||||||
|  |  	#     metadata. It has better performance, especially when more data | ||||||
|  |  	#     is used. It also supports full snapshots. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	sparse_segtype_default = "@DEFAULT_SPARSE_SEGTYPE@" | ||||||
|  |   | ||||||
|  |  	# Configuration option global/lvdisplay_shows_full_device_path. | ||||||
|  | @@ -1130,20 +1130,20 @@ global {
 | ||||||
|  |  	# causing problems. Features include: block_size, discards, | ||||||
|  |  	# discards_non_power_2, external_origin, metadata_resize, | ||||||
|  |  	# external_origin_extend, error_if_no_space. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# thin_disabled_features = [ "discards", "block_size" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option global/cache_disabled_features. | ||||||
|  |  	# Features to not use in the cache driver. | ||||||
|  |  	# This can be helpful for testing, or to avoid using a feature that is | ||||||
|  |  	# causing problems. Features include: policy_mq, policy_smq, metadata2. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# cache_disabled_features = [ "policy_smq" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option global/cache_check_executable. | ||||||
|  | @@ -1207,7 +1207,7 @@ global {
 | ||||||
|  |  	# or vgimport.) A VG on shared storage devices is accessible only to | ||||||
|  |  	# the host with a matching system ID. See 'man lvmsystemid' for | ||||||
|  |  	# information on limitations and correct usage. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   none | ||||||
|  |  	#     The host has no system ID. | ||||||
|  | @@ -1224,7 +1224,7 @@ global {
 | ||||||
|  |  	#   file | ||||||
|  |  	#     Use the contents of another file (system_id_file) to set the | ||||||
|  |  	#     system ID. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	system_id_source = "none" | ||||||
|  |   | ||||||
|  |  	# Configuration option global/system_id_file. | ||||||
|  | @@ -1350,7 +1350,7 @@ activation {
 | ||||||
|  |  	# If this list is defined, an LV is only activated if it matches an | ||||||
|  |  	# entry in this list. If this list is undefined, it imposes no limits | ||||||
|  |  	# on LV activation (all are allowed). | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   vgname | ||||||
|  |  	#     The VG name is matched exactly and selects all LVs in the VG. | ||||||
|  | @@ -1364,10 +1364,10 @@ activation {
 | ||||||
|  |  	#     or VG. See tags/hosttags. If any host tags exist but volume_list | ||||||
|  |  	#     is not defined, a default single-entry list containing '@*' | ||||||
|  |  	#     is assumed. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/auto_activation_volume_list. | ||||||
|  | @@ -1387,7 +1387,7 @@ activation {
 | ||||||
|  |  	# commands run directly by a user. A user may also use the 'a' flag | ||||||
|  |  	# directly to perform auto-activation. Also see pvscan(8) for more | ||||||
|  |  	# information about auto-activation. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   vgname | ||||||
|  |  	#     The VG name is matched exactly and selects all LVs in the VG. | ||||||
|  | @@ -1401,10 +1401,10 @@ activation {
 | ||||||
|  |  	#     or VG. See tags/hosttags. If any host tags exist but volume_list | ||||||
|  |  	#     is not defined, a default single-entry list containing '@*' | ||||||
|  |  	#     is assumed. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/read_only_volume_list. | ||||||
|  | @@ -1413,7 +1413,7 @@ activation {
 | ||||||
|  |  	# against this list, and if it matches, it is activated in read-only | ||||||
|  |  	# mode. This overrides the permission setting stored in the metadata, | ||||||
|  |  	# e.g. from --permission rw. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   vgname | ||||||
|  |  	#     The VG name is matched exactly and selects all LVs in the VG. | ||||||
|  | @@ -1427,10 +1427,10 @@ activation {
 | ||||||
|  |  	#     or VG. See tags/hosttags. If any host tags exist but volume_list | ||||||
|  |  	#     is not defined, a default single-entry list containing '@*' | ||||||
|  |  	#     is assumed. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/raid_region_size. | ||||||
|  | @@ -1453,13 +1453,13 @@ activation {
 | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/readahead. | ||||||
|  |  	# Setting to use when there is no readahead setting in metadata. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   none | ||||||
|  |  	#     Disable readahead. | ||||||
|  |  	#   auto | ||||||
|  |  	#     Use default value chosen by kernel. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# readahead = "auto" | ||||||
|  |   | ||||||
|  | @@ -1471,7 +1471,7 @@ activation {
 | ||||||
|  |  	# performed by dmeventd automatically, and the steps perfomed by the | ||||||
|  |  	# manual command lvconvert --repair --use-policies. | ||||||
|  |  	# Automatic handling requires dmeventd to be monitoring the LV. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   warn | ||||||
|  |  	#     Use the system log to warn the user that a device in the RAID LV | ||||||
|  | @@ -1482,7 +1482,7 @@ activation {
 | ||||||
|  |  	#   allocate | ||||||
|  |  	#     Attempt to use any extra physical volumes in the VG as spares and | ||||||
|  |  	#     replace faulty devices. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	raid_fault_policy = "warn" | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/mirror_image_fault_policy. | ||||||
|  | @@ -1494,7 +1494,7 @@ activation {
 | ||||||
|  |  	# determines the steps perfomed by dmeventd automatically, and the steps | ||||||
|  |  	# performed by the manual command lvconvert --repair --use-policies. | ||||||
|  |  	# Automatic handling requires dmeventd to be monitoring the LV. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   remove | ||||||
|  |  	#     Simply remove the faulty device and run without it. If the log | ||||||
|  | @@ -1519,7 +1519,7 @@ activation {
 | ||||||
|  |  	#     the redundant nature of the mirror. This policy acts like | ||||||
|  |  	#     'remove' if no suitable device and space can be allocated for the | ||||||
|  |  	#     replacement. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	mirror_image_fault_policy = "remove" | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/mirror_log_fault_policy. | ||||||
|  | @@ -1534,26 +1534,26 @@ activation {
 | ||||||
|  |  	# The minimum value is 50 (a smaller value is treated as 50.) | ||||||
|  |  	# Also see snapshot_autoextend_percent. | ||||||
|  |  	# Automatic extension requires dmeventd to be monitoring the LV. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 1G | ||||||
|  |  	# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds | ||||||
|  |  	# 840M, it is extended to 1.44G: | ||||||
|  |  	# snapshot_autoextend_threshold = 70 | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	snapshot_autoextend_threshold = 100 | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/snapshot_autoextend_percent. | ||||||
|  |  	# Auto-extending a snapshot adds this percent extra space. | ||||||
|  |  	# The amount of additional space added to a snapshot is this | ||||||
|  |  	# percent of its current size. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 1G | ||||||
|  |  	# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds | ||||||
|  |  	# 840M, it is extended to 1.44G: | ||||||
|  |  	# snapshot_autoextend_percent = 20 | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	snapshot_autoextend_percent = 20 | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/thin_pool_autoextend_threshold. | ||||||
|  | @@ -1562,26 +1562,26 @@ activation {
 | ||||||
|  |  	# The minimum value is 50 (a smaller value is treated as 50.) | ||||||
|  |  	# Also see thin_pool_autoextend_percent. | ||||||
|  |  	# Automatic extension requires dmeventd to be monitoring the LV. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 1G | ||||||
|  |  	# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds | ||||||
|  |  	# 840M, it is extended to 1.44G: | ||||||
|  |  	# thin_pool_autoextend_threshold = 70 | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	thin_pool_autoextend_threshold = 100 | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/thin_pool_autoextend_percent. | ||||||
|  |  	# Auto-extending a thin pool adds this percent extra space. | ||||||
|  |  	# The amount of additional space added to a thin pool is this | ||||||
|  |  	# percent of its current size. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 1G | ||||||
|  |  	# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds | ||||||
|  |  	# 840M, it is extended to 1.44G: | ||||||
|  |  	# thin_pool_autoextend_percent = 20 | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	thin_pool_autoextend_percent = 20 | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/vdo_pool_autoextend_threshold. | ||||||
|  | @@ -1590,13 +1590,13 @@ activation {
 | ||||||
|  |  	# The minimum value is 50 (a smaller value is treated as 50.) | ||||||
|  |  	# Also see vdo_pool_autoextend_percent. | ||||||
|  |  	# Automatic extension requires dmeventd to be monitoring the LV. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 10G | ||||||
|  |  	# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds | ||||||
|  |  	# 8.4G, it is extended to 14.4G: | ||||||
|  |  	# vdo_pool_autoextend_threshold = 70 | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# vdo_pool_autoextend_threshold = 100 | ||||||
|  |   | ||||||
|  | @@ -1604,7 +1604,7 @@ activation {
 | ||||||
|  |  	# Auto-extending a VDO pool adds this percent extra space. | ||||||
|  |  	# The amount of additional space added to a VDO pool is this | ||||||
|  |  	# percent of its current size. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Using 70% autoextend threshold and 20% autoextend size, when a 10G | ||||||
|  |  	# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds | ||||||
|  | @@ -1623,10 +1623,10 @@ activation {
 | ||||||
|  |  	# pages corresponding to lines that match are not pinned. On some | ||||||
|  |  	# systems, locale-archive was found to make up over 80% of the memory | ||||||
|  |  	# used by the process. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ] | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option is advanced. | ||||||
|  |  	# This configuration option does not have a default value defined. | ||||||
|  |   | ||||||
|  | @@ -1667,7 +1667,7 @@ activation {
 | ||||||
|  |  	# Configuration option activation/activation_mode. | ||||||
|  |  	# How LVs with missing devices are activated. | ||||||
|  |  	# The --activationmode option overrides this setting. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   complete | ||||||
|  |  	#     Only allow activation of an LV if all of the Physical Volumes it | ||||||
|  | @@ -1682,7 +1682,7 @@ activation {
 | ||||||
|  |  	#     could cause data loss with a portion of the LV inaccessible. | ||||||
|  |  	#     This setting should not normally be used, but may sometimes | ||||||
|  |  	#     assist with data recovery. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	activation_mode = "degraded" | ||||||
|  |   | ||||||
|  |  	# Configuration option activation/lock_start_list. | ||||||
|  | @@ -1730,7 +1730,7 @@ activation {
 | ||||||
|  |  	# Configuration option metadata/pvmetadatacopies. | ||||||
|  |  	# Number of copies of metadata to store on each PV. | ||||||
|  |  	# The --pvmetadatacopies option overrides this setting. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   2 | ||||||
|  |  	#     Two copies of the VG metadata are stored on the PV, one at the | ||||||
|  | @@ -1740,7 +1740,7 @@ activation {
 | ||||||
|  |  	#   0 | ||||||
|  |  	#     No copies of VG metadata are stored on the PV. This may be | ||||||
|  |  	#     useful for VGs containing large numbers of PVs. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option is advanced. | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# pvmetadatacopies = 1 | ||||||
|  | @@ -1890,7 +1890,7 @@ activation {
 | ||||||
|  |  	# sequences are copied verbatim. Each special character sequence is | ||||||
|  |  	# introduced by the '%' character and such sequence is then | ||||||
|  |  	# substituted with a value as described below. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Accepted values: | ||||||
|  |  	#   %a | ||||||
|  |  	#     The abbreviated name of the day of the week according to the | ||||||
|  | @@ -2013,7 +2013,7 @@ activation {
 | ||||||
|  |  	#     The timezone name or abbreviation. | ||||||
|  |  	#   %% | ||||||
|  |  	#     A literal '%' character. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# time_format = "%Y-%m-%d %T %z" | ||||||
|  |   | ||||||
|  | @@ -2282,12 +2282,12 @@ dmeventd {
 | ||||||
|  |  	# applied to the local machine as a 'host tag'. If this subsection is | ||||||
|  |  	# empty (has no host_list), then the subsection name is always applied | ||||||
|  |  	# as a 'host tag'. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# The host tag foo is given to all hosts, and the host tag | ||||||
|  |  	# bar is given to the hosts named machine1 and machine2. | ||||||
|  |  	# tags { foo { } bar { host_list = [ "machine1", "machine2" ] } } | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration section has variable name. | ||||||
|  |  	# This configuration section has an automatic default value. | ||||||
|  |  	# tag { | ||||||
|  | diff --git a/conf/lvmlocal.conf.in b/conf/lvmlocal.conf.in
 | ||||||
|  | index 04414bf..12214ea 100644
 | ||||||
|  | --- a/conf/lvmlocal.conf.in
 | ||||||
|  | +++ b/conf/lvmlocal.conf.in
 | ||||||
|  | @@ -28,13 +28,13 @@ local {
 | ||||||
|  |  	# main configuration file, e.g. lvm.conf. When used, it must be set to | ||||||
|  |  	# a unique value among all hosts sharing access to the storage, | ||||||
|  |  	# e.g. a host name. | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# Example | ||||||
|  |  	# Set no system ID: | ||||||
|  |  	# system_id = "" | ||||||
|  |  	# Set the system_id to a specific name: | ||||||
|  |  	# system_id = "host1" | ||||||
|  | -	# 
 | ||||||
|  | +	#
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# system_id = "" | ||||||
|  |   | ||||||
|  | diff --git a/lib/config/config.c b/lib/config/config.c
 | ||||||
|  | index a25b7db..f9ca566 100644
 | ||||||
|  | --- a/lib/config/config.c
 | ||||||
|  | +++ b/lib/config/config.c
 | ||||||
|  | @@ -1738,7 +1738,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
 | ||||||
|  |  						continue; | ||||||
|  |  					commentline[0] = '\0'; | ||||||
|  |  				} | ||||||
|  | -				fprintf(out->fp, "%s# %s\n", line, commentline);
 | ||||||
|  | +				fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
 | ||||||
|  |  				/* withsummary prints only the first comment line. */ | ||||||
|  |  				if (!out->tree_spec->withcomments) | ||||||
|  |  					break; | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | From b3719266bd5e3a9e6737d6bda60e543121ddf343 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: David Teigland <teigland@redhat.com> | ||||||
|  | Date: Tue, 9 Feb 2021 09:47:08 -0600 | ||||||
|  | Subject: [PATCH] dev_get_primary_dev: fix invalid path check | ||||||
|  | 
 | ||||||
|  | Fix commit bee9f4efdd81 "filter-mpath: work with nvme devices" | ||||||
|  | which removed setting the path for readlink. | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit f74f94c2ddb1d33d75d325c959344a566a621fd5) | ||||||
|  | 
 | ||||||
|  | Conflicts: | ||||||
|  | 	lib/device/dev-type.c | ||||||
|  | ---
 | ||||||
|  |  lib/device/dev-type.c | 11 ++++++++--- | ||||||
|  |  1 file changed, 8 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
 | ||||||
|  | index 379afa8..1342e97 100644
 | ||||||
|  | --- a/lib/device/dev-type.c
 | ||||||
|  | +++ b/lib/device/dev-type.c
 | ||||||
|  | @@ -434,7 +434,7 @@ static int _has_sys_partition(struct device *dev)
 | ||||||
|  |  	int minor = (int) MINOR(dev->dev); | ||||||
|  |   | ||||||
|  |  	/* check if dev is a partition */ | ||||||
|  | -	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
 | ||||||
|  | +	if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
 | ||||||
|  |  			dm_sysfs_dir(), major, minor) < 0) { | ||||||
|  |  		log_error("dm_snprintf partition failed"); | ||||||
|  |  		return 0; | ||||||
|  | @@ -660,8 +660,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
 | ||||||
|  |  	 * - basename ../../block/md0/md0  = md0 | ||||||
|  |  	 * Parent's 'dev' sysfs attribute  = /sys/block/md0/dev | ||||||
|  |  	 */ | ||||||
|  | -	if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
 | ||||||
|  | -		log_sys_error("readlink", path);
 | ||||||
|  | +	if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d",
 | ||||||
|  | +			dm_sysfs_dir(), major, minor) < 0) {
 | ||||||
|  | +		log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  | +	if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
 | ||||||
|  | +		log_warn("WARNING: Readlink of %s failed.", path);
 | ||||||
|  |  		goto out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 1.8.3.1 | ||||||
|  | 
 | ||||||
							
								
								
									
										255
									
								
								lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,255 @@ | |||||||
|  |  lib/device/dev-cache.c    | 161 ++++++++++++++++++++++++++++++++++++---------- | ||||||
|  |  test/shell/dev-aliases.sh |  53 +++++++++++++++ | ||||||
|  |  2 files changed, 179 insertions(+), 35 deletions(-) | ||||||
|  |  create mode 100644 test/shell/dev-aliases.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
 | ||||||
|  | index d5f18ff..8082efa 100644
 | ||||||
|  | --- a/lib/device/dev-cache.c
 | ||||||
|  | +++ b/lib/device/dev-cache.c
 | ||||||
|  | @@ -1428,60 +1428,151 @@ struct device *dev_hash_get(const char *name)
 | ||||||
|  |  	return (struct device *) dm_hash_lookup(_cache.names, name); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void _remove_alias(struct device *dev, const char *name)
 | ||||||
|  | +{
 | ||||||
|  | +	struct dm_str_list *strl;
 | ||||||
|  | +
 | ||||||
|  | +	dm_list_iterate_items(strl, &dev->aliases) {
 | ||||||
|  | +		if (!strcmp(strl->str, name)) {
 | ||||||
|  | +			dm_list_del(&strl->list);
 | ||||||
|  | +			return;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/*
 | ||||||
|  | + * Check that paths for this dev still refer to the same dev_t.  This is known
 | ||||||
|  | + * to drop invalid paths in the case where lvm deactivates an LV, which causes
 | ||||||
|  | + * that LV path to go away, but that LV path is not removed from dev-cache (it
 | ||||||
|  | + * probably should be).  Later a new path to a different LV is added to
 | ||||||
|  | + * dev-cache, where the new LV has the same major:minor as the previously
 | ||||||
|  | + * deactivated LV.  The new LV will find the existing struct dev, and that
 | ||||||
|  | + * struct dev will have dev->aliases entries that refer to the name of the old
 | ||||||
|  | + * deactivated LV.  Those old paths are all invalid and are dropped here.
 | ||||||
|  | + */
 | ||||||
|  | +
 | ||||||
|  | +static void _verify_aliases(struct device *dev, const char *newname)
 | ||||||
|  | +{
 | ||||||
|  | +	struct dm_str_list *strl, *strl2;
 | ||||||
|  | +	struct stat st;
 | ||||||
|  | +
 | ||||||
|  | +	dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
 | ||||||
|  | +		/* newname was just stat'd and added by caller */
 | ||||||
|  | +		if (newname && !strcmp(strl->str, newname))
 | ||||||
|  | +			continue;
 | ||||||
|  | +
 | ||||||
|  | +		if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
 | ||||||
|  | +			log_debug("Drop invalid path %s for %d:%d (new path %s).",
 | ||||||
|  | +				  strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
 | ||||||
|  | +			dm_hash_remove(_cache.names, strl->str);
 | ||||||
|  | +			dm_list_del(&strl->list);
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f) | ||||||
|  |  { | ||||||
|  | -	struct stat buf;
 | ||||||
|  | -	struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
 | ||||||
|  | -	int info_available = 0;
 | ||||||
|  | -	int ret = 1;
 | ||||||
|  | +	struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
 | ||||||
|  | +	struct stat st;
 | ||||||
|  | +	int ret;
 | ||||||
|  |   | ||||||
|  | -	if (d && (d->flags & DEV_REGULAR))
 | ||||||
|  | -		return d;
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * DEV_REGULAR means that is "dev" is actually a file, not a device.
 | ||||||
|  | +	 * FIXME: I don't think dev-cache is used for files any more and this
 | ||||||
|  | +	 * can be dropped?
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (dev && (dev->flags & DEV_REGULAR))
 | ||||||
|  | +		return dev;
 | ||||||
|  | +
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * The requested path is invalid, remove any dev-cache
 | ||||||
|  | +	 * info for it.
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (stat(name, &st)) {
 | ||||||
|  | +		if (dev) {
 | ||||||
|  | +			log_print("Device path %s is invalid for %d:%d %s.",
 | ||||||
|  | +				  name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
 | ||||||
|  |   | ||||||
|  | -	/* If the entry's wrong, remove it */
 | ||||||
|  | -	if (stat(name, &buf) < 0) {
 | ||||||
|  | -		if (d)
 | ||||||
|  |  			dm_hash_remove(_cache.names, name); | ||||||
|  | -		log_sys_very_verbose("stat", name);
 | ||||||
|  | -		d = NULL;
 | ||||||
|  | -	} else
 | ||||||
|  | -		info_available = 1;
 | ||||||
|  |   | ||||||
|  | -	if (d && (buf.st_rdev != d->dev)) {
 | ||||||
|  | -		dm_hash_remove(_cache.names, name);
 | ||||||
|  | -		d = NULL;
 | ||||||
|  | -	}
 | ||||||
|  | +			_remove_alias(dev, name);
 | ||||||
|  |   | ||||||
|  | -	if (!d) {
 | ||||||
|  | -		_insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
 | ||||||
|  | -		d = (struct device *) dm_hash_lookup(_cache.names, name);
 | ||||||
|  | -		if (!d) {
 | ||||||
|  | -			log_debug_devs("Device name not found in dev_cache repeat dev_cache_scan for %s", name);
 | ||||||
|  | -			dev_cache_scan();
 | ||||||
|  | -			d = (struct device *) dm_hash_lookup(_cache.names, name);
 | ||||||
|  | +			/* Remove any other names in dev->aliases that are incorrect. */
 | ||||||
|  | +			_verify_aliases(dev, NULL);
 | ||||||
|  |  		} | ||||||
|  | +		return NULL;
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (!d)
 | ||||||
|  | +	if (!S_ISBLK(st.st_mode)) {
 | ||||||
|  | +		log_debug("Not a block device %s.", name);
 | ||||||
|  |  		return NULL; | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  | -	if (d && (d->flags & DEV_REGULAR))
 | ||||||
|  | -		return d;
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * dev-cache has incorrect info for the requested path.
 | ||||||
|  | +	 * Remove incorrect info and then add new dev-cache entry.
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (dev && (st.st_rdev != dev->dev)) {
 | ||||||
|  | +		log_print("Device path %s does not match %d:%d %s.",
 | ||||||
|  | +			  name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
 | ||||||
|  | +
 | ||||||
|  | +		dm_hash_remove(_cache.names, name);
 | ||||||
|  | +
 | ||||||
|  | +		_remove_alias(dev, name);
 | ||||||
|  | +
 | ||||||
|  | +		/* Remove any other names in dev->aliases that are incorrect. */
 | ||||||
|  | +		_verify_aliases(dev, NULL);
 | ||||||
|  | +
 | ||||||
|  | +		/* Add new dev-cache entry next. */
 | ||||||
|  | +		dev = NULL;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * Either add a new struct dev for st_rdev and name,
 | ||||||
|  | +	 * or add name as a new alias for an existing struct dev
 | ||||||
|  | +	 * for st_rdev.
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (!dev) {
 | ||||||
|  | +		_insert_dev(name, st.st_rdev);
 | ||||||
|  |   | ||||||
|  | -	if (f && !(d->flags & DEV_REGULAR)) {
 | ||||||
|  | -		ret = f->passes_filter(cmd, f, d, NULL);
 | ||||||
|  | +		/* Get the struct dev that was just added. */
 | ||||||
|  | +		dev = (struct device *) dm_hash_lookup(_cache.names, name);
 | ||||||
|  |   | ||||||
|  | -		if (ret == -EAGAIN) {
 | ||||||
|  | -			log_debug_devs("get device by name defer filter %s", dev_name(d));
 | ||||||
|  | -			d->flags |= DEV_FILTER_AFTER_SCAN;
 | ||||||
|  | -			ret = 1;
 | ||||||
|  | +		if (!dev) {
 | ||||||
|  | +			log_error("Failed to get device %s", name);
 | ||||||
|  | +			return NULL;
 | ||||||
|  |  		} | ||||||
|  | +
 | ||||||
|  | +		_verify_aliases(dev, name);
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (f && !(d->flags & DEV_REGULAR) && !ret)
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * The caller passed a filter if they only want the dev if it
 | ||||||
|  | +	 * passes filters.
 | ||||||
|  | +	 */
 | ||||||
|  | +
 | ||||||
|  | +	if (!f)
 | ||||||
|  | +		return dev;
 | ||||||
|  | +
 | ||||||
|  | +	ret = f->passes_filter(cmd, f, dev, NULL);
 | ||||||
|  | +
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * This might happen if this function is called before
 | ||||||
|  | +	 * filters can do i/o.  I don't think this will happen
 | ||||||
|  | +	 * any longer and this EAGAIN case can be removed.
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (ret == -EAGAIN) {
 | ||||||
|  | +		log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
 | ||||||
|  | +		dev->flags |= DEV_FILTER_AFTER_SCAN;
 | ||||||
|  | +		ret = 1;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	if (!ret) {
 | ||||||
|  | +		log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
 | ||||||
|  |  		return NULL; | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  | -	return d;
 | ||||||
|  | +	return dev;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static struct device *_dev_cache_seek_devt(dev_t dev) | ||||||
|  | diff --git a/test/shell/dev-aliases.sh b/test/shell/dev-aliases.sh
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..c97cd5d
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/shell/dev-aliases.sh
 | ||||||
|  | @@ -0,0 +1,53 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +
 | ||||||
|  | +# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
 | ||||||
|  | +#
 | ||||||
|  | +# This copyrighted material is made available to anyone wishing to use,
 | ||||||
|  | +# modify, copy, or redistribute it subject to the terms and conditions
 | ||||||
|  | +# of the GNU General Public License v.2.
 | ||||||
|  | +#
 | ||||||
|  | +# You should have received a copy of the GNU General Public License
 | ||||||
|  | +# along with this program; if not, write to the Free Software Foundation,
 | ||||||
|  | +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | ||||||
|  | +
 | ||||||
|  | +SKIP_WITH_LVMPOLLD=1
 | ||||||
|  | +
 | ||||||
|  | +. lib/inittest
 | ||||||
|  | +
 | ||||||
|  | +aux prepare_devs 3
 | ||||||
|  | +
 | ||||||
|  | +vgcreate $vg $dev1 $dev2 $dev3
 | ||||||
|  | +
 | ||||||
|  | +#
 | ||||||
|  | +# This lvconvert command will deactivate LV1, then internally create a new
 | ||||||
|  | +# lv, lvol0, as a poolmetadataspare, then activate lvol0 to zero it.
 | ||||||
|  | +# lvol0 will get the same major:minor that LV1 had.  When the code gets
 | ||||||
|  | +# the struct dev for lvol0, the new path to lvol0 is added to the
 | ||||||
|  | +# dev-cache with it's major:minor.  That major:minor already exists in
 | ||||||
|  | +# dev-cache and has the stale LV1 as an alias.  So the path to lvol0 is
 | ||||||
|  | +# added as an alias to the existing struct dev (with the correct
 | ||||||
|  | +# major:minor), but that struct dev has the stale LV1 path on its aliases
 | ||||||
|  | +# list.  The code will now validate all the aliases before returning the
 | ||||||
|  | +# dev for lvol0, and will find that the LV1 path is stale and remove it
 | ||||||
|  | +# from the aliases.  That will prevent the stale path from being used for
 | ||||||
|  | +# the dev in place of the new path.
 | ||||||
|  | +#
 | ||||||
|  | +# The preferred_name is set to /dev/mapper so that if the stale path still
 | ||||||
|  | +# exists, that stale path would be used as the name for the dev, and the
 | ||||||
|  | +# wiping code would fail to open that stale name.
 | ||||||
|  | +#
 | ||||||
|  | +
 | ||||||
|  | +lvcreate -n $lv1 -L32M $vg $dev1
 | ||||||
|  | +lvcreate -n $lv2 -L16M $vg $dev2
 | ||||||
|  | +lvconvert -y --type cache-pool --poolmetadata $lv2 --cachemode writeback $vg/$lv1 --config='devices { preferred_names=["/dev/mapper/"] }' 
 | ||||||
|  | +lvremove -y $vg/$lv1
 | ||||||
|  | +
 | ||||||
|  | +lvcreate -n $lv1 -L32M $vg $dev1
 | ||||||
|  | +lvcreate -n $lv2 -L16M $vg $dev2
 | ||||||
|  | +lvconvert -y --type cache-pool --poolmetadata $lv2 $vg/$lv1
 | ||||||
|  | +lvremove -y $vg/$lv1
 | ||||||
|  | +
 | ||||||
|  | +# TODO: add more validation of dev aliases being specified as command
 | ||||||
|  | +# args in combination with various preferred_names settings.
 | ||||||
|  | +
 | ||||||
|  | +vgremove -ff  $vg
 | ||||||
							
								
								
									
										494
									
								
								lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,494 @@ | |||||||
|  |  lib/device/dev-type.c      |  81 +++++++++++++++++++---- | ||||||
|  |  lib/device/dev-type.h      |   2 + | ||||||
|  |  lib/device/device.h        |   1 + | ||||||
|  |  lib/filters/filter-mpath.c | 156 ++++++++++++++++++++++++++++++--------------- | ||||||
|  |  4 files changed, 177 insertions(+), 63 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
 | ||||||
|  | index 896821d..379afa8 100644
 | ||||||
|  | --- a/lib/device/dev-type.c
 | ||||||
|  | +++ b/lib/device/dev-type.c
 | ||||||
|  | @@ -21,6 +21,7 @@
 | ||||||
|  |  #include "lib/metadata/metadata.h" | ||||||
|  |  #include "lib/device/bcache.h" | ||||||
|  |  #include "lib/label/label.h" | ||||||
|  | +#include "lib/commands/toolcontext.h"
 | ||||||
|  |   | ||||||
|  |  #ifdef BLKID_WIPING_SUPPORT | ||||||
|  |  #include <blkid.h> | ||||||
|  | @@ -67,6 +68,31 @@ int dev_is_pmem(struct device *dev)
 | ||||||
|  |  	return is_pmem ? 1 : 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * An nvme device has major number 259 (BLKEXT), minor number <minor>,
 | ||||||
|  | + * and reading /sys/dev/block/259:<minor>/device/dev shows a character
 | ||||||
|  | + * device cmajor:cminor where cmajor matches the major number of the
 | ||||||
|  | + * nvme character device entry in /proc/devices.  Checking all of that
 | ||||||
|  | + * is excessive and unnecessary compared to just comparing /dev/name*.
 | ||||||
|  | + */
 | ||||||
|  | +
 | ||||||
|  | +int dev_is_nvme(struct dev_types *dt, struct device *dev)
 | ||||||
|  | +{
 | ||||||
|  | +	struct dm_str_list *strl;
 | ||||||
|  | +
 | ||||||
|  | +	if (dev->flags & DEV_IS_NVME)
 | ||||||
|  | +		return 1;
 | ||||||
|  | +
 | ||||||
|  | +	dm_list_iterate_items(strl, &dev->aliases) {
 | ||||||
|  | +		if (!strncmp(strl->str, "/dev/nvme", 9)) {
 | ||||||
|  | +			log_debug("Found nvme device %s", dev_name(dev));
 | ||||||
|  | +			dev->flags |= DEV_IS_NVME;
 | ||||||
|  | +			return 1;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +	return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int dev_is_lv(struct device *dev) | ||||||
|  |  { | ||||||
|  |  	FILE *fp; | ||||||
|  | @@ -302,6 +328,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
 | ||||||
|  |   | ||||||
|  |  const char *dev_subsystem_name(struct dev_types *dt, struct device *dev) | ||||||
|  |  { | ||||||
|  | +	if (dev->flags & DEV_IS_NVME)
 | ||||||
|  | +		return "NVME";
 | ||||||
|  | +
 | ||||||
|  |  	if (MAJOR(dev->dev) == dt->device_mapper_major) | ||||||
|  |  		return "DM"; | ||||||
|  |   | ||||||
|  | @@ -348,7 +377,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
 | ||||||
|  |  	return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  |  static int _loop_is_with_partscan(struct device *dev) | ||||||
|  |  { | ||||||
|  |  	FILE *fp; | ||||||
|  | @@ -398,6 +426,28 @@ struct partition {
 | ||||||
|  |  	uint32_t nr_sects; | ||||||
|  |  } __attribute__((packed)); | ||||||
|  |   | ||||||
|  | +static int _has_sys_partition(struct device *dev)
 | ||||||
|  | +{
 | ||||||
|  | +	char path[PATH_MAX];
 | ||||||
|  | +	struct stat info;
 | ||||||
|  | +	int major = (int) MAJOR(dev->dev);
 | ||||||
|  | +	int minor = (int) MINOR(dev->dev);
 | ||||||
|  | +
 | ||||||
|  | +	/* check if dev is a partition */
 | ||||||
|  | +	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
 | ||||||
|  | +			dm_sysfs_dir(), major, minor) < 0) {
 | ||||||
|  | +		log_error("dm_snprintf partition failed");
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	if (stat(path, &info) == -1) {
 | ||||||
|  | +		if (errno != ENOENT)
 | ||||||
|  | +			log_sys_error("stat", path);
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  | +	return 1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int _is_partitionable(struct dev_types *dt, struct device *dev) | ||||||
|  |  { | ||||||
|  |  	int parts = major_max_partitions(dt, MAJOR(dev->dev)); | ||||||
|  | @@ -414,6 +464,13 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
 | ||||||
|  |  	    _loop_is_with_partscan(dev)) | ||||||
|  |  		return 1; | ||||||
|  |   | ||||||
|  | +	if (dev_is_nvme(dt, dev)) {
 | ||||||
|  | +		/* If this dev is already a partition then it's not partitionable. */
 | ||||||
|  | +		if (_has_sys_partition(dev))
 | ||||||
|  | +			return 0;
 | ||||||
|  | +		return 1;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	if ((parts <= 1) || (MINOR(dev->dev) % parts)) | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  | @@ -557,11 +614,18 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
 | ||||||
|  |  	char path[PATH_MAX]; | ||||||
|  |  	char temp_path[PATH_MAX]; | ||||||
|  |  	char buffer[64]; | ||||||
|  | -	struct stat info;
 | ||||||
|  |  	FILE *fp = NULL; | ||||||
|  |  	int parts, residue, size, ret = 0; | ||||||
|  |   | ||||||
|  |  	/* | ||||||
|  | +	 * /dev/nvme devs don't use the major:minor numbering like
 | ||||||
|  | +	 * block dev types that have their own major number, so
 | ||||||
|  | +	 * the calculation based on minor number doesn't work.
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (dev_is_nvme(dt, dev))
 | ||||||
|  | +		goto sys_partition;
 | ||||||
|  | +
 | ||||||
|  | +	/*
 | ||||||
|  |  	 * Try to get the primary dev out of the | ||||||
|  |  	 * list of known device types first. | ||||||
|  |  	 */ | ||||||
|  | @@ -576,23 +640,14 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
 | ||||||
|  |  		goto out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | + sys_partition:
 | ||||||
|  |  	/* | ||||||
|  |  	 * If we can't get the primary dev out of the list of known device | ||||||
|  |  	 * types, try to look at sysfs directly then. This is more complex | ||||||
|  |  	 * way and it also requires certain sysfs layout to be present | ||||||
|  |  	 * which might not be there in old kernels! | ||||||
|  |  	 */ | ||||||
|  | -
 | ||||||
|  | -	/* check if dev is a partition */
 | ||||||
|  | -	if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
 | ||||||
|  | -			sysfs_dir, major, minor) < 0) {
 | ||||||
|  | -		log_error("dm_snprintf partition failed");
 | ||||||
|  | -		goto out;
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	if (stat(path, &info) == -1) {
 | ||||||
|  | -		if (errno != ENOENT)
 | ||||||
|  | -			log_sys_error("stat", path);
 | ||||||
|  | +	if (!_has_sys_partition(dev)) {
 | ||||||
|  |  		*result = dev->dev; | ||||||
|  |  		ret = 1; | ||||||
|  |  		goto out; /* dev is not a partition! */ | ||||||
|  | diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
 | ||||||
|  | index fdf7791..8b94b79 100644
 | ||||||
|  | --- a/lib/device/dev-type.h
 | ||||||
|  | +++ b/lib/device/dev-type.h
 | ||||||
|  | @@ -95,6 +95,8 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev);
 | ||||||
|  |   | ||||||
|  |  int dev_is_pmem(struct device *dev); | ||||||
|  |   | ||||||
|  | +int dev_is_nvme(struct dev_types *dt, struct device *dev);
 | ||||||
|  | +
 | ||||||
|  |  int dev_is_lv(struct device *dev); | ||||||
|  |   | ||||||
|  |  int get_fs_block_size(struct device *dev, uint32_t *fs_block_size); | ||||||
|  | diff --git a/lib/device/device.h b/lib/device/device.h
 | ||||||
|  | index a58bff8..816db31 100644
 | ||||||
|  | --- a/lib/device/device.h
 | ||||||
|  | +++ b/lib/device/device.h
 | ||||||
|  | @@ -38,6 +38,7 @@
 | ||||||
|  |  #define DEV_SCAN_FOUND_LABEL	0x00010000      /* label scan read dev and found label */ | ||||||
|  |  #define DEV_IS_MD_COMPONENT	0x00020000	/* device is an md component */ | ||||||
|  |  #define DEV_UDEV_INFO_MISSING   0x00040000	/* we have no udev info for this device */ | ||||||
|  | +#define DEV_IS_NVME		0x00080000	/* set if dev is nvme */
 | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  |   * Support for external device info. | ||||||
|  | diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
 | ||||||
|  | index 85d1625..40e7df6 100644
 | ||||||
|  | --- a/lib/filters/filter-mpath.c
 | ||||||
|  | +++ b/lib/filters/filter-mpath.c
 | ||||||
|  | @@ -16,6 +16,7 @@
 | ||||||
|  |  #include "lib/misc/lib.h" | ||||||
|  |  #include "lib/filters/filter.h" | ||||||
|  |  #include "lib/activate/activate.h" | ||||||
|  | +#include "lib/commands/toolcontext.h"
 | ||||||
|  |  #ifdef UDEV_SYNC_SUPPORT | ||||||
|  |  #include <libudev.h> | ||||||
|  |  #include "lib/device/dev-ext-udev-constants.h" | ||||||
|  | @@ -27,7 +28,6 @@
 | ||||||
|  |   | ||||||
|  |  #define MPATH_PREFIX "mpath-" | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  |  struct mpath_priv { | ||||||
|  |  	struct dm_pool *mem; | ||||||
|  |  	struct dev_filter f; | ||||||
|  | @@ -35,6 +35,9 @@ struct mpath_priv {
 | ||||||
|  |  	struct dm_hash_table *hash; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * given "/dev/foo" return "foo"
 | ||||||
|  | + */
 | ||||||
|  |  static const char *_get_sysfs_name(struct device *dev) | ||||||
|  |  { | ||||||
|  |  	const char *name; | ||||||
|  | @@ -53,6 +56,11 @@ static const char *_get_sysfs_name(struct device *dev)
 | ||||||
|  |  	return name; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * given major:minor
 | ||||||
|  | + * readlink translates /sys/dev/block/major:minor to /sys/.../foo
 | ||||||
|  | + * from /sys/.../foo return "foo"
 | ||||||
|  | + */
 | ||||||
|  |  static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno, | ||||||
|  |  					  char *buf, size_t buf_size) | ||||||
|  |  { | ||||||
|  | @@ -102,27 +110,28 @@ static int _get_sysfs_string(const char *path, char *buffer, int max_size)
 | ||||||
|  |  	return r; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int _get_sysfs_get_major_minor(const char *sysfs_dir, const char *kname, int *major, int *minor)
 | ||||||
|  | +static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
 | ||||||
|  |  { | ||||||
|  | -	char path[PATH_MAX], buffer[64];
 | ||||||
|  | +	char path[PATH_MAX];
 | ||||||
|  | +	char buffer[128];
 | ||||||
|  |   | ||||||
|  | -	if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev", sysfs_dir, kname) < 0) {
 | ||||||
|  | +	if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
 | ||||||
|  |  		log_error("Sysfs path string is too long."); | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	buffer[0] = '\0';
 | ||||||
|  | +
 | ||||||
|  |  	if (!_get_sysfs_string(path, buffer, sizeof(buffer))) | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | -	if (sscanf(buffer, "%d:%d", major, minor) != 2) {
 | ||||||
|  | -		log_error("Failed to parse major minor from %s", buffer);
 | ||||||
|  | -		return 0;
 | ||||||
|  | -	}
 | ||||||
|  | +	if (!strncmp(buffer, MPATH_PREFIX, 6))
 | ||||||
|  | +		return 1;
 | ||||||
|  |   | ||||||
|  | -	return 1;
 | ||||||
|  | +	return 0;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int _get_parent_mpath(const char *dir, char *name, int max_size)
 | ||||||
|  | +static int _get_holder_name(const char *dir, char *name, int max_size)
 | ||||||
|  |  { | ||||||
|  |  	struct dirent *d; | ||||||
|  |  	DIR *dr; | ||||||
|  | @@ -155,7 +164,7 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  #ifdef UDEV_SYNC_SUPPORT | ||||||
|  | -static int _udev_dev_is_mpath(struct device *dev)
 | ||||||
|  | +static int _udev_dev_is_mpath_component(struct device *dev)
 | ||||||
|  |  { | ||||||
|  |  	const char *value; | ||||||
|  |  	struct dev_ext *ext; | ||||||
|  | @@ -174,95 +183,148 @@ static int _udev_dev_is_mpath(struct device *dev)
 | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |  #else | ||||||
|  | -static int _udev_dev_is_mpath(struct device *dev)
 | ||||||
|  | +static int _udev_dev_is_mpath_component(struct device *dev)
 | ||||||
|  |  { | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | -static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
 | ||||||
|  | +static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
 | ||||||
|  |  { | ||||||
|  |  	struct mpath_priv *mp = (struct mpath_priv *) f->private; | ||||||
|  |  	struct dev_types *dt = mp->dt; | ||||||
|  | -	const char *part_name, *name;
 | ||||||
|  | -	struct stat info;
 | ||||||
|  | -	char path[PATH_MAX], parent_name[PATH_MAX];
 | ||||||
|  | +	const char *part_name;
 | ||||||
|  | +	const char *name;               /* e.g. "sda" for "/dev/sda" */
 | ||||||
|  | +	char link_path[PATH_MAX];       /* some obscure, unpredictable sysfs path */
 | ||||||
|  | +	char holders_path[PATH_MAX];    /* e.g. "/sys/block/sda/holders/" */
 | ||||||
|  | +	char dm_dev_path[PATH_MAX];    /* e.g. "/dev/dm-1" */
 | ||||||
|  | +	char holder_name[128] = { 0 };  /* e.g. "dm-1" */
 | ||||||
|  |  	const char *sysfs_dir = dm_sysfs_dir(); | ||||||
|  | -	int major = MAJOR(dev->dev);
 | ||||||
|  | -	int minor = MINOR(dev->dev);
 | ||||||
|  | +	int dev_major = MAJOR(dev->dev);
 | ||||||
|  | +	int dev_minor = MINOR(dev->dev);
 | ||||||
|  | +	int dm_dev_major;
 | ||||||
|  | +	int dm_dev_minor;
 | ||||||
|  | +	struct stat info;
 | ||||||
|  |  	dev_t primary_dev; | ||||||
|  |  	long look; | ||||||
|  |   | ||||||
|  | -	/* Limit this filter only to SCSI devices */
 | ||||||
|  | -	if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
 | ||||||
|  | +	/* Limit this filter to SCSI or NVME devices */
 | ||||||
|  | +	if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
 | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	switch (dev_get_primary_dev(dt, dev, &primary_dev)) { | ||||||
|  | +
 | ||||||
|  |  	case 2: /* The dev is partition. */ | ||||||
|  |  		part_name = dev_name(dev); /* name of original dev for log_debug msg */ | ||||||
|  | -		if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, parent_name, sizeof(parent_name))))
 | ||||||
|  | +
 | ||||||
|  | +		/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
 | ||||||
|  | +		if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
 | ||||||
|  |  			return_0; | ||||||
|  | +
 | ||||||
|  |  		log_debug_devs("%s: Device is a partition, using primary " | ||||||
|  |  			       "device %s for mpath component detection", | ||||||
|  |  			       part_name, name); | ||||||
|  |  		break; | ||||||
|  | +
 | ||||||
|  |  	case 1: /* The dev is already a primary dev. Just continue with the dev. */ | ||||||
|  | +
 | ||||||
|  | +		/* gets "foo" for "/dev/foo" */
 | ||||||
|  |  		if (!(name = _get_sysfs_name(dev))) | ||||||
|  |  			return_0; | ||||||
|  |  		break; | ||||||
|  | +
 | ||||||
|  |  	default: /* 0, error. */ | ||||||
|  | -		log_warn("Failed to get primary device for %d:%d.", major, minor);
 | ||||||
|  | +		log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
 | ||||||
|  | +	if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
 | ||||||
|  |  		log_warn("Sysfs path to check mpath is too long."); | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	/* also will filter out partitions */ | ||||||
|  | -	if (stat(path, &info))
 | ||||||
|  | +	if (stat(holders_path, &info))
 | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  |  	if (!S_ISDIR(info.st_mode)) { | ||||||
|  | -		log_warn("Path %s is not a directory.", path);
 | ||||||
|  | +		log_warn("Path %s is not a directory.", holders_path);
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (!_get_parent_mpath(path, parent_name, sizeof(parent_name)))
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * If holders dir contains an entry such as "dm-1", then this sets
 | ||||||
|  | +	 * holder_name to "dm-1".
 | ||||||
|  | +	 *
 | ||||||
|  | +	 * If holders dir is empty, return 0 (this is generally where
 | ||||||
|  | +	 * devs that are not mpath components return.)
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
 | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  | -	if (!_get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
 | ||||||
|  | -		return_0;
 | ||||||
|  | +	if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
 | ||||||
|  | +		log_warn("dm device path to check mpath is too long.");
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  | -	if (major != dt->device_mapper_major)
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * stat "/dev/dm-1" which is the holder of the dev we're checking
 | ||||||
|  | +	 * dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (stat(dm_dev_path, &info)) {
 | ||||||
|  | +		log_debug("filter-mpath %s holder %s stat result %d",
 | ||||||
|  | +			  dev_name(dev), dm_dev_path, errno);
 | ||||||
|  |  		return 0; | ||||||
|  | +	}
 | ||||||
|  | +	dm_dev_major = (int)MAJOR(info.st_rdev);
 | ||||||
|  | +	dm_dev_minor = (int)MINOR(info.st_rdev);
 | ||||||
|  | +	
 | ||||||
|  | +	if (dm_dev_major != dt->device_mapper_major) {
 | ||||||
|  | +		log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
 | ||||||
|  | +			       dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  |   | ||||||
|  | -	/* Avoid repeated detection of multipath device and use first checked result */
 | ||||||
|  | -	look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * Save the result of checking that "/dev/dm-1" is an mpath device
 | ||||||
|  | +	 * to avoid repeating it for each path component.
 | ||||||
|  | +	 * The minor number of "/dev/dm-1" is added to the hash table with
 | ||||||
|  | +	 * const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
 | ||||||
|  | +	 * and const value 1 meaning that dm minor 1 is not a multipath dev.
 | ||||||
|  | +	 */
 | ||||||
|  | +	look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
 | ||||||
|  |  	if (look > 0) { | ||||||
|  | -		log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
 | ||||||
|  | -			       parent_name, major, minor, (look > 1) ? "" : "not ");
 | ||||||
|  | +		log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
 | ||||||
|  | +			       dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
 | ||||||
|  |  		return (look > 1) ? 1 : 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
 | ||||||
|  | -		(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
 | ||||||
|  | +	/*
 | ||||||
|  | +	 * Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
 | ||||||
|  | +	 * <holder_name> is a dm device with dm uuid prefix mpath-.
 | ||||||
|  | +	 * When true, <holder_name> will be something like "dm-1".
 | ||||||
|  | +	 *
 | ||||||
|  | +	 * (Is a hash table worth it to avoid reading one sysfs file?)
 | ||||||
|  | +	 */
 | ||||||
|  | +	if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
 | ||||||
|  | +		log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
 | ||||||
|  | +			       dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
 | ||||||
|  | +		(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
 | ||||||
|  |  		return 1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
 | ||||||
|  | +	(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
 | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
 | ||||||
|  | +static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
 | ||||||
|  |  { | ||||||
|  |  	if (dev->ext.src == DEV_EXT_NONE) | ||||||
|  | -		return _native_dev_is_mpath(f, dev);
 | ||||||
|  | +		return _native_dev_is_mpath_component(cmd, f, dev);
 | ||||||
|  |   | ||||||
|  |  	if (dev->ext.src == DEV_EXT_UDEV) | ||||||
|  | -		return _udev_dev_is_mpath(dev);
 | ||||||
|  | +		return _udev_dev_is_mpath_component(dev);
 | ||||||
|  |   | ||||||
|  |  	log_error(INTERNAL_ERROR "Missing hook for mpath recognition " | ||||||
|  |  		  "using external device info source %s", dev_ext_name(dev)); | ||||||
|  | @@ -272,11 +334,11 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
 | ||||||
|  |   | ||||||
|  |  #define MSG_SKIPPING "%s: Skipping mpath component device" | ||||||
|  |   | ||||||
|  | -static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
 | ||||||
|  | +static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
 | ||||||
|  |  { | ||||||
|  |  	dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT; | ||||||
|  |   | ||||||
|  | -	if (_dev_is_mpath(f, dev) == 1) {
 | ||||||
|  | +	if (_dev_is_mpath_component(cmd, f, dev) == 1) {
 | ||||||
|  |  		if (dev->ext.src == DEV_EXT_NONE) | ||||||
|  |  			log_debug_devs(MSG_SKIPPING, dev_name(dev)); | ||||||
|  |  		else | ||||||
|  | @@ -303,8 +365,8 @@ static void _destroy(struct dev_filter *f)
 | ||||||
|  |  struct dev_filter *mpath_filter_create(struct dev_types *dt) | ||||||
|  |  { | ||||||
|  |  	const char *sysfs_dir = dm_sysfs_dir(); | ||||||
|  | -	struct dm_pool *mem;
 | ||||||
|  |  	struct mpath_priv *mp; | ||||||
|  | +	struct dm_pool *mem;
 | ||||||
|  |  	struct dm_hash_table *hash; | ||||||
|  |   | ||||||
|  |  	if (!*sysfs_dir) { | ||||||
|  | @@ -328,19 +390,13 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
 | ||||||
|  |  		goto bad; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
 | ||||||
|  | -		log_error("mpath filter allocation failed.");
 | ||||||
|  | -		goto bad;
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	mp->f.passes_filter = _ignore_mpath;
 | ||||||
|  | +	mp->f.passes_filter = _ignore_mpath_component;
 | ||||||
|  |  	mp->f.destroy = _destroy; | ||||||
|  |  	mp->f.use_count = 0; | ||||||
|  |  	mp->f.private = mp; | ||||||
|  |  	mp->f.name = "mpath"; | ||||||
|  | -
 | ||||||
|  | -	mp->mem = mem;
 | ||||||
|  |  	mp->dt = dt; | ||||||
|  | +	mp->mem = mem;
 | ||||||
|  |  	mp->hash = hash; | ||||||
|  |   | ||||||
|  |  	log_debug_devs("mpath filter initialised."); | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  |  lib/metadata/integrity_manip.c | 10 +++++++--- | ||||||
|  |  1 file changed, 7 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/metadata/integrity_manip.c b/lib/metadata/integrity_manip.c
 | ||||||
|  | index 53ab1b3..abf90d8 100644
 | ||||||
|  | --- a/lib/metadata/integrity_manip.c
 | ||||||
|  | +++ b/lib/metadata/integrity_manip.c
 | ||||||
|  | @@ -773,9 +773,13 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting
 | ||||||
|  |  bad: | ||||||
|  |  	log_error("Failed to add integrity."); | ||||||
|  |   | ||||||
|  | -	for (s = 0; s < revert_meta_lvs; s++) {
 | ||||||
|  | -		if (!lv_remove(imeta_lvs[s]))
 | ||||||
|  | -			log_error("New integrity metadata LV may require manual removal.");
 | ||||||
|  | +	if (revert_meta_lvs) {
 | ||||||
|  | +		for (s = 0; s < DEFAULT_RAID_MAX_IMAGES; s++) {
 | ||||||
|  | +			if (!imeta_lvs[s])
 | ||||||
|  | +				continue;
 | ||||||
|  | +			if (!lv_remove(imeta_lvs[s]))
 | ||||||
|  | +				log_error("New integrity metadata LV may require manual removal.");
 | ||||||
|  | +		}
 | ||||||
|  |  	} | ||||||
|  |  			        | ||||||
|  |  	if (!vg_write(vg) || !vg_commit(vg)) | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  |  lib/label/label.c | 5 +++++ | ||||||
|  |  1 file changed, 5 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/label/label.c b/lib/label/label.c
 | ||||||
|  | index e067a6b..e6dd4a1 100644
 | ||||||
|  | --- a/lib/label/label.c
 | ||||||
|  | +++ b/lib/label/label.c
 | ||||||
|  | @@ -1243,6 +1243,11 @@ int label_scan(struct cmd_context *cmd)
 | ||||||
|  |  		free(devl); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	dm_list_iterate_items_safe(devl, devl2, &filtered_devs) {
 | ||||||
|  | +		dm_list_del(&devl->list);
 | ||||||
|  | +		free(devl);
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	/* | ||||||
|  |  	 * If hints were not available/usable, then we scanned all devs, | ||||||
|  |  	 * and we now know which are PVs.  Save this list of PVs we've | ||||||
							
								
								
									
										66
									
								
								lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  |  WHATS_NEW               | 4 ++++ | ||||||
|  |  lib/activate/activate.c | 5 +++++ | ||||||
|  |  lib/activate/activate.h | 2 ++ | ||||||
|  |  lib/metadata/lv_manip.c | 6 ++++++ | ||||||
|  |  4 files changed, 17 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/WHATS_NEW b/WHATS_NEW
 | ||||||
|  | index 3953c7e..c8f869c 100644
 | ||||||
|  | --- a/WHATS_NEW
 | ||||||
|  | +++ b/WHATS_NEW
 | ||||||
|  | @@ -1,5 +1,9 @@
 | ||||||
|  |  Version 2.03.12 -  | ||||||
|  |  =================================== | ||||||
|  | +  Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
 | ||||||
|  | +  Limit pool metadata spare to 16GiB.
 | ||||||
|  | +  Improves conversion and allocation of pool metadata.
 | ||||||
|  | +  Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
 | ||||||
|  |    Fix problem with wiping of converted LVs. | ||||||
|  |    Fix memleak in scanning  (2.03.11). | ||||||
|  |    Fix corner case allocation for thin-pools. | ||||||
|  | diff --git a/lib/activate/activate.c b/lib/activate/activate.c
 | ||||||
|  | index 7ed6441..de866fb 100644
 | ||||||
|  | --- a/lib/activate/activate.c
 | ||||||
|  | +++ b/lib/activate/activate.c
 | ||||||
|  | @@ -466,6 +466,11 @@ static int _passes_readonly_filter(struct cmd_context *cmd,
 | ||||||
|  |  	return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int lv_passes_readonly_filter(const struct logical_volume *lv)
 | ||||||
|  | +{
 | ||||||
|  | +	return _passes_readonly_filter(lv->vg->cmd, lv);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int library_version(char *version, size_t size) | ||||||
|  |  { | ||||||
|  |  	if (!activation()) | ||||||
|  | diff --git a/lib/activate/activate.h b/lib/activate/activate.h
 | ||||||
|  | index 3f4d128..53c8631 100644
 | ||||||
|  | --- a/lib/activate/activate.h
 | ||||||
|  | +++ b/lib/activate/activate.h
 | ||||||
|  | @@ -208,6 +208,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
 | ||||||
|  |   | ||||||
|  |  int lv_is_active(const struct logical_volume *lv); | ||||||
|  |   | ||||||
|  | +int lv_passes_readonly_filter(const struct logical_volume *lv);
 | ||||||
|  | +
 | ||||||
|  |  /* Check is any component LV is active */ | ||||||
|  |  const struct logical_volume *lv_component_is_active(const struct logical_volume *lv); | ||||||
|  |  const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv); | ||||||
|  | diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
 | ||||||
|  | index 445c4ad..5ff64a3 100644
 | ||||||
|  | --- a/lib/metadata/lv_manip.c
 | ||||||
|  | +++ b/lib/metadata/lv_manip.c
 | ||||||
|  | @@ -7976,6 +7976,12 @@ static int _should_wipe_lv(struct lvcreate_params *lp,
 | ||||||
|  |  	     first_seg(first_seg(lv)->pool_lv)->zero_new_blocks)) | ||||||
|  |  		return 0; | ||||||
|  |   | ||||||
|  | +	if (warn && (lv_passes_readonly_filter(lv))) {
 | ||||||
|  | +		log_warn("WARNING: Read-only activated logical volume %s not zeroed.",
 | ||||||
|  | +			 display_lvname(lv));
 | ||||||
|  | +		return 0;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	/* Cannot zero read-only volume */ | ||||||
|  |  	if ((lv->status & LVM_WRITE) && | ||||||
|  |  	    (lp->zero || lp->wipe_signatures)) | ||||||
							
								
								
									
										29
									
								
								lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  |  daemons/lvmlockd/lvmlockd-core.c | 6 ++++-- | ||||||
|  |  1 file changed, 4 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
 | ||||||
|  | index fea8ee6..c4abf66 100644
 | ||||||
|  | --- a/daemons/lvmlockd/lvmlockd-core.c
 | ||||||
|  | +++ b/daemons/lvmlockd/lvmlockd-core.c
 | ||||||
|  | @@ -896,8 +896,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
 | ||||||
|  |  				goto fail; | ||||||
|  |   | ||||||
|  |  			memset(vg_uuid, 0, sizeof(vg_uuid)); | ||||||
|  | +			memset(lm_type_str, 0, sizeof(lm_type_str));
 | ||||||
|  |   | ||||||
|  | -			if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
 | ||||||
|  | +			if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
 | ||||||
|  |  				   vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) { | ||||||
|  |  				goto fail; | ||||||
|  |  			} | ||||||
|  | @@ -916,8 +917,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
 | ||||||
|  |  			r->type = LD_RT_LV; | ||||||
|  |   | ||||||
|  |  			memset(vg_uuid, 0, sizeof(vg_uuid)); | ||||||
|  | +			memset(mode, 0, sizeof(mode));
 | ||||||
|  |   | ||||||
|  | -			if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
 | ||||||
|  | +			if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
 | ||||||
|  |  				   vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) { | ||||||
|  |  				goto fail; | ||||||
|  |  			} | ||||||
							
								
								
									
										18
									
								
								lvm2-2_03_12-make-generate.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lvm2-2_03_12-make-generate.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  |  man/lvconvert.8_pregen | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/man/lvconvert.8_pregen b/man/lvconvert.8_pregen
 | ||||||
|  | index a47ccac..170eec8 100644
 | ||||||
|  | --- a/man/lvconvert.8_pregen
 | ||||||
|  | +++ b/man/lvconvert.8_pregen
 | ||||||
|  | @@ -772,6 +772,10 @@ Add a cache to an LV, using a specified cache device.
 | ||||||
|  |  .br | ||||||
|  |  .RS 4 | ||||||
|  |  .ad l | ||||||
|  | +[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
 | ||||||
|  | +.ad b
 | ||||||
|  | +.br
 | ||||||
|  | +.ad l
 | ||||||
|  |  [    \fB--cachesize\fP \fISize\fP[m|UNIT] ] | ||||||
|  |  .ad b | ||||||
|  |  .br | ||||||
							
								
								
									
										86
									
								
								lvm2-2_03_12-man-update-lvmthin.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								lvm2-2_03_12-man-update-lvmthin.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  |  man/lvmthin.7_main | 37 +++++++++++++++++++++++++------------ | ||||||
|  |  1 file changed, 25 insertions(+), 12 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
 | ||||||
|  | index ce23431..e6f1d63 100644
 | ||||||
|  | --- a/man/lvmthin.7_main
 | ||||||
|  | +++ b/man/lvmthin.7_main
 | ||||||
|  | @@ -394,7 +394,7 @@ the pmspare LV.
 | ||||||
|  |  \& | ||||||
|  |   | ||||||
|  |  If thin pool metadata is damaged, it may be repairable. | ||||||
|  | -Checking and repairing thin pool metadata is analagous to
 | ||||||
|  | +Checking and repairing thin pool metadata is analogous to
 | ||||||
|  |  running fsck/repair on a file system. | ||||||
|  |   | ||||||
|  |  When a thin pool LV is activated, lvm runs the thin_check command | ||||||
|  | @@ -437,14 +437,24 @@ copy to the VG's pmspare LV.
 | ||||||
|  |  If step 1 is successful, the thin pool metadata LV is replaced | ||||||
|  |  with the pmspare LV containing the corrected metadata. | ||||||
|  |  The previous thin pool metadata LV, containing the damaged metadata, | ||||||
|  | -becomes visible with the new name ThinPoolLV_tmetaN (where N is 0,1,...).
 | ||||||
|  | -
 | ||||||
|  | -If the repair works, the thin pool LV and its thin LVs can be activated,
 | ||||||
|  | -and the LV containing the damaged thin pool metadata can be removed.
 | ||||||
|  | -It may be useful to move the new metadata LV (previously pmspare) to a
 | ||||||
|  | -better PV.
 | ||||||
|  | -
 | ||||||
|  | -If the repair does not work, the thin pool LV and its thin LVs are lost.
 | ||||||
|  | +becomes visible with the new name ThinPoolLV_metaN (where N is 0,1,...).
 | ||||||
|  | +
 | ||||||
|  | +If the repair works, the thin pool LV and its thin LVs can be activated.
 | ||||||
|  | +User should manually check if repaired thin pool kernel metadata
 | ||||||
|  | +has all data for all lvm2 known LVs by individual activation of
 | ||||||
|  | +every thin LV. When all works, user should continue with fsck of
 | ||||||
|  | +all filesystems present these such volumes.
 | ||||||
|  | +Once the thin pool is considered fully functional user may remove ThinPoolLV_metaN
 | ||||||
|  | +(the LV containing the damaged thin pool metadata) for possible
 | ||||||
|  | +space reuse.
 | ||||||
|  | +For a better performance it may be useful to pvmove the new repaired metadata LV
 | ||||||
|  | +(written to previous pmspare volume) to a better PV (i.e. SSD)
 | ||||||
|  | +
 | ||||||
|  | +If the repair operation fails, the thin pool LV and its thin LVs
 | ||||||
|  | +are not accessible and it may be necessary to restore their content
 | ||||||
|  | +from a backup.  In such case the content of unmodified original damaged
 | ||||||
|  | +ThinPoolLV_metaN volume can be used by your support for more
 | ||||||
|  | +advanced recovery methods.
 | ||||||
|  |   | ||||||
|  |  If metadata is manually restored with thin_repair directly, | ||||||
|  |  the pool metadata LV can be manually swapped with another LV | ||||||
|  | @@ -452,6 +462,9 @@ containing new metadata:
 | ||||||
|  |   | ||||||
|  |  .B lvconvert --thinpool VG/ThinPoolLV --poolmetadata VG/NewThinMetaLV | ||||||
|  |   | ||||||
|  | +Note: Thin pool metadata is compact so even small corruptions
 | ||||||
|  | +in them may result in significant portions of mappings to be lost.
 | ||||||
|  | +It is recommended to use fast resilient storage for them.
 | ||||||
|  |   | ||||||
|  |  .SS Activation of thin snapshots | ||||||
|  |   | ||||||
|  | @@ -549,7 +562,7 @@ Command to extend thin pool data space:
 | ||||||
|  |  .fi | ||||||
|  |   | ||||||
|  |  Other methods of increasing free data space in a thin pool LV | ||||||
|  | -include removing a thin LV and its related snapsots, or running
 | ||||||
|  | +include removing a thin LV and its related snapshots, or running
 | ||||||
|  |  fstrim on the file system using a thin LV. | ||||||
|  |   | ||||||
|  |   | ||||||
|  | @@ -689,7 +702,7 @@ with two configuration settings:
 | ||||||
|  |  .B thin_pool_autoextend_threshold | ||||||
|  |  .br | ||||||
|  |  is a percentage full value that defines when the thin pool LV should be | ||||||
|  | -extended.  Setting this to 100 disables automatic extention.  The minimum
 | ||||||
|  | +extended.  Setting this to 100 disables automatic extension.  The minimum
 | ||||||
|  |  value is 50. | ||||||
|  |   | ||||||
|  |  .BR lvm.conf (5) | ||||||
|  | @@ -716,7 +729,7 @@ the --ignoremonitoring option can be used.  With this option, the command
 | ||||||
|  |  will not ask dmeventd to monitor the thin pool LV. | ||||||
|  |   | ||||||
|  |  .IP \[bu] | ||||||
|  | -Setting thin_pool_autoextend_threshould to 100 disables automatic
 | ||||||
|  | +Setting thin_pool_autoextend_threshold to 100 disables automatic
 | ||||||
|  |  extension of thin pool LVs, even if they are being monitored by dmeventd. | ||||||
|  |   | ||||||
|  |  .P | ||||||
							
								
								
									
										39
									
								
								lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  |  lib/metadata/pool_manip.c | 10 +++++++++- | ||||||
|  |  1 file changed, 9 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
 | ||||||
|  | index b67882e..1975cb4 100644
 | ||||||
|  | --- a/lib/metadata/pool_manip.c
 | ||||||
|  | +++ b/lib/metadata/pool_manip.c
 | ||||||
|  | @@ -697,6 +697,8 @@ static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg
 | ||||||
|  |  int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents, | ||||||
|  |  			       struct dm_list *pvh, int poolmetadataspare) | ||||||
|  |  { | ||||||
|  | +	/* Max usable size of any spare volume is currently 16GiB rouned to extent size */
 | ||||||
|  | +	const uint64_t MAX_SIZE = (UINT64_C(2 * 16) * 1024 * 1024 + vg->extent_size - 1) / vg->extent_size;
 | ||||||
|  |  	struct logical_volume *lv = vg->pool_metadata_spare_lv; | ||||||
|  |  	uint32_t seg_mirrors; | ||||||
|  |  	struct lv_segment *seg; | ||||||
|  | @@ -706,8 +708,11 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
 | ||||||
|  |  		/* Find maximal size of metadata LV */ | ||||||
|  |  		dm_list_iterate_items(lvl, &vg->lvs) | ||||||
|  |  			if (lv_is_pool_metadata(lvl->lv) && | ||||||
|  | -			    (lvl->lv->le_count > extents))
 | ||||||
|  | +			    (lvl->lv->le_count > extents)) {
 | ||||||
|  |  				extents = lvl->lv->le_count; | ||||||
|  | +				if (extents >= MAX_SIZE)
 | ||||||
|  | +					break;
 | ||||||
|  | +			}
 | ||||||
|  |   | ||||||
|  |  	if (!poolmetadataspare) { | ||||||
|  |  		/* TODO: Not showing when lvm.conf would define 'n' ? */ | ||||||
|  | @@ -718,6 +723,9 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
 | ||||||
|  |  		return 1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (extents > MAX_SIZE)
 | ||||||
|  | +		extents = MAX_SIZE;
 | ||||||
|  | +
 | ||||||
|  |  	if (!lv) { | ||||||
|  |  		if (!_alloc_pool_metadata_spare(vg, extents, pvh)) | ||||||
|  |  			return_0; | ||||||
							
								
								
									
										92
									
								
								lvm2-2_03_12-pools-fix-removal-of-spare-volume.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								lvm2-2_03_12-pools-fix-removal-of-spare-volume.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  |  lib/metadata/lv_manip.c | 48 ++++++++++++++++++++++++------------------------ | ||||||
|  |  1 file changed, 24 insertions(+), 24 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
 | ||||||
|  | index 443d32c..c740ba2 100644
 | ||||||
|  | --- a/lib/metadata/lv_manip.c
 | ||||||
|  | +++ b/lib/metadata/lv_manip.c
 | ||||||
|  | @@ -1470,6 +1470,8 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
 | ||||||
|  |  	struct logical_volume *external_lv = NULL; | ||||||
|  |  	int is_raid10 = 0; | ||||||
|  |  	uint32_t data_copies = 0; | ||||||
|  | +	struct lv_list *lvl;
 | ||||||
|  | +	int is_last_pool = lv_is_pool(lv);
 | ||||||
|  |   | ||||||
|  |  	if (!dm_list_empty(&lv->segments)) { | ||||||
|  |  		seg = first_seg(lv); | ||||||
|  | @@ -1581,6 +1583,28 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
 | ||||||
|  |  	    !lv_update_and_reload(external_lv)) | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | +	/* When removing last pool, automatically drop the spare volume */
 | ||||||
|  | +	if (is_last_pool && lv->vg->pool_metadata_spare_lv) {
 | ||||||
|  | +		/* TODO: maybe use a list of pools or a counter to avoid linear search through VG */
 | ||||||
|  | +		dm_list_iterate_items(lvl, &lv->vg->lvs)
 | ||||||
|  | +			if (lv_is_thin_type(lvl->lv) ||
 | ||||||
|  | +			    lv_is_cache_type(lvl->lv)) {
 | ||||||
|  | +				is_last_pool = 0;
 | ||||||
|  | +				break;
 | ||||||
|  | +			}
 | ||||||
|  | +
 | ||||||
|  | +		if (is_last_pool) {
 | ||||||
|  | +			/* This is purely internal LV volume, no question */
 | ||||||
|  | +			if (!deactivate_lv(lv->vg->cmd, lv->vg->pool_metadata_spare_lv)) {
 | ||||||
|  | +				log_error("Unable to deactivate spare logical volume %s.",
 | ||||||
|  | +					  display_lvname(lv->vg->pool_metadata_spare_lv));
 | ||||||
|  | +				return 0;
 | ||||||
|  | +			}
 | ||||||
|  | +			if (!lv_remove(lv->vg->pool_metadata_spare_lv))
 | ||||||
|  | +				return_0;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -6433,10 +6457,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | ||||||
|  |  	struct logical_volume *lock_lv = lv; | ||||||
|  |  	struct lv_segment *cache_seg = NULL; | ||||||
|  |  	int ask_discard; | ||||||
|  | -	struct lv_list *lvl;
 | ||||||
|  |  	struct seg_list *sl; | ||||||
|  |  	struct lv_segment *seg = first_seg(lv); | ||||||
|  | -	int is_last_pool = lv_is_pool(lv);
 | ||||||
|  |   | ||||||
|  |  	vg = lv->vg; | ||||||
|  |   | ||||||
|  | @@ -6558,9 +6580,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | ||||||
|  |  		 */ | ||||||
|  |  		struct logical_volume *cachevol_lv = first_seg(lv)->pool_lv; | ||||||
|  |   | ||||||
|  | -		if (lv_is_cache_pool(cachevol_lv))
 | ||||||
|  | -			is_last_pool = 1;
 | ||||||
|  | -
 | ||||||
|  |  		if (!archive(vg)) | ||||||
|  |  			return_0; | ||||||
|  |   | ||||||
|  | @@ -6667,25 +6686,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (is_last_pool && vg->pool_metadata_spare_lv) {
 | ||||||
|  | -		/* When removed last pool, also remove the spare */
 | ||||||
|  | -		dm_list_iterate_items(lvl, &vg->lvs)
 | ||||||
|  | -			if (lv_is_pool_metadata(lvl->lv)) {
 | ||||||
|  | -				is_last_pool = 0;
 | ||||||
|  | -				break;
 | ||||||
|  | -			}
 | ||||||
|  | -		if (is_last_pool) {
 | ||||||
|  | -			/* This is purely internal LV volume, no question */
 | ||||||
|  | -			if (!deactivate_lv(cmd, vg->pool_metadata_spare_lv)) {
 | ||||||
|  | -				log_error("Unable to deactivate spare logical volume %s.",
 | ||||||
|  | -					  display_lvname(vg->pool_metadata_spare_lv));
 | ||||||
|  | -				return 0;
 | ||||||
|  | -			}
 | ||||||
|  | -			if (!lv_remove(vg->pool_metadata_spare_lv))
 | ||||||
|  | -				return_0;
 | ||||||
|  | -		}
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  |  	/* store it on disks */ | ||||||
|  |  	if (!vg_write(vg) || !vg_commit(vg)) | ||||||
|  |  		return_0; | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  |  tools/pvck.c | 10 +++++++--- | ||||||
|  |  1 file changed, 7 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/tools/pvck.c b/tools/pvck.c
 | ||||||
|  | index c36e182..88350de 100644
 | ||||||
|  | --- a/tools/pvck.c
 | ||||||
|  | +++ b/tools/pvck.c
 | ||||||
|  | @@ -1140,9 +1140,13 @@ static int _dump_label_and_pv_header(struct cmd_context *cmd, uint64_t labelsect
 | ||||||
|  |  			*mda1_offset = xlate64(dlocn->offset); | ||||||
|  |  			*mda1_size = xlate64(dlocn->size); | ||||||
|  |   | ||||||
|  | -			if (*mda1_offset != 4096) {
 | ||||||
|  | -				log_print("CHECK: pv_header.disk_locn[%d].offset expected 4096 # for first mda", di);
 | ||||||
|  | -				bad++;
 | ||||||
|  | +			/*
 | ||||||
|  | +			 * mda1 offset is page size from machine that created it,
 | ||||||
|  | +			 * warn if it's not one of the expected page sizes.
 | ||||||
|  | +			 */
 | ||||||
|  | +			if ((*mda1_offset != 4096) && (*mda1_offset != 8192) && (*mda1_offset != 65536)) {
 | ||||||
|  | +				log_print("WARNING: pv_header.disk_locn[%d].offset %llu is unexpected # for first mda",
 | ||||||
|  | +					  di, (unsigned long long)*mda1_offset);
 | ||||||
|  |  			} | ||||||
|  |  		} else { | ||||||
|  |  			*mda2_offset = xlate64(dlocn->offset); | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  |  test/shell/tags.sh | 5 +++++ | ||||||
|  |  1 file changed, 5 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/tags.sh b/test/shell/tags.sh
 | ||||||
|  | index fd1b332..5b636a8 100644
 | ||||||
|  | --- a/test/shell/tags.sh
 | ||||||
|  | +++ b/test/shell/tags.sh
 | ||||||
|  | @@ -52,6 +52,11 @@ check lv_field @firstlvtag1 tags "firstlvtag1"
 | ||||||
|  |  not check lv_field @secondlvtag1 tags "firstlvtag1" | ||||||
|  |  check lv_field $vg1/$lv2 tags "secondlvtag1" | ||||||
|  |  not check lv_field $vg1/$lv1 tags "secondlvtag1" | ||||||
|  | +
 | ||||||
|  | +# LV is not zeroed when tag matches read only volume list
 | ||||||
|  | +lvcreate -l1 $vg1 --addtag "RO" --config "activation/read_only_volume_list = [ \"@RO\" ]" 2>&1 | tee out
 | ||||||
|  | +grep "not zeroed" out
 | ||||||
|  | +
 | ||||||
|  |  vgremove -f $vg1 | ||||||
|  |   | ||||||
|  |  # lvchange with --addtag and --deltag | ||||||
							
								
								
									
										98
									
								
								lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  |  test/shell/thin-16g.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 88 insertions(+) | ||||||
|  |  create mode 100644 test/shell/thin-16g.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/thin-16g.sh b/test/shell/thin-16g.sh
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..ee7e22e
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/shell/thin-16g.sh
 | ||||||
|  | @@ -0,0 +1,88 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +
 | ||||||
|  | +# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
 | ||||||
|  | +#
 | ||||||
|  | +# This copyrighted material is made available to anyone wishing to use,
 | ||||||
|  | +# modify, copy, or redistribute it subject to the terms and conditions
 | ||||||
|  | +# of the GNU General Public License v.2.
 | ||||||
|  | +#
 | ||||||
|  | +# You should have received a copy of the GNU General Public License
 | ||||||
|  | +# along with this program; if not, write to the Free Software Foundation,
 | ||||||
|  | +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | ||||||
|  | +
 | ||||||
|  | +# Test usability of 16g thin pool metadata  LV
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +SKIP_WITH_LVMPOLLD=1
 | ||||||
|  | +
 | ||||||
|  | +. lib/inittest
 | ||||||
|  | +
 | ||||||
|  | +aux have_thin 1 0 0 || skip
 | ||||||
|  | +
 | ||||||
|  | +aux prepare_vg 1 50000
 | ||||||
|  | +
 | ||||||
|  | +lvcreate -T -L10 --poolmetadatasize 16g $vg/pool
 | ||||||
|  | +check lv_field $vg/pool_tmeta size "<15.88g"
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +# Cropped way
 | ||||||
|  | +lvcreate -T -L10 --poolmetadatasize 16g --config 'allocation/thin_pool_crop_metadata=1' $vg/pool
 | ||||||
|  | +check lv_field $vg/pool_tmeta size "15.81g"
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +lvcreate -L16G -n meta $vg
 | ||||||
|  | +lvcreate -L10  -n pool $vg
 | ||||||
|  | +lvconvert --yes --thinpool $vg/pool --poolmetadata meta
 | ||||||
|  | +# Uncropped size 33554432 sectors - 16GiB
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33554432
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +# Uses 20G metadata volume, but crops the size in DM table
 | ||||||
|  | +lvcreate -L20G -n meta $vg
 | ||||||
|  | +lvcreate -L10  -n pool $vg
 | ||||||
|  | +lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
 | ||||||
|  | +check lv_field $vg/lvol0_pmspare size "16.00g"
 | ||||||
|  | +# Size should be cropped to 33161216 sectors  ~15.81GiB
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33161216
 | ||||||
|  | +
 | ||||||
|  | +# Also size remains unchanged with activation has no cropping,
 | ||||||
|  | +# but metadata have no CROP_METADATA flag set
 | ||||||
|  | +lvchange -an $vg
 | ||||||
|  | +lvchange -ay $vg
 | ||||||
|  | +# Size still stays cropped to 33161216 sectors  ~15.81GiB
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33161216
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +# Minimal size is 2M
 | ||||||
|  | +lvcreate -L1M -n meta $vg
 | ||||||
|  | +lvcreate -L10 -n pool $vg
 | ||||||
|  | +not lvconvert --yes --thinpool $vg/pool --poolmetadata meta
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +# Uses 20G metadata volume, but crops the size in DM table
 | ||||||
|  | +lvcreate -L1 --poolmetadatasize 10G -T $vg/pool
 | ||||||
|  | +lvresize -L+10G $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
 | ||||||
|  | +check lv_field $vg/lvol0_pmspare size "15.81g"
 | ||||||
|  | +# Size should be cropped to 33161216 sectors  ~15.81GiB
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33161216
 | ||||||
|  | +
 | ||||||
|  | +# Without cropping we can grop to ~15.88GiB
 | ||||||
|  | +lvresize -L+10G $vg/pool_tmeta
 | ||||||
|  | +check lv_field $vg/lvol0_pmspare size "<15.88g"
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +# User has already 'bigger' metadata and wants them uncropped
 | ||||||
|  | +lvcreate -L16G -n meta $vg
 | ||||||
|  | +lvcreate -L10  -n pool $vg
 | ||||||
|  | +lvconvert --yes --thinpool $vg/pool --poolmetadata meta --config 'allocation/thin_pool_crop_metadata=1'
 | ||||||
|  | +
 | ||||||
|  | +# No change with cropping
 | ||||||
|  | +lvresize -l+1 $vg/pool_tmeta --config 'allocation/thin_pool_crop_metadata=1'
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33161216
 | ||||||
|  | +
 | ||||||
|  | +# Resizes to 'uncropped' size 16GiB with ANY size
 | ||||||
|  | +lvresize -l+1 $vg/pool_tmeta
 | ||||||
|  | +dmsetup table ${vg}-pool_tmeta | grep 33554432
 | ||||||
|  | +check lv_field $vg/pool_tmeta size "16.00g"
 | ||||||
|  | +
 | ||||||
|  | +vgremove -ff $vg
 | ||||||
| @ -0,0 +1,78 @@ | |||||||
|  |  test/shell/thin-zero-meta.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 68 insertions(+) | ||||||
|  |  create mode 100644 test/shell/thin-zero-meta.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/thin-zero-meta.sh b/test/shell/thin-zero-meta.sh
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..6a15a73
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/shell/thin-zero-meta.sh
 | ||||||
|  | @@ -0,0 +1,68 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +
 | ||||||
|  | +# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
 | ||||||
|  | +#
 | ||||||
|  | +# This copyrighted material is made available to anyone wishing to use,
 | ||||||
|  | +# modify, copy, or redistribute it subject to the terms and conditions
 | ||||||
|  | +# of the GNU General Public License v.2.
 | ||||||
|  | +#
 | ||||||
|  | +# You should have received a copy of the GNU General Public License
 | ||||||
|  | +# along with this program; if not, write to the Free Software Foundation,
 | ||||||
|  | +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | ||||||
|  | +
 | ||||||
|  | +# Test how zeroing of thin-pool metadata works
 | ||||||
|  | +
 | ||||||
|  | +SKIP_WITH_LVMLOCKD=1
 | ||||||
|  | +SKIP_WITH_LVMPOLLD=1
 | ||||||
|  | +
 | ||||||
|  | +export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
 | ||||||
|  | +
 | ||||||
|  | +. lib/inittest
 | ||||||
|  | +
 | ||||||
|  | +#
 | ||||||
|  | +# Main
 | ||||||
|  | +#
 | ||||||
|  | +aux have_thin 1 3 0 || skip
 | ||||||
|  | +aux have_cache 1 3 0 || skip
 | ||||||
|  | +
 | ||||||
|  | +aux prepare_vg 3 40000
 | ||||||
|  | +
 | ||||||
|  | +# Create mostly-zero devs only front of it has some 'real' back-end
 | ||||||
|  | +aux zero_dev "$dev1" "$(( $(get first_extent_sector "$dev1") + 8192 )):"
 | ||||||
|  | +aux zero_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 8192 )):"
 | ||||||
|  | +aux zero_dev "$dev3" "$(( $(get first_extent_sector "$dev3") + 8192 )):"
 | ||||||
|  | +
 | ||||||
|  | +# Prepare randomly filled 4M LV on dev2
 | ||||||
|  | +lvcreate -L16G -n $lv1 $vg "$dev2"
 | ||||||
|  | +dd if=/dev/urandom of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=4 oflag=direct  || true
 | ||||||
|  | +lvremove -f $vg
 | ||||||
|  | +
 | ||||||
|  | +for i in 0 1
 | ||||||
|  | +do
 | ||||||
|  | +	aux lvmconf "allocation/zero_metadata = $i"
 | ||||||
|  | +
 | ||||||
|  | +	# Lvm2 should allocate metadata on dev2
 | ||||||
|  | +	lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2"
 | ||||||
|  | +	lvchange -an $vg
 | ||||||
|  | +
 | ||||||
|  | +	lvs -ao+seg_pe_ranges $vg
 | ||||||
|  | +	lvchange -ay $vg/pool_tmeta --yes
 | ||||||
|  | +
 | ||||||
|  | +	# Skip past 1.2M which is 'created' by  thin-pool initialization
 | ||||||
|  | +	hexdump -C -n 200 -s 2000000 "$DM_DEV_DIR/$vg/pool_tmeta" | tee out
 | ||||||
|  | +
 | ||||||
|  | +	# When fully zeroed, it should be zero - so almost no output from hexdump
 | ||||||
|  | +	case "$i" in
 | ||||||
|  | +	0) test $(wc -l < out) -ge 10 ;; # should not be zeroed
 | ||||||
|  | +	1) test $(wc -l < out) -le 10 ;; # should be zeroed
 | ||||||
|  | +	esac
 | ||||||
|  | +
 | ||||||
|  | +	lvremove -f $vg/pool
 | ||||||
|  | +done
 | ||||||
|  | +
 | ||||||
|  | +# Check lvm2 spots error during full zeroing of metadata device
 | ||||||
|  | +aux error_dev "$dev2" "$(( $(get first_extent_sector "$dev2") + 32 )):"
 | ||||||
|  | +not lvcreate -T -L10G --poolmetadatasize 16G $vg/pool "$dev1" "$dev2" |& tee err
 | ||||||
|  | +grep "Failed to initialize logical volume" err
 | ||||||
|  | +
 | ||||||
|  | +vgremove -ff $vg
 | ||||||
							
								
								
									
										128
									
								
								lvm2-2_03_12-tests-check-support-for-online-vdo-rename.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								lvm2-2_03_12-tests-check-support-for-online-vdo-rename.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | |||||||
|  |  test/shell/lvcreate-vdo-cache.sh | 17 +------- | ||||||
|  |  test/shell/lvrename-vdo.sh       | 88 ++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  2 files changed, 90 insertions(+), 15 deletions(-) | ||||||
|  |  create mode 100644 test/shell/lvrename-vdo.sh | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/lvcreate-vdo-cache.sh b/test/shell/lvcreate-vdo-cache.sh
 | ||||||
|  | index c31cccc..6cf8437 100644
 | ||||||
|  | --- a/test/shell/lvcreate-vdo-cache.sh
 | ||||||
|  | +++ b/test/shell/lvcreate-vdo-cache.sh
 | ||||||
|  | @@ -32,22 +32,9 @@ export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
 | ||||||
|  |   | ||||||
|  |  aux prepare_vg 1 9000 | ||||||
|  |   | ||||||
|  | -lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
 | ||||||
|  | -
 | ||||||
|  | +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool
 | ||||||
|  |  # Test caching VDOPoolLV | ||||||
|  | -lvcreate -H -L10 $vg/vpool1
 | ||||||
|  | -
 | ||||||
|  | -# Current VDO target driver cannot handle online rename
 | ||||||
|  | -# once this will be supported - update this test
 | ||||||
|  | -not lvrename $vg/vpool1 $vg/vpool 2>&1 | tee out
 | ||||||
|  | -grep "Cannot rename" out
 | ||||||
|  | -
 | ||||||
|  | -lvchange -an $vg
 | ||||||
|  | -
 | ||||||
|  | -# Ofline should work
 | ||||||
|  | -lvrename $vg/vpool1 $vg/vpool
 | ||||||
|  | -
 | ||||||
|  | -lvchange -ay $vg
 | ||||||
|  | +lvcreate -H -L10 $vg/vpool
 | ||||||
|  |   | ||||||
|  |  mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1" | ||||||
|  |   | ||||||
|  | diff --git a/test/shell/lvrename-vdo.sh b/test/shell/lvrename-vdo.sh
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..1417d9f
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/test/shell/lvrename-vdo.sh
 | ||||||
|  | @@ -0,0 +1,88 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +
 | ||||||
|  | +# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
 | ||||||
|  | +#
 | ||||||
|  | +# This copyrighted material is made available to anyone wishing to use,
 | ||||||
|  | +# modify, copy, or redistribute it subject to the terms and conditions
 | ||||||
|  | +# of the GNU General Public License v.2.
 | ||||||
|  | +#
 | ||||||
|  | +# You should have received a copy of the GNU General Public License
 | ||||||
|  | +# along with this program; if not, write to the Free Software Foundation,
 | ||||||
|  | +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | ||||||
|  | +
 | ||||||
|  | +# Check online renaming of VDO devices works
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +SKIP_WITH_LVMPOLLD=1
 | ||||||
|  | +
 | ||||||
|  | +. lib/inittest
 | ||||||
|  | +
 | ||||||
|  | +#
 | ||||||
|  | +# Main
 | ||||||
|  | +#
 | ||||||
|  | +
 | ||||||
|  | +aux have_vdo 6 2 1 || skip
 | ||||||
|  | +aux have_cache 1 3 0 || skip
 | ||||||
|  | +aux have_raid 1 3 0 || skip
 | ||||||
|  | +
 | ||||||
|  | +aux prepare_vg 2 5000
 | ||||||
|  | +
 | ||||||
|  | +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
 | ||||||
|  | +lvrename $vg/vpool1 vpool2
 | ||||||
|  | +check lv_exists $vg $lv1 vpool2 vpool2_vdata
 | ||||||
|  | +
 | ||||||
|  | +lvremove -ff $vg
 | ||||||
|  | +
 | ||||||
|  | +# With version >= 6.2.3 online rename should work
 | ||||||
|  | +if aux have_vdo 6 2 3 ; then
 | ||||||
|  | +
 | ||||||
|  | +### CACHE ####
 | ||||||
|  | +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
 | ||||||
|  | +lvcreate -H -L10 $vg/vpool1
 | ||||||
|  | +lvrename $vg/vpool1 $vg/vpool2
 | ||||||
|  | +check lv_exists $vg vpool2 vpool2_vdata
 | ||||||
|  | +lvremove -ff $vg
 | ||||||
|  | +
 | ||||||
|  | +### RAID ####
 | ||||||
|  | +lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
 | ||||||
|  | +lvconvert --yes --type vdo-pool $vg/vpool1
 | ||||||
|  | +lvrename $vg/vpool1 $vg/vpool2
 | ||||||
|  | +check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
 | ||||||
|  | +lvremove -ff $vg
 | ||||||
|  | +
 | ||||||
|  | +fi # >= 6.2.3
 | ||||||
|  | +
 | ||||||
|  | +# Check when VDO target does not support online resize
 | ||||||
|  | +aux lvmconf "global/vdo_disabled_features = [ \"online_rename\" ]"
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +### CACHE ####
 | ||||||
|  | +lvcreate --vdo -L4G -V2G --name $lv1 $vg/vpool1
 | ||||||
|  | +lvcreate -H -L10 $vg/vpool1
 | ||||||
|  | +
 | ||||||
|  | +# VDO target driver cannot handle online rename
 | ||||||
|  | +not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
 | ||||||
|  | +grep "Cannot rename" out
 | ||||||
|  | +
 | ||||||
|  | +# Ofline should work
 | ||||||
|  | +lvchange -an $vg
 | ||||||
|  | +lvrename $vg/vpool1 $vg/vpool2
 | ||||||
|  | +lvchange -ay $vg
 | ||||||
|  | +check lv_exists $vg $lv1 vpool2 vpool2_vdata
 | ||||||
|  | +lvremove -ff $vg
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +### RAID ####
 | ||||||
|  | +lvcreate --type raid1 -L4G --nosync --name vpool1 $vg
 | ||||||
|  | +lvconvert --yes --type vdo-pool $vg/vpool1
 | ||||||
|  | +not lvrename $vg/vpool1 $vg/vpool2 2>&1 | tee out
 | ||||||
|  | +grep "Cannot rename" out
 | ||||||
|  | +
 | ||||||
|  | +# Ofline should work
 | ||||||
|  | +lvchange -an $vg
 | ||||||
|  | +lvrename $vg/vpool1 $vg/vpool2
 | ||||||
|  | +lvchange -ay $vg
 | ||||||
|  | +check lv_exists $vg vpool2 vpool2_vdata vpool2_vdata_rimage_0
 | ||||||
|  | +lvremove -ff $vg
 | ||||||
|  | +
 | ||||||
|  | +vgremove -ff $vg
 | ||||||
							
								
								
									
										47
									
								
								lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  |  test/shell/lvcreate-thin-limits.sh | 30 ++++++++++++++++++++++++++---- | ||||||
|  |  1 file changed, 26 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/lvcreate-thin-limits.sh b/test/shell/lvcreate-thin-limits.sh
 | ||||||
|  | index 6a9c33d..5dcc160 100644
 | ||||||
|  | --- a/test/shell/lvcreate-thin-limits.sh
 | ||||||
|  | +++ b/test/shell/lvcreate-thin-limits.sh
 | ||||||
|  | @@ -27,13 +27,35 @@ aux can_use_16T || skip
 | ||||||
|  |  aux have_thin 1 0 0 || skip | ||||||
|  |  which mkfs.ext4 || skip | ||||||
|  |   | ||||||
|  | -aux prepare_pvs 1 16777216
 | ||||||
|  | +# 16T device
 | ||||||
|  | +aux prepare_pvs 2 8388608
 | ||||||
|  |  get_devs | ||||||
|  |   | ||||||
|  | -vgcreate $SHARED -s 4K "$vg" "${DEVICES[@]}"
 | ||||||
|  | +# gives 16777215M device
 | ||||||
|  | +vgcreate $SHARED -s 4M "$vg" "${DEVICES[@]}"
 | ||||||
|  |   | ||||||
|  | -not lvcreate -T -L15.995T --poolmetadatasize 5G $vg/pool
 | ||||||
|  | +# For 1st. pass only single PV
 | ||||||
|  | +lvcreate -l100%PV --name $lv1 $vg "$dev2"
 | ||||||
|  |   | ||||||
|  | -lvs -ao+seg_pe_ranges $vg
 | ||||||
|  | +for i in 1 0
 | ||||||
|  | +do
 | ||||||
|  | +	SIZE=$(get vg_field "$vg" vg_free --units m)
 | ||||||
|  | +	SIZE=${SIZE%%\.*}
 | ||||||
|  | +
 | ||||||
|  | +	# ~16T - 2 * 5G + something  -> should not fit
 | ||||||
|  | +	not lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 + 1 )) --poolmetadatasize 5G $vg/pool
 | ||||||
|  | +
 | ||||||
|  | +	check vg_field "$vg" lv_count "$i"
 | ||||||
|  | +
 | ||||||
|  | +	# Should fit  data + metadata + pmspare
 | ||||||
|  | +	lvcreate -Zn -T -L$(( SIZE - 2 * 5 * 1024 )) --poolmetadatasize 5G $vg/pool
 | ||||||
|  | +
 | ||||||
|  | +	check vg_field "$vg" vg_free "0"
 | ||||||
|  | +
 | ||||||
|  | +	lvs -ao+seg_pe_ranges $vg
 | ||||||
|  | +
 | ||||||
|  | +        # Remove everything for 2nd. pass
 | ||||||
|  | +	lvremove -ff $vg
 | ||||||
|  | +done
 | ||||||
|  |   | ||||||
|  |  vgremove -ff $vg | ||||||
| @ -0,0 +1,77 @@ | |||||||
|  |  test/shell/lvconvert-thin.sh    |  2 +- | ||||||
|  |  test/shell/lvcreate-cache.sh    | 12 +++++------- | ||||||
|  |  test/shell/lvcreate-thin-big.sh | 10 +++++----- | ||||||
|  |  3 files changed, 11 insertions(+), 13 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/test/shell/lvconvert-thin.sh b/test/shell/lvconvert-thin.sh
 | ||||||
|  | index 1319655..ee85691 100644
 | ||||||
|  | --- a/test/shell/lvconvert-thin.sh
 | ||||||
|  | +++ b/test/shell/lvconvert-thin.sh
 | ||||||
|  | @@ -128,7 +128,7 @@ lvcreate -L1T -n $lv1 $vg
 | ||||||
|  |  lvcreate -L32G -n $lv2 $vg | ||||||
|  |  # Warning about bigger then needed | ||||||
|  |  lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err | ||||||
|  | -grep "WARNING: Maximum" err
 | ||||||
|  | +grep -i "maximum" err
 | ||||||
|  |  lvremove -f $vg | ||||||
|  |   | ||||||
|  |   | ||||||
|  | diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
 | ||||||
|  | index 2c46e21..4d9d75e 100644
 | ||||||
|  | --- a/test/shell/lvcreate-cache.sh
 | ||||||
|  | +++ b/test/shell/lvcreate-cache.sh
 | ||||||
|  | @@ -27,7 +27,6 @@ aux prepare_vg 5 80000
 | ||||||
|  |   | ||||||
|  |  aux lvmconf 'global/cache_disabled_features = [ "policy_smq" ]' | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  |  ####################### | ||||||
|  |  # Cache_Pool creation # | ||||||
|  |  ####################### | ||||||
|  | @@ -173,17 +172,16 @@ dmsetup table ${vg}-$lv1 | grep cache  # ensure it is loaded in kernel
 | ||||||
|  |   | ||||||
|  |  lvremove -f $vg | ||||||
|  |   | ||||||
|  | -
 | ||||||
|  |  # Check minimum cache pool metadata size | ||||||
|  | -lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>out
 | ||||||
|  | -grep "WARNING: Minimum" out
 | ||||||
|  | +lvcreate -l 1 --type cache-pool --poolmetadatasize 1 $vg 2>&1 | tee out
 | ||||||
|  | +grep -i "minimal" out
 | ||||||
|  | +
 | ||||||
|  |   | ||||||
|  |  # FIXME: This test is failing in allocator with smaller VG sizes | ||||||
|  | -lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>out
 | ||||||
|  | -grep "WARNING: Maximum" out
 | ||||||
|  | +lvcreate -l 1 --type cache-pool --poolmetadatasize 17G $vg 2>&1 | tee out
 | ||||||
|  | +grep -i "maximum" out
 | ||||||
|  |   | ||||||
|  |  lvremove -f $vg | ||||||
|  | -
 | ||||||
|  |  ######################################## | ||||||
|  |  # Cache conversion and r/w permissions # | ||||||
|  |  ######################################## | ||||||
|  | diff --git a/test/shell/lvcreate-thin-big.sh b/test/shell/lvcreate-thin-big.sh
 | ||||||
|  | index 0b622b7..2549035 100644
 | ||||||
|  | --- a/test/shell/lvcreate-thin-big.sh
 | ||||||
|  | +++ b/test/shell/lvcreate-thin-big.sh
 | ||||||
|  | @@ -31,14 +31,14 @@ vgcreate $SHARED -s 64K "$vg" "${DEVICES[@]}"
 | ||||||
|  |   | ||||||
|  |  # Size 0 is not valid | ||||||
|  |  invalid lvcreate -L4M --chunksize 128 --poolmetadatasize 0 -T $vg/pool1 2>out | ||||||
|  | -lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>out
 | ||||||
|  | -grep "WARNING: Minimum" out
 | ||||||
|  | +lvcreate -Zn -L4M --chunksize 128 --poolmetadatasize 16k -T $vg/pool1 2>&1 >out
 | ||||||
|  | +grep -i "minimal" out
 | ||||||
|  |  # FIXME: metadata allocation fails, if PV doesn't have at least 16GB | ||||||
|  |  # i.e. pool metadata device cannot be multisegment | ||||||
|  | -lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>out
 | ||||||
|  | -grep "WARNING: Maximum" out
 | ||||||
|  | +lvcreate -Zn -L4M --chunksize 64k --poolmetadatasize 17G -T $vg/pool2 2>&1 >out
 | ||||||
|  | +grep "maximum" out
 | ||||||
|  |  check lv_field $vg/pool1_tmeta size "2.00m" | ||||||
|  | -check lv_field $vg/pool2_tmeta size "15.81g"
 | ||||||
|  | +check lv_field $vg/pool2_tmeta size "<15.88g"
 | ||||||
|  |   | ||||||
|  |  # Check we do report correct percent values. | ||||||
|  |  lvcreate --type zero -L3G $vg -n pool3 | ||||||
| @ -0,0 +1,694 @@ | |||||||
|  |  conf/example.conf.in             |  7 +++ | ||||||
|  |  device_mapper/all.h              | 16 +++++-- | ||||||
|  |  device_mapper/libdm-deptree.c    | 39 ++++++++++++----- | ||||||
|  |  lib/activate/dev_manager.c       |  8 ++-- | ||||||
|  |  lib/config/config_settings.h     |  5 +++ | ||||||
|  |  lib/config/defaults.h            |  2 + | ||||||
|  |  lib/format_text/flags.c          |  1 + | ||||||
|  |  lib/metadata/lv_manip.c          | 31 ++++++++++++++ | ||||||
|  |  lib/metadata/merge.c             |  2 + | ||||||
|  |  lib/metadata/metadata-exported.h | 11 +++++ | ||||||
|  |  lib/metadata/metadata.h          | 13 ++++++ | ||||||
|  |  lib/metadata/pool_manip.c        | 46 ++++++++++++++++++++ | ||||||
|  |  lib/metadata/thin_manip.c        | 92 ++++++++++++++++++++++++++-------------- | ||||||
|  |  lib/thin/thin.c                  | 22 +++++++--- | ||||||
|  |  man/lvmthin.7_main               | 10 ++++- | ||||||
|  |  tools/lvconvert.c                |  4 ++ | ||||||
|  |  tools/lvcreate.c                 |  2 + | ||||||
|  |  17 files changed, 256 insertions(+), 55 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/conf/example.conf.in b/conf/example.conf.in
 | ||||||
|  | index d149ed9..107a071 100644
 | ||||||
|  | --- a/conf/example.conf.in
 | ||||||
|  | +++ b/conf/example.conf.in
 | ||||||
|  | @@ -494,6 +494,13 @@ allocation {
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# thin_pool_metadata_require_separate_pvs = 0 | ||||||
|  |   | ||||||
|  | +	# Configuration option allocation/thin_pool_crop_metadata.
 | ||||||
|  | +	# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
 | ||||||
|  | +	# This is slightly less then the actual maximum 15.88 GiB.
 | ||||||
|  | +	# For compatibility with older version and use of cropped size set to 1.
 | ||||||
|  | +	# This configuration option has an automatic default value.
 | ||||||
|  | +	# thin_pool_crop_metadata = 0
 | ||||||
|  | +
 | ||||||
|  |  	# Configuration option allocation/thin_pool_zero. | ||||||
|  |  	# Thin pool data chunks are zeroed before they are first used. | ||||||
|  |  	# Zeroing with a larger thin pool chunk size reduces performance. | ||||||
|  | diff --git a/device_mapper/all.h b/device_mapper/all.h
 | ||||||
|  | index 1080d25..489ca1c 100644
 | ||||||
|  | --- a/device_mapper/all.h
 | ||||||
|  | +++ b/device_mapper/all.h
 | ||||||
|  | @@ -1072,10 +1072,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
 | ||||||
|  |  #define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128)) | ||||||
|  |  #define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152)) | ||||||
|  |  /* | ||||||
|  | - * Max supported size for thin pool  metadata device (17112760320 bytes)
 | ||||||
|  | - * Limitation is hardcoded into the kernel and bigger device size
 | ||||||
|  | - * is not accepted.
 | ||||||
|  | + * Max supported size for thin pool metadata device (17045913600 bytes)
 | ||||||
|  |   * drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS | ||||||
|  | + * But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
 | ||||||
|  | + * Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
 | ||||||
|  |   */ | ||||||
|  |  #define DM_THIN_MAX_METADATA_SIZE   (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024) | ||||||
|  |   | ||||||
|  | @@ -1088,6 +1088,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
 | ||||||
|  |  				      uint64_t low_water_mark, | ||||||
|  |  				      unsigned skip_block_zeroing); | ||||||
|  |   | ||||||
|  | +int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
 | ||||||
|  | +					 uint64_t size,
 | ||||||
|  | +					 uint64_t transaction_id,
 | ||||||
|  | +					 const char *metadata_uuid,
 | ||||||
|  | +					 const char *pool_uuid,
 | ||||||
|  | +					 uint32_t data_block_size,
 | ||||||
|  | +					 uint64_t low_water_mark,
 | ||||||
|  | +					 unsigned skip_block_zeroing,
 | ||||||
|  | +					 unsigned crop_metadata);
 | ||||||
|  | +
 | ||||||
|  |  /* Supported messages for thin provision target */ | ||||||
|  |  typedef enum { | ||||||
|  |  	DM_THIN_MESSAGE_CREATE_SNAP,		/* device_id, origin_id */ | ||||||
|  | diff --git a/device_mapper/libdm-deptree.c b/device_mapper/libdm-deptree.c
 | ||||||
|  | index 6ce956f..5b60dc9 100644
 | ||||||
|  | --- a/device_mapper/libdm-deptree.c
 | ||||||
|  | +++ b/device_mapper/libdm-deptree.c
 | ||||||
|  | @@ -3979,6 +3979,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
 | ||||||
|  |  				      uint64_t low_water_mark, | ||||||
|  |  				      unsigned skip_block_zeroing) | ||||||
|  |  { | ||||||
|  | +	return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
 | ||||||
|  | +						    metadata_uuid, pool_uuid,
 | ||||||
|  | +						    data_block_size,
 | ||||||
|  | +						    low_water_mark,
 | ||||||
|  | +						    skip_block_zeroing,
 | ||||||
|  | +						    1);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
 | ||||||
|  | +					 uint64_t size,
 | ||||||
|  | +					 uint64_t transaction_id,
 | ||||||
|  | +					 const char *metadata_uuid,
 | ||||||
|  | +					 const char *pool_uuid,
 | ||||||
|  | +					 uint32_t data_block_size,
 | ||||||
|  | +					 uint64_t low_water_mark,
 | ||||||
|  | +					 unsigned skip_block_zeroing,
 | ||||||
|  | +					 unsigned crop_metadata)
 | ||||||
|  | +{
 | ||||||
|  |  	struct load_segment *seg, *mseg; | ||||||
|  |  	uint64_t devsize = 0; | ||||||
|  |   | ||||||
|  | @@ -4005,17 +4023,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
 | ||||||
|  |  	if (!_link_tree_nodes(node, seg->metadata)) | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | -	/* FIXME: more complex target may need more tweaks */
 | ||||||
|  | -	dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
 | ||||||
|  | -		devsize += mseg->size;
 | ||||||
|  | -		if (devsize > DM_THIN_MAX_METADATA_SIZE) {
 | ||||||
|  | -			log_debug_activation("Ignoring %" PRIu64 " of device.",
 | ||||||
|  | -					     devsize - DM_THIN_MAX_METADATA_SIZE);
 | ||||||
|  | -			mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
 | ||||||
|  | -			devsize = DM_THIN_MAX_METADATA_SIZE;
 | ||||||
|  | -			/* FIXME: drop remaining segs */
 | ||||||
|  | +	if (crop_metadata)
 | ||||||
|  | +		/* FIXME: more complex target may need more tweaks */
 | ||||||
|  | +		dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
 | ||||||
|  | +			devsize += mseg->size;
 | ||||||
|  | +			if (devsize > DM_THIN_MAX_METADATA_SIZE) {
 | ||||||
|  | +				log_debug_activation("Ignoring %" PRIu64 " of device.",
 | ||||||
|  | +						     devsize - DM_THIN_MAX_METADATA_SIZE);
 | ||||||
|  | +				mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
 | ||||||
|  | +				devsize = DM_THIN_MAX_METADATA_SIZE;
 | ||||||
|  | +				/* FIXME: drop remaining segs */
 | ||||||
|  | +			}
 | ||||||
|  |  		} | ||||||
|  | -	}
 | ||||||
|  |   | ||||||
|  |  	if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) { | ||||||
|  |  		log_error("Missing pool uuid %s.", pool_uuid); | ||||||
|  | diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
 | ||||||
|  | index 8d27bd3..9a25482 100644
 | ||||||
|  | --- a/lib/activate/dev_manager.c
 | ||||||
|  | +++ b/lib/activate/dev_manager.c
 | ||||||
|  | @@ -261,7 +261,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
 | ||||||
|  |  	int dmtask; | ||||||
|  |  	int with_flush; /* TODO: arg for _info_run */ | ||||||
|  |  	void *target = NULL; | ||||||
|  | -	uint64_t target_start, target_length, start, length;
 | ||||||
|  | +	uint64_t target_start, target_length, start, length, length_crop = 0;
 | ||||||
|  |  	char *target_name, *target_params; | ||||||
|  |  	const char *devname; | ||||||
|  |   | ||||||
|  | @@ -297,7 +297,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
 | ||||||
|  |  		/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */ | ||||||
|  |  		if (lv_is_thin_pool_metadata(seg_status->seg->lv) && | ||||||
|  |  		    (length > DM_THIN_MAX_METADATA_SIZE)) | ||||||
|  | -			length = DM_THIN_MAX_METADATA_SIZE;
 | ||||||
|  | +			length_crop = DM_THIN_MAX_METADATA_SIZE;
 | ||||||
|  |   | ||||||
|  |  		/* Uses virtual size with headers for VDO pool device */ | ||||||
|  |  		if (lv_is_vdo_pool(seg_status->seg->lv)) | ||||||
|  | @@ -310,7 +310,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
 | ||||||
|  |  			target = dm_get_next_target(dmt, target, &target_start, | ||||||
|  |  						    &target_length, &target_name, &target_params); | ||||||
|  |   | ||||||
|  | -			if ((start == target_start) && (length == target_length))
 | ||||||
|  | +			if ((start == target_start) &&
 | ||||||
|  | +			    ((length == target_length) ||
 | ||||||
|  | +			     (length_crop && (length_crop == target_length))))
 | ||||||
|  |  				break; /* Keep target_params when matching segment is found */ | ||||||
|  |   | ||||||
|  |  			target_params = NULL; /* Marking this target_params unusable */ | ||||||
|  | diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
 | ||||||
|  | index 3c4032e..cb4e23a 100644
 | ||||||
|  | --- a/lib/config/config_settings.h
 | ||||||
|  | +++ b/lib/config/config_settings.h
 | ||||||
|  | @@ -628,6 +628,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
 | ||||||
|  |  cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL, | ||||||
|  |  	"Thin pool metadata and data will always use different PVs.\n") | ||||||
|  |   | ||||||
|  | +cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
 | ||||||
|  | +	"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
 | ||||||
|  | +	"This is slightly less then the actual maximum 15.88 GiB.\n"
 | ||||||
|  | +	"For compatibility with older version and use of cropped size set to 1.\n")
 | ||||||
|  | +
 | ||||||
|  |  cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL, | ||||||
|  |  	"Thin pool data chunks are zeroed before they are first used.\n" | ||||||
|  |  	"Zeroing with a larger thin pool chunk size reduces performance.\n") | ||||||
|  | diff --git a/lib/config/defaults.h b/lib/config/defaults.h
 | ||||||
|  | index 708a575..bcc20cc 100644
 | ||||||
|  | --- a/lib/config/defaults.h
 | ||||||
|  | +++ b/lib/config/defaults.h
 | ||||||
|  | @@ -118,6 +118,8 @@
 | ||||||
|  |  #define DEFAULT_THIN_REPAIR_OPTION1 "" | ||||||
|  |  #define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1 | ||||||
|  |  #define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0 | ||||||
|  | +#define DEFAULT_THIN_POOL_CROP_METADATA 0
 | ||||||
|  | +#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4)  /* KB */ /* 0x3f8040 blocks */
 | ||||||
|  |  #define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2)  /* KB */ | ||||||
|  |  #define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048  /* KB */ | ||||||
|  |  #define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */ | ||||||
|  | diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
 | ||||||
|  | index bc93a5d..4cee14a 100644
 | ||||||
|  | --- a/lib/format_text/flags.c
 | ||||||
|  | +++ b/lib/format_text/flags.c
 | ||||||
|  | @@ -72,6 +72,7 @@ static const struct flag _lv_flags[] = {
 | ||||||
|  |  	{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG}, | ||||||
|  |  	{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG}, | ||||||
|  |  	{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG}, | ||||||
|  | +	{LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
 | ||||||
|  |  	{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG}, | ||||||
|  |  	{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG}, | ||||||
|  |  	{LV_NOSCAN, NULL, 0}, | ||||||
|  | diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
 | ||||||
|  | index 443d32c..445c4ad 100644
 | ||||||
|  | --- a/lib/metadata/lv_manip.c
 | ||||||
|  | +++ b/lib/metadata/lv_manip.c
 | ||||||
|  | @@ -5384,6 +5384,8 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
 | ||||||
|  |  	uint32_t existing_extents; | ||||||
|  |  	uint32_t seg_size = 0; | ||||||
|  |  	uint32_t new_extents; | ||||||
|  | +	uint64_t max_metadata_size;
 | ||||||
|  | +	thin_crop_metadata_t crop;
 | ||||||
|  |  	int reducing = 0; | ||||||
|  |   | ||||||
|  |  	seg_last = last_seg(lv); | ||||||
|  | @@ -5544,6 +5546,33 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
 | ||||||
|  |  					return 1; | ||||||
|  |  				} | ||||||
|  |  			} | ||||||
|  | +		} else if (lv_is_thin_pool_metadata(lv)) {
 | ||||||
|  | +			if (!(seg = get_only_segment_using_this_lv(lv)))
 | ||||||
|  | +				return_0;
 | ||||||
|  | +
 | ||||||
|  | +			max_metadata_size = get_thin_pool_max_metadata_size(cmd, vg->profile, &crop);
 | ||||||
|  | +
 | ||||||
|  | +			if (((uint64_t)lp->extents * vg->extent_size) > max_metadata_size) {
 | ||||||
|  | +				lp->extents = (max_metadata_size + vg->extent_size - 1) / vg->extent_size;
 | ||||||
|  | +				log_print_unless_silent("Reached maximum pool metadata size %s (%" PRIu32 " extents).",
 | ||||||
|  | +							display_size(vg->cmd, max_metadata_size), lp->extents);
 | ||||||
|  | +			}
 | ||||||
|  | +
 | ||||||
|  | +			if (existing_logical_extents >= lp->extents)
 | ||||||
|  | +				lp->extents = existing_logical_extents;
 | ||||||
|  | +
 | ||||||
|  | +			crop = get_thin_pool_crop_metadata(cmd, crop, (uint64_t)lp->extents * vg->extent_size);
 | ||||||
|  | +
 | ||||||
|  | +			if (seg->crop_metadata != crop) {
 | ||||||
|  | +				seg->crop_metadata = crop;
 | ||||||
|  | +				seg->lv->status |= LV_CROP_METADATA;
 | ||||||
|  | +				/* Crop change require reload even if there no size change */
 | ||||||
|  | +				lp->size_changed = 1;
 | ||||||
|  | +				log_print_unless_silent("Thin pool will use metadata without cropping.");
 | ||||||
|  | +			}
 | ||||||
|  | +
 | ||||||
|  | +			if (!(seg_size = lp->extents - existing_logical_extents))
 | ||||||
|  | +				return 1;  /* No change in metadata size */
 | ||||||
|  |  		} | ||||||
|  |  	} else {  /* If reducing, find stripes, stripesize & size of last segment */ | ||||||
|  |  		if (lp->stripes || lp->stripe_size || lp->mirrors) | ||||||
|  | @@ -8388,6 +8417,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
 | ||||||
|  |  		first_seg(lv)->chunk_size = lp->chunk_size; | ||||||
|  |  		first_seg(lv)->zero_new_blocks = lp->zero_new_blocks; | ||||||
|  |  		first_seg(lv)->discards = lp->discards; | ||||||
|  | +		if ((first_seg(lv)->crop_metadata = lp->crop_metadata) == THIN_CROP_METADATA_NO)
 | ||||||
|  | +			lv->status |= LV_CROP_METADATA;
 | ||||||
|  |  		if (!recalculate_pool_chunk_size_with_dev_hints(lv, lp->thin_chunk_size_calc_policy)) { | ||||||
|  |  			stack; | ||||||
|  |  			goto revert_new_lv; | ||||||
|  | diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
 | ||||||
|  | index 0aa2293..eff59ae 100644
 | ||||||
|  | --- a/lib/metadata/merge.c
 | ||||||
|  | +++ b/lib/metadata/merge.c
 | ||||||
|  | @@ -495,6 +495,8 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
 | ||||||
|  |  			seg_error("sets discards"); | ||||||
|  |  		if (!dm_list_empty(&seg->thin_messages)) | ||||||
|  |  			seg_error("sets thin_messages list"); | ||||||
|  | +		if (seg->lv->status & LV_CROP_METADATA)
 | ||||||
|  | +			seg_error("sets CROP_METADATA flag");
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (seg_is_thin_volume(seg)) { | ||||||
|  | diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
 | ||||||
|  | index 54dc29f..0e57722 100644
 | ||||||
|  | --- a/lib/metadata/metadata-exported.h
 | ||||||
|  | +++ b/lib/metadata/metadata-exported.h
 | ||||||
|  | @@ -143,6 +143,7 @@
 | ||||||
|  |   | ||||||
|  |  #define LV_REMOVE_AFTER_RESHAPE	UINT64_C(0x0400000000000000)	/* LV needs to be removed after a shrinking reshape */ | ||||||
|  |  #define LV_METADATA_FORMAT	UINT64_C(0x0800000000000000)    /* LV has segments with metadata format */ | ||||||
|  | +#define LV_CROP_METADATA	UINT64_C(0x0000000000000400)	/* LV - also VG CLUSTERED */
 | ||||||
|  |   | ||||||
|  |  #define LV_RESHAPE		UINT64_C(0x1000000000000000)    /* Ongoing reshape (number of stripes, stripesize or raid algorithm change): | ||||||
|  |  								   used as SEGTYPE_FLAG to prevent activation on old runtime */ | ||||||
|  | @@ -326,6 +327,12 @@ typedef enum {
 | ||||||
|  |  } thin_discards_t; | ||||||
|  |   | ||||||
|  |  typedef enum { | ||||||
|  | +	THIN_CROP_METADATA_UNSELECTED = 0,  /* 'auto' selects */
 | ||||||
|  | +	THIN_CROP_METADATA_NO,
 | ||||||
|  | +	THIN_CROP_METADATA_YES,
 | ||||||
|  | +} thin_crop_metadata_t;
 | ||||||
|  | +
 | ||||||
|  | +typedef enum {
 | ||||||
|  |  	CACHE_MODE_UNSELECTED = 0, | ||||||
|  |  	CACHE_MODE_WRITETHROUGH, | ||||||
|  |  	CACHE_MODE_WRITEBACK, | ||||||
|  | @@ -502,6 +509,7 @@ struct lv_segment {
 | ||||||
|  |  	uint64_t transaction_id;		/* For thin_pool, thin */ | ||||||
|  |  	thin_zero_t zero_new_blocks;		/* For thin_pool */ | ||||||
|  |  	thin_discards_t discards;		/* For thin_pool */ | ||||||
|  | +	thin_crop_metadata_t crop_metadata;	/* For thin_pool */
 | ||||||
|  |  	struct dm_list thin_messages;		/* For thin_pool */ | ||||||
|  |  	struct logical_volume *external_lv;	/* For thin */ | ||||||
|  |  	struct logical_volume *pool_lv;		/* For thin, cache */ | ||||||
|  | @@ -885,6 +893,8 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  			    unsigned attr, | ||||||
|  |  			    uint32_t pool_data_extents, | ||||||
|  |  			    uint32_t *pool_metadata_extents, | ||||||
|  | +			    struct logical_volume *metadata_lv,
 | ||||||
|  | +			    unsigned *crop_metadata,
 | ||||||
|  |  			    int *chunk_size_calc_method, uint32_t *chunk_size, | ||||||
|  |  			    thin_discards_t *discards, thin_zero_t *zero_new_blocks); | ||||||
|  |   | ||||||
|  | @@ -1011,6 +1021,7 @@ struct lvcreate_params {
 | ||||||
|  |   | ||||||
|  |  	uint64_t permission; /* all */ | ||||||
|  |  	unsigned error_when_full; /* when segment supports it */ | ||||||
|  | +	thin_crop_metadata_t crop_metadata;
 | ||||||
|  |  	uint32_t read_ahead; /* all */ | ||||||
|  |  	int approx_alloc;     /* all */ | ||||||
|  |  	alloc_policy_t alloc; /* all */ | ||||||
|  | diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
 | ||||||
|  | index 2c22450..0f230e4 100644
 | ||||||
|  | --- a/lib/metadata/metadata.h
 | ||||||
|  | +++ b/lib/metadata/metadata.h
 | ||||||
|  | @@ -512,8 +512,21 @@ int pool_below_threshold(const struct lv_segment *pool_seg);
 | ||||||
|  |  int pool_check_overprovisioning(const struct logical_volume *lv); | ||||||
|  |  int create_pool(struct logical_volume *pool_lv, const struct segment_type *segtype, | ||||||
|  |  		struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size); | ||||||
|  | +uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
 | ||||||
|  | +					 thin_crop_metadata_t *crop);
 | ||||||
|  | +thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
 | ||||||
|  | +						  thin_crop_metadata_t crop,
 | ||||||
|  | +						  uint64_t metadata_size);
 | ||||||
|  |  uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size); | ||||||
|  |   | ||||||
|  | +int update_pool_metadata_min_max(struct cmd_context *cmd,
 | ||||||
|  | +				 uint32_t extent_size,
 | ||||||
|  | +				 uint64_t min_metadata_size,		/* required min */
 | ||||||
|  | +				 uint64_t max_metadata_size,		/* writable max */
 | ||||||
|  | +				 uint64_t *metadata_size,		/* current calculated */
 | ||||||
|  | +				 struct logical_volume *metadata_lv,	/* name of converted LV or NULL */
 | ||||||
|  | +				 uint32_t *metadata_extents);		/* resulting extent count */
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * Begin skeleton for external LVM library | ||||||
|  |   */ | ||||||
|  | diff --git a/lib/metadata/pool_manip.c b/lib/metadata/pool_manip.c
 | ||||||
|  | index a9dc611..b67882e 100644
 | ||||||
|  | --- a/lib/metadata/pool_manip.c
 | ||||||
|  | +++ b/lib/metadata/pool_manip.c
 | ||||||
|  | @@ -742,6 +742,52 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
 | ||||||
|  |  	return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int update_pool_metadata_min_max(struct cmd_context *cmd,
 | ||||||
|  | +				 uint32_t extent_size,
 | ||||||
|  | +				 uint64_t min_metadata_size,		/* required min */
 | ||||||
|  | +				 uint64_t max_metadata_size,		/* writable max */
 | ||||||
|  | +				 uint64_t *metadata_size,		/* current calculated */
 | ||||||
|  | +				 struct logical_volume *metadata_lv,	/* name of converted LV or NULL */
 | ||||||
|  | +				 uint32_t *metadata_extents)		/* resulting extent count */
 | ||||||
|  | +{
 | ||||||
|  | +	max_metadata_size = dm_round_up(max_metadata_size, extent_size);
 | ||||||
|  | +	min_metadata_size = dm_round_up(min_metadata_size, extent_size);
 | ||||||
|  | +
 | ||||||
|  | +	if (*metadata_size > max_metadata_size) {
 | ||||||
|  | +		if (metadata_lv) {
 | ||||||
|  | +			log_print_unless_silent("Size %s of pool metadata volume %s is bigger then maximum usable size %s.",
 | ||||||
|  | +						display_size(cmd, *metadata_size),
 | ||||||
|  | +						display_lvname(metadata_lv),
 | ||||||
|  | +						display_size(cmd, max_metadata_size));
 | ||||||
|  | +		} else {
 | ||||||
|  | +			if (*metadata_extents)
 | ||||||
|  | +				log_print_unless_silent("Reducing pool metadata size %s to maximum usable size %s.",
 | ||||||
|  | +							display_size(cmd, *metadata_size),
 | ||||||
|  | +							display_size(cmd, max_metadata_size));
 | ||||||
|  | +			*metadata_size = max_metadata_size;
 | ||||||
|  | +		}
 | ||||||
|  | +	} else if (*metadata_size < min_metadata_size) {
 | ||||||
|  | +		if (metadata_lv) {
 | ||||||
|  | +			log_error("Can't use volume %s with size %s as pool metadata. Minimal required size is %s.",
 | ||||||
|  | +				  display_lvname(metadata_lv),
 | ||||||
|  | +				  display_size(cmd, *metadata_size),
 | ||||||
|  | +				  display_size(cmd, min_metadata_size));
 | ||||||
|  | +			return 0;
 | ||||||
|  | +		} else {
 | ||||||
|  | +			if (*metadata_extents)
 | ||||||
|  | +				log_print_unless_silent("Extending pool metadata size %s to required minimal size %s.",
 | ||||||
|  | +							display_size(cmd, *metadata_size),
 | ||||||
|  | +							display_size(cmd, min_metadata_size));
 | ||||||
|  | +			*metadata_size = min_metadata_size;
 | ||||||
|  | +		}
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  | +	if (!(*metadata_extents = extents_from_size(cmd, *metadata_size, extent_size)))
 | ||||||
|  | +		return_0;
 | ||||||
|  | +
 | ||||||
|  | +	return 1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int vg_set_pool_metadata_spare(struct logical_volume *lv) | ||||||
|  |  { | ||||||
|  |  	char new_name[NAME_LEN]; | ||||||
|  | diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
 | ||||||
|  | index 4591dd7..451c382 100644
 | ||||||
|  | --- a/lib/metadata/thin_manip.c
 | ||||||
|  | +++ b/lib/metadata/thin_manip.c
 | ||||||
|  | @@ -610,9 +610,9 @@ static uint64_t _estimate_metadata_size(uint32_t data_extents, uint32_t extent_s
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* Estimate maximal supportable thin pool data size for given chunk_size */ | ||||||
|  | -static uint64_t _estimate_max_data_size(uint32_t chunk_size)
 | ||||||
|  | +static uint64_t _estimate_max_data_size(uint64_t max_metadata_size, uint32_t chunk_size)
 | ||||||
|  |  { | ||||||
|  | -	return  chunk_size * (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2) * SECTOR_SIZE / UINT64_C(64);
 | ||||||
|  | +	return  max_metadata_size * chunk_size * SECTOR_SIZE / UINT64_C(64);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* Estimate thin pool chunk size from data and metadata size (in sector units) */ | ||||||
|  | @@ -662,6 +662,38 @@ int get_default_allocation_thin_pool_chunk_size(struct cmd_context *cmd, struct
 | ||||||
|  |  	return 1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/* Return max supported metadata size with selected cropping */
 | ||||||
|  | +uint64_t get_thin_pool_max_metadata_size(struct cmd_context *cmd, struct profile *profile,
 | ||||||
|  | +					 thin_crop_metadata_t *crop)
 | ||||||
|  | +{
 | ||||||
|  | +	*crop = find_config_tree_bool(cmd, allocation_thin_pool_crop_metadata_CFG, profile) ?
 | ||||||
|  | +		THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
 | ||||||
|  | +
 | ||||||
|  | +	return (*crop == THIN_CROP_METADATA_NO) ?
 | ||||||
|  | +		(2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB) : (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +/*
 | ||||||
|  | + * With existing crop method, check if the metadata_size would need cropping.
 | ||||||
|  | + * If not, set UNSELECTED, otherwise print some verbose info about selected cropping
 | ||||||
|  | + */
 | ||||||
|  | +thin_crop_metadata_t get_thin_pool_crop_metadata(struct cmd_context *cmd,
 | ||||||
|  | +						  thin_crop_metadata_t crop,
 | ||||||
|  | +						  uint64_t metadata_size)
 | ||||||
|  | +{
 | ||||||
|  | +	const uint64_t crop_size = (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE);
 | ||||||
|  | +
 | ||||||
|  | +	if (metadata_size > crop_size) {
 | ||||||
|  | +		if (crop == THIN_CROP_METADATA_NO)
 | ||||||
|  | +			log_verbose("Using metadata size without cropping.");
 | ||||||
|  | +		else
 | ||||||
|  | +			log_verbose("Cropping metadata size to %s.", display_size(cmd, crop_size));
 | ||||||
|  | +	} else
 | ||||||
|  | +		crop = THIN_CROP_METADATA_UNSELECTED;
 | ||||||
|  | +
 | ||||||
|  | +	return crop;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  int update_thin_pool_params(struct cmd_context *cmd, | ||||||
|  |  			    struct profile *profile, | ||||||
|  |  			    uint32_t extent_size, | ||||||
|  | @@ -669,10 +701,13 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  			    unsigned attr, | ||||||
|  |  			    uint32_t pool_data_extents, | ||||||
|  |  			    uint32_t *pool_metadata_extents, | ||||||
|  | +			    struct logical_volume *metadata_lv,
 | ||||||
|  | +			    thin_crop_metadata_t *crop_metadata,
 | ||||||
|  |  			    int *chunk_size_calc_method, uint32_t *chunk_size, | ||||||
|  |  			    thin_discards_t *discards, thin_zero_t *zero_new_blocks) | ||||||
|  |  { | ||||||
|  | -	uint64_t pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
 | ||||||
|  | +	uint64_t pool_metadata_size;
 | ||||||
|  | +	uint64_t max_metadata_size;
 | ||||||
|  |  	uint32_t estimate_chunk_size; | ||||||
|  |  	uint64_t max_pool_data_size; | ||||||
|  |  	const char *str; | ||||||
|  | @@ -702,7 +737,9 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  		*zero_new_blocks = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile) | ||||||
|  |  			? THIN_ZERO_YES : THIN_ZERO_NO; | ||||||
|  |   | ||||||
|  | -	if (!pool_metadata_size) {
 | ||||||
|  | +	max_metadata_size = get_thin_pool_max_metadata_size(cmd, profile, crop_metadata);
 | ||||||
|  | +
 | ||||||
|  | +	if (!*pool_metadata_extents) {
 | ||||||
|  |  		if (!*chunk_size) { | ||||||
|  |  			if (!get_default_allocation_thin_pool_chunk_size(cmd, profile, | ||||||
|  |  									 chunk_size, | ||||||
|  | @@ -723,20 +760,20 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  		} else { | ||||||
|  |  			pool_metadata_size = _estimate_metadata_size(pool_data_extents, extent_size, *chunk_size); | ||||||
|  |   | ||||||
|  | -			if (pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
 | ||||||
|  | +			if (pool_metadata_size > max_metadata_size) {
 | ||||||
|  |  				/* Suggest bigger chunk size */ | ||||||
|  |  				estimate_chunk_size = | ||||||
|  |  					_estimate_chunk_size(pool_data_extents, extent_size, | ||||||
|  | -							     (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2), attr);
 | ||||||
|  | +							     max_metadata_size, attr);
 | ||||||
|  |  				log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.", | ||||||
|  |  					 display_size(cmd, estimate_chunk_size)); | ||||||
|  |  			} | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		/* Round up to extent size silently */ | ||||||
|  | -		if (pool_metadata_size % extent_size)
 | ||||||
|  | -			pool_metadata_size += extent_size - pool_metadata_size % extent_size;
 | ||||||
|  | +		pool_metadata_size = dm_round_up(pool_metadata_size, extent_size);
 | ||||||
|  |  	} else { | ||||||
|  | +		pool_metadata_size = (uint64_t) *pool_metadata_extents * extent_size;
 | ||||||
|  |  		estimate_chunk_size = _estimate_chunk_size(pool_data_extents, extent_size, | ||||||
|  |  							   pool_metadata_size, attr); | ||||||
|  |   | ||||||
|  | @@ -751,7 +788,19 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	max_pool_data_size = _estimate_max_data_size(*chunk_size);
 | ||||||
|  | +	/* Use not rounded max for data size */
 | ||||||
|  | +	max_pool_data_size = _estimate_max_data_size(max_metadata_size, *chunk_size);
 | ||||||
|  | +
 | ||||||
|  | +	if (!update_pool_metadata_min_max(cmd, extent_size,
 | ||||||
|  | +					  2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE,
 | ||||||
|  | +					  max_metadata_size,
 | ||||||
|  | +					  &pool_metadata_size,
 | ||||||
|  | +					  metadata_lv,
 | ||||||
|  | +					  pool_metadata_extents))
 | ||||||
|  | +		return_0;
 | ||||||
|  | +
 | ||||||
|  | +	*crop_metadata = get_thin_pool_crop_metadata(cmd, *crop_metadata, pool_metadata_size);
 | ||||||
|  | +
 | ||||||
|  |  	if ((max_pool_data_size / extent_size) < pool_data_extents) { | ||||||
|  |  		log_error("Selected chunk size %s cannot address more then %s of thin pool data space.", | ||||||
|  |  			  display_size(cmd, *chunk_size), display_size(cmd, max_pool_data_size)); | ||||||
|  | @@ -764,22 +813,6 @@ int update_thin_pool_params(struct cmd_context *cmd,
 | ||||||
|  |  	if (!validate_thin_pool_chunk_size(cmd, *chunk_size)) | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  | -	if (pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
 | ||||||
|  | -		pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
 | ||||||
|  | -		if (*pool_metadata_extents)
 | ||||||
|  | -			log_warn("WARNING: Maximum supported pool metadata size is %s.",
 | ||||||
|  | -				 display_size(cmd, pool_metadata_size));
 | ||||||
|  | -	} else if (pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
 | ||||||
|  | -		pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
 | ||||||
|  | -		if (*pool_metadata_extents)
 | ||||||
|  | -			log_warn("WARNING: Minimum supported pool metadata size is %s.",
 | ||||||
|  | -				 display_size(cmd, pool_metadata_size));
 | ||||||
|  | -	}
 | ||||||
|  | -
 | ||||||
|  | -	if (!(*pool_metadata_extents =
 | ||||||
|  | -	      extents_from_size(cmd, pool_metadata_size, extent_size)))
 | ||||||
|  | -		return_0;
 | ||||||
|  | -
 | ||||||
|  |  	if ((uint64_t) *chunk_size > (uint64_t) pool_data_extents * extent_size) { | ||||||
|  |  		log_error("Size of %s data volume cannot be smaller than chunk size %s.", | ||||||
|  |  			  segtype->name, display_size(cmd, *chunk_size)); | ||||||
|  | @@ -958,12 +991,5 @@ int validate_thin_pool_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
 | ||||||
|  |   | ||||||
|  |  uint64_t estimate_thin_pool_metadata_size(uint32_t data_extents, uint32_t extent_size, uint32_t chunk_size) | ||||||
|  |  { | ||||||
|  | -	uint64_t sz = _estimate_metadata_size(data_extents, extent_size, chunk_size);
 | ||||||
|  | -
 | ||||||
|  | -	if (sz > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE))
 | ||||||
|  | -		sz = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
 | ||||||
|  | -	else if (sz < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE))
 | ||||||
|  | -		sz = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
 | ||||||
|  | -
 | ||||||
|  | -	return sz;
 | ||||||
|  | +	return _estimate_metadata_size(data_extents, extent_size, chunk_size);
 | ||||||
|  |  } | ||||||
|  | diff --git a/lib/thin/thin.c b/lib/thin/thin.c
 | ||||||
|  | index ba0da71..51bc269 100644
 | ||||||
|  | --- a/lib/thin/thin.c
 | ||||||
|  | +++ b/lib/thin/thin.c
 | ||||||
|  | @@ -86,6 +86,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
 | ||||||
|  |  	struct logical_volume *pool_data_lv, *pool_metadata_lv; | ||||||
|  |  	const char *discards_str = NULL; | ||||||
|  |  	uint32_t zero = 0; | ||||||
|  | +	uint32_t crop = 0;
 | ||||||
|  |   | ||||||
|  |  	if (!dm_config_get_str(sn, "metadata", &lv_name)) | ||||||
|  |  		return SEG_LOG_ERROR("Metadata must be a string in"); | ||||||
|  | @@ -131,6 +132,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
 | ||||||
|  |   | ||||||
|  |  	seg->zero_new_blocks = (zero) ? THIN_ZERO_YES : THIN_ZERO_NO; | ||||||
|  |   | ||||||
|  | +	if (dm_config_has_node(sn, "crop_metadata")) {
 | ||||||
|  | +		if (!dm_config_get_uint32(sn, "crop_metadata", &crop))
 | ||||||
|  | +			return SEG_LOG_ERROR("Could not read crop_metadata for");
 | ||||||
|  | +		seg->crop_metadata = (crop) ? THIN_CROP_METADATA_YES : THIN_CROP_METADATA_NO;
 | ||||||
|  | +		seg->lv->status |= LV_CROP_METADATA;
 | ||||||
|  | +	}
 | ||||||
|  | +
 | ||||||
|  |  	/* Read messages */ | ||||||
|  |  	for (; sn; sn = sn->sib) | ||||||
|  |  		if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child)) | ||||||
|  | @@ -177,6 +185,9 @@ static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (seg->crop_metadata != THIN_CROP_METADATA_UNSELECTED)
 | ||||||
|  | +		outf(f, "crop_metadata = %u", (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0);
 | ||||||
|  | +
 | ||||||
|  |  	dm_list_iterate_items(tmsg, &seg->thin_messages) { | ||||||
|  |  		/* Extra validation */ | ||||||
|  |  		switch (tmsg->type) { | ||||||
|  | @@ -307,11 +318,12 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
 | ||||||
|  |  	else | ||||||
|  |  		low_water_mark = 0; | ||||||
|  |   | ||||||
|  | -	if (!dm_tree_node_add_thin_pool_target(node, len,
 | ||||||
|  | -					       seg->transaction_id,
 | ||||||
|  | -					       metadata_dlid, pool_dlid,
 | ||||||
|  | -					       seg->chunk_size, low_water_mark,
 | ||||||
|  | -					       (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1))
 | ||||||
|  | +	if (!dm_tree_node_add_thin_pool_target_v1(node, len,
 | ||||||
|  | +						  seg->transaction_id,
 | ||||||
|  | +						  metadata_dlid, pool_dlid,
 | ||||||
|  | +						  seg->chunk_size, low_water_mark,
 | ||||||
|  | +						  (seg->zero_new_blocks == THIN_ZERO_YES) ? 0 : 1,
 | ||||||
|  | +						  (seg->crop_metadata == THIN_CROP_METADATA_YES) ? 1 : 0))
 | ||||||
|  |  		return_0; | ||||||
|  |   | ||||||
|  |  	if (attr & THIN_FEATURE_DISCARDS) { | ||||||
|  | diff --git a/man/lvmthin.7_main b/man/lvmthin.7_main
 | ||||||
|  | index e6f1d63..3ce34a5 100644
 | ||||||
|  | --- a/man/lvmthin.7_main
 | ||||||
|  | +++ b/man/lvmthin.7_main
 | ||||||
|  | @@ -1104,7 +1104,7 @@ The default value is shown by:
 | ||||||
|  |  The amount of thin metadata depends on how many blocks are shared between | ||||||
|  |  thin LVs (i.e. through snapshots).  A thin pool with many snapshots may | ||||||
|  |  need a larger metadata LV.  Thin pool metadata LV sizes can be from 2MiB | ||||||
|  | -to 16GiB.
 | ||||||
|  | +to approximately 16GiB.
 | ||||||
|  |   | ||||||
|  |  When using lvcreate to create what will become a thin metadata LV, the | ||||||
|  |  size is specified with the -L|--size option. | ||||||
|  | @@ -1119,6 +1119,14 @@ needed, so it is recommended to start with a size of 1GiB which should be
 | ||||||
|  |  enough for all practical purposes.  A thin pool metadata LV can later be | ||||||
|  |  manually or automatically extended if needed. | ||||||
|  |   | ||||||
|  | +Configurable setting
 | ||||||
|  | +.BR lvm.conf (5)
 | ||||||
|  | +.BR allocation / thin_pool_crop_metadata
 | ||||||
|  | +gives control over cropping to 15.81GiB to stay backward compatible with older
 | ||||||
|  | +versions of lvm2. With enabled cropping there can be observed some problems when
 | ||||||
|  | +using volumes above this size with thin tools (i.e. thin_repair).
 | ||||||
|  | +Cropping should be enabled only when compatibility is required.
 | ||||||
|  | +
 | ||||||
|  |   | ||||||
|  |  .SS Create a thin snapshot of an external, read only LV | ||||||
|  |   | ||||||
|  | diff --git a/tools/lvconvert.c b/tools/lvconvert.c
 | ||||||
|  | index 7b74afb..ce90279 100644
 | ||||||
|  | --- a/tools/lvconvert.c
 | ||||||
|  | +++ b/tools/lvconvert.c
 | ||||||
|  | @@ -3032,6 +3032,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
 | ||||||
|  |  	const char *policy_name; | ||||||
|  |  	struct dm_config_tree *policy_settings = NULL; | ||||||
|  |  	int pool_metadata_spare; | ||||||
|  | +	thin_crop_metadata_t crop_metadata;
 | ||||||
|  |  	thin_discards_t discards; | ||||||
|  |  	thin_zero_t zero_new_blocks; | ||||||
|  |  	int r = 0; | ||||||
|  | @@ -3196,6 +3197,8 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
 | ||||||
|  |  					     pool_segtype, target_attr, | ||||||
|  |  					     lv->le_count, | ||||||
|  |  					     &meta_extents, | ||||||
|  | +					     metadata_lv,
 | ||||||
|  | +					     &crop_metadata,
 | ||||||
|  |  					     &chunk_calc, | ||||||
|  |  					     &chunk_size, | ||||||
|  |  					     &discards, &zero_new_blocks)) | ||||||
|  | @@ -3401,6 +3404,7 @@ static int _lvconvert_to_pool(struct cmd_context *cmd,
 | ||||||
|  |  			goto_bad; | ||||||
|  |  	} else { | ||||||
|  |  		seg->transaction_id = 0; | ||||||
|  | +		seg->crop_metadata = crop_metadata;
 | ||||||
|  |  		seg->chunk_size = chunk_size; | ||||||
|  |  		seg->discards = discards; | ||||||
|  |  		seg->zero_new_blocks = zero_new_blocks; | ||||||
|  | diff --git a/tools/lvcreate.c b/tools/lvcreate.c
 | ||||||
|  | index e384291..1ee9e14 100644
 | ||||||
|  | --- a/tools/lvcreate.c
 | ||||||
|  | +++ b/tools/lvcreate.c
 | ||||||
|  | @@ -391,6 +391,8 @@ static int _update_extents_params(struct volume_group *vg,
 | ||||||
|  |  						     lp->segtype, lp->target_attr, | ||||||
|  |  						     lp->extents, | ||||||
|  |  						     &lp->pool_metadata_extents, | ||||||
|  | +						     NULL,
 | ||||||
|  | +						     &lp->crop_metadata,
 | ||||||
|  |  						     &lp->thin_chunk_size_calc_policy, | ||||||
|  |  						     &lp->chunk_size, | ||||||
|  |  						     &lp->discards, | ||||||
							
								
								
									
										194
									
								
								lvm2-2_03_12-vdo-support-online-rename.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								lvm2-2_03_12-vdo-support-online-rename.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,194 @@ | |||||||
|  |  conf/example.conf.in         | 10 ++++++++++ | ||||||
|  |  lib/config/config_settings.h |  9 +++++++++ | ||||||
|  |  lib/metadata/lv_manip.c      | 14 +++++++++++--- | ||||||
|  |  lib/metadata/segtype.h       |  2 ++ | ||||||
|  |  lib/vdo/vdo.c                | 46 ++++++++++++++++++++++++++++++++++++-------- | ||||||
|  |  5 files changed, 70 insertions(+), 11 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/conf/example.conf.in b/conf/example.conf.in
 | ||||||
|  | index cd53147..d02965e 100644
 | ||||||
|  | --- a/conf/example.conf.in
 | ||||||
|  | +++ b/conf/example.conf.in
 | ||||||
|  | @@ -1195,6 +1195,16 @@ global {
 | ||||||
|  |  	# This configuration option has an automatic default value. | ||||||
|  |  	# vdo_format_options = [ "" ] | ||||||
|  |   | ||||||
|  | +	# Configuration option global/vdo_disabled_features.
 | ||||||
|  | +	# Features to not use in the vdo driver.
 | ||||||
|  | +	# This can be helpful for testing, or to avoid using a feature that is
 | ||||||
|  | +	# causing problems. Features include: online_rename
 | ||||||
|  | +	#
 | ||||||
|  | +	# Example
 | ||||||
|  | +	# vdo_disabled_features = [ "online_rename" ]
 | ||||||
|  | +	#
 | ||||||
|  | +	# This configuration option does not have a default value defined.
 | ||||||
|  | +
 | ||||||
|  |  	# Configuration option global/fsadm_executable. | ||||||
|  |  	# The full path to the fsadm command. | ||||||
|  |  	# LVM uses this command to help with lvresize -r operations. | ||||||
|  | diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
 | ||||||
|  | index 3c4032e..f844594 100644
 | ||||||
|  | --- a/lib/config/config_settings.h
 | ||||||
|  | +++ b/lib/config/config_settings.h
 | ||||||
|  | @@ -1206,6 +1206,15 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
 | ||||||
|  |  cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL, | ||||||
|  |  	"List of options passed added to standard vdoformat command.\n") | ||||||
|  |   | ||||||
|  | +cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
 | ||||||
|  | +	"Features to not use in the vdo driver.\n"
 | ||||||
|  | +	"This can be helpful for testing, or to avoid using a feature that is\n"
 | ||||||
|  | +	"causing problems. Features include: online_rename\n"
 | ||||||
|  | +	"#\n"
 | ||||||
|  | +	"Example\n"
 | ||||||
|  | +	"vdo_disabled_features = [ \"online_rename\" ]\n"
 | ||||||
|  | +	"#\n")
 | ||||||
|  | +
 | ||||||
|  |  cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL, | ||||||
|  |  	"The full path to the fsadm command.\n" | ||||||
|  |  	"LVM uses this command to help with lvresize -r operations.\n") | ||||||
|  | diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
 | ||||||
|  | index c740ba2..6c71263 100644
 | ||||||
|  | --- a/lib/metadata/lv_manip.c
 | ||||||
|  | +++ b/lib/metadata/lv_manip.c
 | ||||||
|  | @@ -4738,6 +4738,8 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
 | ||||||
|  |  	struct lv_names lv_names = { .old = lv->name }; | ||||||
|  |  	int old_lv_is_historical = lv_is_historical(lv); | ||||||
|  |  	int historical; | ||||||
|  | +	unsigned attrs;
 | ||||||
|  | +	const struct segment_type *segtype;
 | ||||||
|  |   | ||||||
|  |  	/* | ||||||
|  |  	 * rename is not allowed on sub LVs except for pools | ||||||
|  | @@ -4763,9 +4765,15 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (lv_is_vdo_pool(lv) && lv_is_active(lv_lock_holder(lv))) { | ||||||
|  | -		log_error("Cannot rename active VDOPOOL volume %s.",
 | ||||||
|  | -			  display_lvname(lv));
 | ||||||
|  | -		return 0;
 | ||||||
|  | +		segtype = first_seg(lv)->segtype;
 | ||||||
|  | +		if (!segtype->ops->target_present ||
 | ||||||
|  | +		    !segtype->ops->target_present(lv->vg->cmd, NULL, &attrs) ||
 | ||||||
|  | +		    !(attrs & VDO_FEATURE_ONLINE_RENAME)) {
 | ||||||
|  | +			log_error("Cannot rename active VDOPOOL volume %s, "
 | ||||||
|  | +				  "VDO target feature support is missing.",
 | ||||||
|  | +				  display_lvname(lv));
 | ||||||
|  | +			return 0;
 | ||||||
|  | +		}
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (update_mda && !archive(vg)) | ||||||
|  | diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
 | ||||||
|  | index 08ddc35..2714a6b 100644
 | ||||||
|  | --- a/lib/metadata/segtype.h
 | ||||||
|  | +++ b/lib/metadata/segtype.h
 | ||||||
|  | @@ -349,6 +349,8 @@ int init_cache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
 | ||||||
|  |  int init_vdo_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +#define VDO_FEATURE_ONLINE_RENAME		(1U << 0) /* version 6.2.3 */
 | ||||||
|  | +
 | ||||||
|  |  int init_writecache_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); | ||||||
|  |   | ||||||
|  |  int init_integrity_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); | ||||||
|  | diff --git a/lib/vdo/vdo.c b/lib/vdo/vdo.c
 | ||||||
|  | index c43a5dc..bb7c784 100644
 | ||||||
|  | --- a/lib/vdo/vdo.c
 | ||||||
|  | +++ b/lib/vdo/vdo.c
 | ||||||
|  | @@ -25,6 +25,7 @@
 | ||||||
|  |  #include "lib/metadata/segtype.h" | ||||||
|  |  #include "base/memory/zalloc.h" | ||||||
|  |   | ||||||
|  | +static const char _vdo_module[] = MODULE_NAME_VDO;
 | ||||||
|  |  static unsigned _feature_mask; | ||||||
|  |   | ||||||
|  |  static int _bad_field(const char *field) | ||||||
|  | @@ -391,18 +392,21 @@ static int _vdo_target_present(struct cmd_context *cmd,
 | ||||||
|  |  	static const struct feature { | ||||||
|  |  		uint32_t maj; | ||||||
|  |  		uint32_t min; | ||||||
|  | +		uint32_t patchlevel;
 | ||||||
|  |  		unsigned vdo_feature; | ||||||
|  |  		const char *feature; | ||||||
|  |  	} _features[] = { | ||||||
|  | -		{ 1, 1, 0, "" },
 | ||||||
|  | -		//{ 9, 9, VDO_FEATURE_RESIZE, "resize" },
 | ||||||
|  | +		{ 6, 2, 3, VDO_FEATURE_ONLINE_RENAME, "online_rename" },
 | ||||||
|  |  	}; | ||||||
|  | -	//static const char _lvmconf[] = "global/vdo_disabled_features";
 | ||||||
|  | +	static const char _lvmconf[] = "global/vdo_disabled_features";
 | ||||||
|  |  	static int _vdo_checked = 0; | ||||||
|  |  	static int _vdo_present = 0; | ||||||
|  |  	static unsigned _vdo_attrs = 0; | ||||||
|  |  	uint32_t i, maj, min, patchlevel; | ||||||
|  |  	const struct segment_type *segtype; | ||||||
|  | +	const struct dm_config_node *cn;
 | ||||||
|  | +	const struct dm_config_value *cv;
 | ||||||
|  | +	const char *str;
 | ||||||
|  |   | ||||||
|  |  	if (!activation()) | ||||||
|  |  		return 0; | ||||||
|  | @@ -419,8 +423,8 @@ static int _vdo_target_present(struct cmd_context *cmd,
 | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		if (maj < 6 || (maj == 6 && min < 2)) { | ||||||
|  | -			log_warn("WARNING: VDO target version %u.%u.%u is too old.",
 | ||||||
|  | -				 maj, min, patchlevel);
 | ||||||
|  | +			log_warn("WARNING: Target %s version %u.%u.%u is too old.",
 | ||||||
|  | +				 _vdo_module, maj, min, patchlevel);
 | ||||||
|  |  			return 0; | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  | @@ -437,15 +441,41 @@ static int _vdo_target_present(struct cmd_context *cmd,
 | ||||||
|  |  		/* Prepare for adding supported features */ | ||||||
|  |  		for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) | ||||||
|  |  			if ((maj > _features[i].maj) || | ||||||
|  | -			    (maj == _features[i].maj && min >= _features[i].min))
 | ||||||
|  | +			    ((maj == _features[i].maj) && (min > _features[i].min)) ||
 | ||||||
|  | +			    ((maj == _features[i].maj) && (min == _features[i].min) && (patchlevel >= _features[i].patchlevel)))
 | ||||||
|  |  				_vdo_attrs |= _features[i].vdo_feature; | ||||||
|  |  			else | ||||||
|  |  				log_very_verbose("Target %s does not support %s.", | ||||||
|  | -						 TARGET_NAME_VDO,
 | ||||||
|  | +						 _vdo_module,
 | ||||||
|  |  						 _features[i].feature); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (attributes) { | ||||||
|  | +		if (!_feature_mask) {
 | ||||||
|  | +			/* Support runtime lvm.conf changes, N.B. avoid 32 feature */
 | ||||||
|  | +			if ((cn = find_config_tree_array(cmd, global_vdo_disabled_features_CFG, NULL))) {
 | ||||||
|  | +				for (cv = cn->v; cv; cv = cv->next) {
 | ||||||
|  | +					if (cv->type != DM_CFG_STRING) {
 | ||||||
|  | +						log_warn("WARNING: Ignoring invalid string in config file %s.",
 | ||||||
|  | +							  _lvmconf);
 | ||||||
|  | +						continue;
 | ||||||
|  | +					}
 | ||||||
|  | +					str = cv->v.str;
 | ||||||
|  | +					if (!*str)
 | ||||||
|  | +						continue;
 | ||||||
|  | +					for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
 | ||||||
|  | +						if (strcasecmp(str, _features[i].feature) == 0)
 | ||||||
|  | +							_feature_mask |= _features[i].vdo_feature;
 | ||||||
|  | +				}
 | ||||||
|  | +			}
 | ||||||
|  | +			_feature_mask = ~_feature_mask;
 | ||||||
|  | +			for (i = 0; i < DM_ARRAY_SIZE(_features); ++i)
 | ||||||
|  | +				if ((_vdo_attrs & _features[i].vdo_feature) &&
 | ||||||
|  | +				    !(_feature_mask & _features[i].vdo_feature))
 | ||||||
|  | +					log_very_verbose("Target %s %s support disabled by %s.",
 | ||||||
|  | +							 _vdo_module,
 | ||||||
|  | +							 _features[i].feature, _lvmconf);
 | ||||||
|  | +		}
 | ||||||
|  |  		*attributes = _vdo_attrs & _feature_mask; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | @@ -456,7 +486,7 @@ static int _vdo_modules_needed(struct dm_pool *mem,
 | ||||||
|  |  			   const struct lv_segment *seg __attribute__((unused)), | ||||||
|  |  			   struct dm_list *modules) | ||||||
|  |  { | ||||||
|  | -	if (!str_list_add(mem, modules, MODULE_NAME_VDO)) {
 | ||||||
|  | +	if (!str_list_add(mem, modules, _vdo_module)) {
 | ||||||
|  |  		log_error("String list allocation failed for VDO module."); | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  |  lib/metadata/writecache_manip.c | 10 +++++++--- | ||||||
|  |  tools/lvconvert.c               |  2 ++ | ||||||
|  |  2 files changed, 9 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/lib/metadata/writecache_manip.c b/lib/metadata/writecache_manip.c
 | ||||||
|  | index 5004aa9..8150d07 100644
 | ||||||
|  | --- a/lib/metadata/writecache_manip.c
 | ||||||
|  | +++ b/lib/metadata/writecache_manip.c
 | ||||||
|  | @@ -75,7 +75,7 @@ static int _get_writecache_kernel_status(struct cmd_context *cmd,
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 1, 1)) {
 | ||||||
|  | +	if (!lv_info_with_seg_status(cmd, first_seg(lv), &status, 0, 0)) {
 | ||||||
|  |  		log_error("Failed to get device mapper status for %s", display_lvname(lv)); | ||||||
|  |  		goto fail; | ||||||
|  |  	} | ||||||
|  | @@ -434,8 +434,12 @@ int lv_writecache_set_cleaner(struct logical_volume *lv)
 | ||||||
|  |  	seg->writecache_settings.cleaner_set = 1; | ||||||
|  |   | ||||||
|  |  	if (lv_is_active(lv)) { | ||||||
|  | -		if (!lv_update_and_reload(lv)) {
 | ||||||
|  | -			log_error("Failed to update VG and reload LV.");
 | ||||||
|  | +		if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
 | ||||||
|  | +			log_error("Failed to update VG.");
 | ||||||
|  | +			return 0;
 | ||||||
|  | +		}
 | ||||||
|  | +		if (!lv_writecache_message(lv, "cleaner")) {
 | ||||||
|  | +			log_error("Failed to set writecache cleaner for %s.", display_lvname(lv));
 | ||||||
|  |  			return 0; | ||||||
|  |  		} | ||||||
|  |  	} else { | ||||||
|  | diff --git a/tools/lvconvert.c b/tools/lvconvert.c
 | ||||||
|  | index 4323965..7b74afb 100644
 | ||||||
|  | --- a/tools/lvconvert.c
 | ||||||
|  | +++ b/tools/lvconvert.c
 | ||||||
|  | @@ -5720,6 +5720,8 @@ static int _lvconvert_detach_writecache_when_clean(struct cmd_context *cmd,
 | ||||||
|  |  		return 0; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	log_debug("detach writecache check clean reading vg %s", id->vg_name);
 | ||||||
|  | +
 | ||||||
|  |  	vg = vg_read(cmd, id->vg_name, NULL, READ_FOR_UPDATE, lockd_state, &error_flags, NULL); | ||||||
|  |   | ||||||
|  |  	if (!vg) { | ||||||
							
								
								
									
										96
									
								
								lvm2.spec
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								lvm2.spec
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| %global device_mapper_version 1.02.173 | %global device_mapper_version 1.02.175 | ||||||
| 
 | 
 | ||||||
| %global enable_cache 1 | %global enable_cache 1 | ||||||
| %global enable_cluster 1 | %global enable_cluster 1 | ||||||
| @ -11,6 +11,7 @@ | |||||||
| %global enable_testsuite 1 | %global enable_testsuite 1 | ||||||
| %global enable_vdo 1 | %global enable_vdo 1 | ||||||
| %global enable_writecache 1 | %global enable_writecache 1 | ||||||
|  | %global enable_integrity 1 | ||||||
| 
 | 
 | ||||||
| %global system_release_version 23 | %global system_release_version 23 | ||||||
| %global systemd_version 189-3 | %global systemd_version 189-3 | ||||||
| @ -56,12 +57,42 @@ Name: lvm2 | |||||||
| %if 0%{?rhel} | %if 0%{?rhel} | ||||||
| Epoch: %{rhel} | Epoch: %{rhel} | ||||||
| %endif | %endif | ||||||
| Version: 2.03.10 | Version: 2.03.11 | ||||||
| Release: 2%{?dist} | Release: 1%{?dist} | ||||||
| License: GPLv2 | License: GPLv2 | ||||||
| URL: http://sourceware.org/lvm2 | URL: http://sourceware.org/lvm2 | ||||||
| Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz | Source0: ftp://sourceware.org/pub/lvm2/releases/LVM2.%{version}.tgz | ||||||
| Patch0: lvm2-set-default-preferred_names.patch | Patch0: lvm2-set-default-preferred_names.patch | ||||||
|  | Patch3: lvm2-2_03_12-lvmlockd-sscanf-buffer-size-warnings.patch | ||||||
|  | # BZ 1915497: | ||||||
|  | Patch4: lvm2-2_03_12-alloc-enhance-estimation-of-sufficient_pes_free.patch | ||||||
|  | Patch5: lvm2-2_03_12-tests-check-thin-pool-corner-case-allocs.patch | ||||||
|  | Patch6: lvm2-2_03_12-tests-check-full-zeroing-of-thin-pool-metadata.patch | ||||||
|  | # BZ 1915580: | ||||||
|  | Patch7: lvm2-2_03_12-integrity-fix-segfault-on-error-path-when-replacing-.patch | ||||||
|  | # BZ 1872695: | ||||||
|  | Patch8: lvm2-2_03_12-devs-remove-invalid-path-name-aliases.patch | ||||||
|  | Patch9: lvm2-2_03_12-make-generate.patch | ||||||
|  | Patch10: lvm2-2_03_12-label_scan-fix-missing-free-of-filtered_devs.patch | ||||||
|  | # BZ 1917920: | ||||||
|  | Patch11: lvm2-2_03_12-pvck-fix-warning-and-exit-code-for-non-4k-mda1-offse.patch | ||||||
|  | Patch12: lvm2-2_03_12-WHATS_NEW-update.patch | ||||||
|  | # BZ 1921214: | ||||||
|  | Patch13: lvm2-2_03_12-writecache-use-cleaner-message-instead-of-table-relo.patch | ||||||
|  | # BZ 1909699: | ||||||
|  | Patch14: lvm2-2_03_12-man-update-lvmthin.patch | ||||||
|  | Patch15: lvm2-2_03_12-thin-improve-16g-support-for-thin-pool-metadata.patch | ||||||
|  | Patch16: lvm2-2_03_12-pool-limit-pmspare-to-16GiB.patch | ||||||
|  | Patch17: lvm2-2_03_12-cache-reuse-code-for-metadata-min_max.patch | ||||||
|  | Patch18: lvm2-2_03_12-tests-check-16G-thin-pool-metadata-size.patch | ||||||
|  | Patch19: lvm2-2_03_12-tests-update-thin-and-cache-checked-messages.patch | ||||||
|  | # BZ 1914389: | ||||||
|  | Patch20: lvm2-2_03_12-lvcreate-use-lv_passes_readonly_filter.patch | ||||||
|  | Patch21: lvm2-2_03_12-test-check-read_only_volume_list-tagging-works.patch | ||||||
|  | # BZ 1859659: | ||||||
|  | Patch22: lvm2-2_03_12-filter-mpath-work-with-nvme-devices.patch | ||||||
|  | # BZ 1925871: | ||||||
|  | Patch23: lvm2-2_03_12-dev_get_primary_dev-fix-invalid-path-check.patch | ||||||
| 
 | 
 | ||||||
| BuildRequires: make | BuildRequires: make | ||||||
| BuildRequires: gcc | BuildRequires: gcc | ||||||
| @ -118,7 +149,28 @@ or more physical volumes and creating one or more logical volumes | |||||||
| 
 | 
 | ||||||
| %prep | %prep | ||||||
| %setup -q -n LVM2.%{version} | %setup -q -n LVM2.%{version} | ||||||
| %patch0 -p1 -b .preferred_names | %patch0 -p1 -b .backup0 | ||||||
|  | %patch3 -p1 -b .backup3 | ||||||
|  | %patch4 -p1 -b .backup4 | ||||||
|  | %patch5 -p1 -b .backup5 | ||||||
|  | %patch6 -p1 -b .backup6 | ||||||
|  | %patch7 -p1 -b .backup7 | ||||||
|  | %patch8 -p1 -b .backup8 | ||||||
|  | %patch9 -p1 -b .backup9 | ||||||
|  | %patch10 -p1 -b .backup10 | ||||||
|  | %patch11 -p1 -b .backup11 | ||||||
|  | %patch12 -p1 -b .backup12 | ||||||
|  | %patch13 -p1 -b .backup13 | ||||||
|  | %patch14 -p1 -b .backup14 | ||||||
|  | %patch15 -p1 -b .backup15 | ||||||
|  | %patch16 -p1 -b .backup16 | ||||||
|  | %patch17 -p1 -b .backup17 | ||||||
|  | %patch18 -p1 -b .backup18 | ||||||
|  | %patch19 -p1 -b .backup19 | ||||||
|  | %patch20 -p1 -b .backup20 | ||||||
|  | %patch21 -p1 -b .backup21 | ||||||
|  | %patch22 -p1 -b .backup22 | ||||||
|  | %patch23 -p1 -b .backup23 | ||||||
| 
 | 
 | ||||||
| %build | %build | ||||||
| %global _default_pid_dir /run | %global _default_pid_dir /run | ||||||
| @ -165,12 +217,16 @@ or more physical volumes and creating one or more logical volumes | |||||||
| %global configure_writecache --with-writecache=internal | %global configure_writecache --with-writecache=internal | ||||||
| %endif | %endif | ||||||
| 
 | 
 | ||||||
|  | %if %{enable_integrity} | ||||||
|  | %global configure_integrity --with-integrity=internal | ||||||
|  | %endif | ||||||
|  | 
 | ||||||
| # NOTE: Using CFLAGS and LDFLAGS would override the fedora default flags, thus | # NOTE: Using CFLAGS and LDFLAGS would override the fedora default flags, thus | ||||||
| # using paths here... | # using paths here... | ||||||
| export CPATH="%{_includedir}/readline5" | export CPATH="%{_includedir}/readline5" | ||||||
| export LIBRARY_PATH="%{_libdir}/readline5" | export LIBRARY_PATH="%{_libdir}/readline5" | ||||||
| 
 | 
 | ||||||
| %configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_lvmdbusd} %{?configure_dmfilemapd} %{?configure_writecache} %{?configure_vdo} --disable-silent-rules | %configure --with-default-dm-run-dir=%{_default_dm_run_dir} --with-default-run-dir=%{_default_run_dir} --with-default-pid-dir=%{_default_pid_dir} --with-default-locking-dir=%{_default_locking_dir} --with-usrlibdir=%{_libdir} --enable-fsadm --enable-write_install --with-user= --with-group= --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --enable-pkgconfig --enable-cmdlib --enable-dmeventd --enable-blkid_wiping %{?configure_cluster} %{?configure_cmirror} %{?configure_udev} %{?configure_thin} %{?configure_cache} %{?configure_lvmpolld} %{?configure_lockd_dlm} %{?configure_lockd_sanlock} %{?configure_lvmdbusd} %{?configure_dmfilemapd} %{?configure_writecache} %{?configure_vdo} %{?configure_integrity} --disable-silent-rules | ||||||
| 
 | 
 | ||||||
| %make_build | %make_build | ||||||
| 
 | 
 | ||||||
| @ -724,6 +780,36 @@ An extensive functional testsuite for LVM2. | |||||||
| %endif | %endif | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Mon Feb 22 2021 Marian Csontos <mcsontos@redhat.com> - 2.03.11-1 | ||||||
|  | - Fix mpath filtering of NVMe devices. | ||||||
|  | - Check if lvcreate passes read_only_volume_list with tags and skips zeroing. | ||||||
|  | - Limit pool metadata spare to 16GiB. | ||||||
|  | - Improves conversion and allocation of pool metadata. | ||||||
|  | - Fix different limits used for metadata by lvm2 and thin-tools. | ||||||
|  | - Fix interrupting lvconvert --splitcache command with striped origin volumes. | ||||||
|  | - Fix problem with wiping of converted LVs. | ||||||
|  | - Fix memleak in scanning. | ||||||
|  | - Fix corner case allocation for thin-pools. | ||||||
|  | - Fix pvck handling MDA at offset different from 4096. | ||||||
|  | - Partial or degraded activation of writecache is not allowed. | ||||||
|  | - Enhance error handling in fsadm and handle correct fsck result. | ||||||
|  | - Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values. | ||||||
|  | - Support using BLKZEROOUT for clearing devices. | ||||||
|  | - Fixed interrup handling. | ||||||
|  | - Fix block cache when device has too many failing writes. | ||||||
|  | - Fix block cache waiting for IO completion with failing disks. | ||||||
|  | - Add configure --enable-editline support as an alternative to readline. | ||||||
|  | - Enhance reporting and error handling when creating thin volumes. | ||||||
|  | - Enable vgsplit for VDO volumes. | ||||||
|  | - Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added. | ||||||
|  | - Restore lost signal blocking while VG lock is held. | ||||||
|  | - Improve estimation of needed extents when creating thin-pool. | ||||||
|  | - Use extra 1% when resizing thin-pool metadata LV with --use-policy. | ||||||
|  | - Enhance --use-policy percentage rounding. | ||||||
|  | - Allow pvmove of writecache origin. | ||||||
|  | - Report integrity fields. | ||||||
|  | - Integrity volumes defaults to journal mode. | ||||||
|  | 
 | ||||||
| * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.03.10-2 | * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.03.10-2 | ||||||
| - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild | - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sources
									
									
									
									
									
								
							| @ -1 +1 @@ | |||||||
| SHA512 (LVM2.2.03.10.tgz) = 8678ae2f99739ccad0250f6f4b4b8e84520f2053835985a1ea9c80196a64df31a48858aebf983170c3dfcafecea83f2c6aa630ef73fd31dd84cf1627a1b421e4 | SHA512 (LVM2.2.03.11.tgz) = 50f21337e397fc5b4692bb08e5d48409b907b96b39168343bab2d40bb74fd84ff466e15f3d664305bc044f3f6be4369fa7378399d5a838793632e74706f17653 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user