mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	Compare commits
	
		
			34 Commits
		
	
	
		
			dev-mcsont
			...
			v2_03_27
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					207990a877 | ||
| 
						 | 
					ec965dde39 | ||
| 
						 | 
					b77f7acac8 | ||
| 
						 | 
					ca02546649 | ||
| 
						 | 
					493d8908fb | ||
| 
						 | 
					9d6a3ee547 | ||
| 
						 | 
					bd5ca83c43 | ||
| 
						 | 
					5096335277 | ||
| 
						 | 
					e009becd73 | ||
| 
						 | 
					4524778b23 | ||
| 
						 | 
					d5d2c98980 | ||
| 
						 | 
					84cabd068b | ||
| 
						 | 
					4708a354f6 | ||
| 
						 | 
					28e7be9f39 | ||
| 
						 | 
					0e1e220c3d | ||
| 
						 | 
					7f29afdb06 | ||
| 
						 | 
					6816366ff1 | ||
| 
						 | 
					7447634c26 | ||
| 
						 | 
					0862e2b150 | ||
| 
						 | 
					74f607952d | ||
| 
						 | 
					cb781b3e1d | ||
| 
						 | 
					964012fdb9 | ||
| 
						 | 
					7e2bb2a35e | ||
| 
						 | 
					e9413fb211 | ||
| 
						 | 
					9d7c19c2ce | ||
| 
						 | 
					d7a028aaad | ||
| 
						 | 
					1c3d7dfb07 | ||
| 
						 | 
					86a9db05cf | ||
| 
						 | 
					f42aef4706 | ||
| 
						 | 
					1b68841605 | ||
| 
						 | 
					e8383073a9 | ||
| 
						 | 
					1e48599193 | ||
| 
						 | 
					f7f08ba881 | ||
| 
						 | 
					de196f4b60 | 
@@ -1 +1 @@
 | 
			
		||||
1.02.201-git (2024-08-23)
 | 
			
		||||
1.02.201 (2024-10-02)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								WHATS_NEW
									
									
									
									
									
								
							@@ -1,5 +1,11 @@
 | 
			
		||||
Version 2.03.27 - 
 | 
			
		||||
==================
 | 
			
		||||
Version 2.03.27 - 02nd October 2024
 | 
			
		||||
===================================
 | 
			
		||||
  Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
 | 
			
		||||
  Detect GPT partition table and pass partition filter if no partitions defined.
 | 
			
		||||
  Add global/sanlock_align_size option to configure sanlock lease size.
 | 
			
		||||
  Disable mem locking when activation/reserved_stack or reserved_memory is 0.
 | 
			
		||||
  Fix locking issues in lvmlockd leaving thin pool locked.
 | 
			
		||||
  Deprecate vdo settings vdo_write_policy and vdo_write_policy.
 | 
			
		||||
  Lots of typo fixes across lvm2 code base (codespell).
 | 
			
		||||
  Corrected integrity parameter interleave_sectors for DM table line.
 | 
			
		||||
  Ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV, like raid10.
 | 
			
		||||
@@ -429,7 +435,7 @@ Version 2.03.03 - 07th June 2019
 | 
			
		||||
  Improve -lXXX%VG modifier which improves cache segment estimation.
 | 
			
		||||
  Ensure migration_threshold for cache is at least 8 chunks.
 | 
			
		||||
  Restore missing man info lvcreate --zero for thin-pools.
 | 
			
		||||
  Drop misleadning comment for metadata minimum_io_size for VDO segment.
 | 
			
		||||
  Drop misleading comment for metadata minimum_io_size for VDO segment.
 | 
			
		||||
  Add device hints to reduce scanning.
 | 
			
		||||
  Introduce LVM_SUPPRESS_SYSLOG to suppress syslog usage by generator.
 | 
			
		||||
  Fix generator querying lvmconfig unpresent config option.
 | 
			
		||||
@@ -555,7 +561,7 @@ Version 2.02.177 - 18th December 2017
 | 
			
		||||
  Fix lvmlockd to use pool lock when accessing _tmeta volume.
 | 
			
		||||
  Report expected sanlock_convert errors only when retries fail.
 | 
			
		||||
  Avoid blocking in sanlock_convert on SH to EX lock conversion.
 | 
			
		||||
  Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on decativation.
 | 
			
		||||
  Deactivate missing raid LV legs (_rimage_X-missing_Y_Z) on deactivation.
 | 
			
		||||
  Skip read-modify-write when entire block is replaced.
 | 
			
		||||
  Categorise I/O with reason annotations in debug messages.
 | 
			
		||||
  Allow extending of raid LVs created with --nosync after a failed repair.
 | 
			
		||||
@@ -577,7 +583,7 @@ Version 2.02.177 - 18th December 2017
 | 
			
		||||
  Check raid reshape flags in vg_validate().
 | 
			
		||||
  Add support for pvmove of cache and snapshot origins.
 | 
			
		||||
  Avoid using precommitted metadata for suspending pvmove tree.
 | 
			
		||||
  Ehnance pvmove locking.
 | 
			
		||||
  Enhance pvmove locking.
 | 
			
		||||
  Deactivate activated LVs on error path when pvmove activation fails.
 | 
			
		||||
  Add "io" to log/debug_classes for logging low-level I/O.
 | 
			
		||||
  Eliminate redundant nested VG metadata in VG struct.
 | 
			
		||||
@@ -1154,7 +1160,7 @@ Version 2.02.143 - 21st February 2016
 | 
			
		||||
  Fix error path when sending thin-pool message fails in update_pool_lv().
 | 
			
		||||
  Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
 | 
			
		||||
  For failing thin-pool and thin volume correctly report percentage as INVALID.
 | 
			
		||||
  Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
 | 
			
		||||
  Report -1, not 'unknown' for lv_{snapshot_invalid,merge_failed} with --binary.
 | 
			
		||||
  Add configure --enable-dbus-service for an LVM D-Bus service.
 | 
			
		||||
  Replace configure --enable-python_bindings with python2 and python3 versions.
 | 
			
		||||
  If PV belongs to some VG and metadata missing, skip it if system ID is used.
 | 
			
		||||
@@ -1183,7 +1189,7 @@ Version 2.02.141 - 25th January 2016
 | 
			
		||||
  Restore support for command breaking in process_each_lv_in_vg() (2.02.118).
 | 
			
		||||
  Use correct mempool when process_each_lv_in_vg() (2.02.118).
 | 
			
		||||
  Fix lvm.8 man to show again prohibited suffixes.
 | 
			
		||||
  Fix configure to set proper use_blkid_wiping if autodetected as disabled.
 | 
			
		||||
  Fix configure to set proper use_blkid_wiping if autodetection as disabled.
 | 
			
		||||
  Initialise udev in clvmd for use in device scanning. (2.02.116)
 | 
			
		||||
  Add seg_le_ranges report field for common format when displaying seg devices.
 | 
			
		||||
  Honour report/list_item_separator for seg_metadata_le_ranges report field.
 | 
			
		||||
@@ -4702,7 +4708,7 @@ Version 2.02.11 - 12th October 2006
 | 
			
		||||
  Capture error messages in clvmd and pass them back to the user.
 | 
			
		||||
  Remove unused #defines from filter-md.c.
 | 
			
		||||
  Make clvmd restart init script wait until clvmd has died before starting it.
 | 
			
		||||
  Add -R to clvmd which tells running clvmds to reload their device cache.
 | 
			
		||||
  Add -R to clvmd which tells running clvmd to reload their device cache.
 | 
			
		||||
  Add LV column to reports listing kernel modules needed for activation.
 | 
			
		||||
  Show available fields if report given invalid field. (e.g. lvs -o list)
 | 
			
		||||
  Add timestamp functions with --disable-realtime configure option.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
Version 1.02.201 - 
 | 
			
		||||
===================
 | 
			
		||||
Version 1.02.201 - 02nd October 2024
 | 
			
		||||
====================================
 | 
			
		||||
  Cleanup udev sync semaphore if dm_{udev_create,task_set}_cookie fails.
 | 
			
		||||
  Improve error messages on failed udev cookie create/inc/dec operation.
 | 
			
		||||
 | 
			
		||||
Version 1.02.200 - 23rd August 2024
 | 
			
		||||
===================================
 | 
			
		||||
 
 | 
			
		||||
@@ -646,13 +646,6 @@ allocation {
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# vdo_use_deduplication = 1
 | 
			
		||||
 | 
			
		||||
	# Configuration option allocation/vdo_use_metadata_hints.
 | 
			
		||||
	# Enables or disables whether VDO volume should tag its latency-critical
 | 
			
		||||
	# writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5
 | 
			
		||||
	# process writes with this flag at a higher priority.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# vdo_use_metadata_hints = 1
 | 
			
		||||
 | 
			
		||||
	# Configuration option allocation/vdo_minimum_io_size.
 | 
			
		||||
	# The minimum IO size for VDO volume to accept, in bytes.
 | 
			
		||||
	# Valid values are 512 or 4096. The recommended value is 4096.
 | 
			
		||||
@@ -751,19 +744,6 @@ allocation {
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# vdo_physical_threads = 1
 | 
			
		||||
 | 
			
		||||
	# Configuration option allocation/vdo_write_policy.
 | 
			
		||||
	# Specifies the write policy:
 | 
			
		||||
	# auto  - VDO will check the storage device and determine whether it supports flushes.
 | 
			
		||||
	#         If it does, VDO will run in async mode, otherwise it will run in sync mode.
 | 
			
		||||
	# sync  - Writes are acknowledged only after data is stably written.
 | 
			
		||||
	#         This policy is not supported if the underlying storage is not also synchronous.
 | 
			
		||||
	# async - Writes are acknowledged after data has been cached for writing to stable storage.
 | 
			
		||||
	#         Data which has not been flushed is not guaranteed to persist in this mode.
 | 
			
		||||
	# async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.
 | 
			
		||||
	#         This mode should only be used for better performance when atomicity is not required.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# vdo_write_policy = "auto"
 | 
			
		||||
 | 
			
		||||
	# Configuration option allocation/vdo_max_discard.
 | 
			
		||||
	# Specified the maximum size of discard bio accepted, in 4096 byte blocks.
 | 
			
		||||
	# I/O requests to a VDO volume are normally split into 4096-byte blocks,
 | 
			
		||||
@@ -1212,6 +1192,16 @@ global {
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# sanlock_lv_extend = 256
 | 
			
		||||
 | 
			
		||||
	# Configuration option global/sanlock_align_size.
 | 
			
		||||
	# The sanlock lease size in MiB to use on disks with a 4K sector size.
 | 
			
		||||
	# Possible values are 1,2,4,8.  The default is 8, which supports up to
 | 
			
		||||
	# 2000 hosts (and max host_id 2000.)  Smaller values support smaller
 | 
			
		||||
	# numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for
 | 
			
		||||
	# lease sizes 1,2,4,8.  Disks with 512 byte sectors always use 1MiB
 | 
			
		||||
	# leases and support 2000 hosts, and are not affected by this setting.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# sanlock_align_size = 8
 | 
			
		||||
 | 
			
		||||
	# Configuration option global/lvmlockctl_kill_command.
 | 
			
		||||
	# The command that lvmlockctl --kill should use to force LVs offline.
 | 
			
		||||
	# The lvmlockctl --kill command is run when a shared VG has lost
 | 
			
		||||
@@ -1515,12 +1505,14 @@ activation {
 | 
			
		||||
	# Configuration option activation/reserved_stack.
 | 
			
		||||
	# Stack size in KiB to reserve for use while devices are suspended.
 | 
			
		||||
	# Insufficient reserve risks I/O deadlock during device suspension.
 | 
			
		||||
	# Value 0 disables memory locking.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# reserved_stack = 64
 | 
			
		||||
 | 
			
		||||
	# Configuration option activation/reserved_memory.
 | 
			
		||||
	# Memory size in KiB to reserve for use while devices are suspended.
 | 
			
		||||
	# Insufficient reserve risks I/O deadlock during device suspension.
 | 
			
		||||
	# Value 0 disables memory locking.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# reserved_memory = 8192
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,10 @@ local {
 | 
			
		||||
	# This configuration option does not have a default value defined.
 | 
			
		||||
 | 
			
		||||
	# Configuration option local/host_id.
 | 
			
		||||
	# The lvmlockd sanlock host_id.
 | 
			
		||||
	# This must be unique among all hosts, and must be between 1 and 2000.
 | 
			
		||||
	# Applicable only if LVM is compiled with lockd support
 | 
			
		||||
	# The sanlock host_id used by lvmlockd. This must be unique among all the hosts
 | 
			
		||||
	# using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size
 | 
			
		||||
	# is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.
 | 
			
		||||
	# Applicable only if LVM is compiled with support for lvmlockd+sanlock.
 | 
			
		||||
	# This configuration option has an automatic default value.
 | 
			
		||||
	# host_id = 0
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@
 | 
			
		||||
allocation {
 | 
			
		||||
	vdo_use_compression=1
 | 
			
		||||
	vdo_use_deduplication=1
 | 
			
		||||
	vdo_use_metadata_hints=1
 | 
			
		||||
	vdo_minimum_io_size=4096
 | 
			
		||||
	vdo_block_map_cache_size_mb=128
 | 
			
		||||
	vdo_block_map_period=16380
 | 
			
		||||
@@ -18,6 +17,5 @@ allocation {
 | 
			
		||||
	vdo_hash_zone_threads=1
 | 
			
		||||
	vdo_logical_threads=1
 | 
			
		||||
	vdo_physical_threads=1
 | 
			
		||||
	vdo_write_policy="auto"
 | 
			
		||||
	vdo_max_discard=1
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,7 @@ def process_args():
 | 
			
		||||
 | 
			
		||||
def running_under_systemd():
 | 
			
		||||
	""""
 | 
			
		||||
	Checks to see if we are running under systemd, by checking damon fd 0, 1
 | 
			
		||||
	Checks to see if we are running under systemd, by checking daemon fd 0, 1
 | 
			
		||||
	systemd sets stdin to /dev/null and 1 & 2 are a socket
 | 
			
		||||
	"""
 | 
			
		||||
	base = "/proc/self/fd"
 | 
			
		||||
@@ -214,7 +214,7 @@ def main():
 | 
			
		||||
		cfg.loop = GLib.MainLoop()
 | 
			
		||||
 | 
			
		||||
		for thread in thread_list:
 | 
			
		||||
			thread.damon = True
 | 
			
		||||
			thread.daemon = True
 | 
			
		||||
			thread.start()
 | 
			
		||||
 | 
			
		||||
		# In all cases we are going to monitor for udev until we get an
 | 
			
		||||
 
 | 
			
		||||
@@ -1177,12 +1177,12 @@ static void lm_rem_resource(struct lockspace *ls, struct resource *r)
 | 
			
		||||
		lm_rem_resource_idm(ls, r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
 | 
			
		||||
static int lm_find_free_lock(struct lockspace *ls, uint64_t lv_size_bytes)
 | 
			
		||||
{
 | 
			
		||||
	if (ls->lm_type == LD_LM_DLM)
 | 
			
		||||
		return 0;
 | 
			
		||||
	else if (ls->lm_type == LD_LM_SANLOCK)
 | 
			
		||||
		return lm_find_free_lock_sanlock(ls, free_offset, sector_size, align_size);
 | 
			
		||||
		return lm_find_free_lock_sanlock(ls, lv_size_bytes);
 | 
			
		||||
	else if (ls->lm_type == LD_LM_IDM)
 | 
			
		||||
		return 0;
 | 
			
		||||
	return -1;
 | 
			
		||||
@@ -2712,17 +2712,10 @@ static void *lockspace_thread_main(void *arg_in)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (act->op == LD_OP_FIND_FREE_LOCK && act->rt == LD_RT_VG) {
 | 
			
		||||
				uint64_t free_offset = 0;
 | 
			
		||||
				int sector_size = 0;
 | 
			
		||||
				int align_size = 0;
 | 
			
		||||
 | 
			
		||||
				log_debug("S %s find free lock", ls->name);
 | 
			
		||||
				rv = lm_find_free_lock(ls, &free_offset, §or_size, &align_size);
 | 
			
		||||
				log_debug("S %s find free lock %d offset %llu sector_size %d align_size %d",
 | 
			
		||||
					  ls->name, rv, (unsigned long long)free_offset, sector_size, align_size);
 | 
			
		||||
				ls->free_lock_offset = free_offset;
 | 
			
		||||
				ls->free_lock_sector_size = sector_size;
 | 
			
		||||
				ls->free_lock_align_size = align_size;
 | 
			
		||||
				rv = lm_find_free_lock(ls, act->lv_size_bytes);
 | 
			
		||||
				log_debug("S %s find free lock %d offset %llu",
 | 
			
		||||
					  ls->name, rv, (unsigned long long)ls->free_lock_offset);
 | 
			
		||||
				list_del(&act->list);
 | 
			
		||||
				act->result = rv;
 | 
			
		||||
				add_client_result(act);
 | 
			
		||||
@@ -3556,7 +3549,7 @@ static int work_init_vg(struct action *act)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (act->lm_type == LD_LM_SANLOCK)
 | 
			
		||||
		rv = lm_init_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
 | 
			
		||||
		rv = lm_init_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args, act->align_mb);
 | 
			
		||||
	else if (act->lm_type == LD_LM_DLM)
 | 
			
		||||
		rv = lm_init_vg_dlm(ls_name, act->vg_name, act->flags, act->vg_args);
 | 
			
		||||
	else if (act->lm_type == LD_LM_IDM)
 | 
			
		||||
@@ -3622,9 +3615,6 @@ static int work_init_lv(struct action *act)
 | 
			
		||||
	char ls_name[MAX_NAME+1];
 | 
			
		||||
	char vg_args[MAX_ARGS+1];
 | 
			
		||||
	char lv_args[MAX_ARGS+1];
 | 
			
		||||
	uint64_t free_offset = 0;
 | 
			
		||||
	int sector_size = 0;
 | 
			
		||||
	int align_size = 0;
 | 
			
		||||
	int lm_type = 0;
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
 | 
			
		||||
@@ -3639,9 +3629,6 @@ static int work_init_lv(struct action *act)
 | 
			
		||||
	if (ls) {
 | 
			
		||||
		lm_type = ls->lm_type;
 | 
			
		||||
		memcpy(vg_args, ls->vg_args, MAX_ARGS);
 | 
			
		||||
		free_offset = ls->free_lock_offset;
 | 
			
		||||
		sector_size = ls->free_lock_sector_size;
 | 
			
		||||
		align_size = ls->free_lock_align_size;
 | 
			
		||||
	}
 | 
			
		||||
	pthread_mutex_unlock(&lockspaces_mutex);
 | 
			
		||||
 | 
			
		||||
@@ -3657,8 +3644,13 @@ static int work_init_lv(struct action *act)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (lm_type == LD_LM_SANLOCK) {
 | 
			
		||||
		rv = lm_init_lv_sanlock(ls_name, act->vg_name, act->lv_uuid,
 | 
			
		||||
					vg_args, lv_args, sector_size, align_size, free_offset);
 | 
			
		||||
		/* FIXME: can init_lv ever be called without the lockspace already started? */
 | 
			
		||||
		if (!ls) {
 | 
			
		||||
			log_error("init_lv no lockspace found");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rv = lm_init_lv_sanlock(ls, act->lv_uuid, vg_args, lv_args);
 | 
			
		||||
 | 
			
		||||
		memcpy(act->lv_args, lv_args, MAX_ARGS);
 | 
			
		||||
		return rv;
 | 
			
		||||
@@ -5032,6 +5024,12 @@ static void client_recv_action(struct client *cl)
 | 
			
		||||
	if (val)
 | 
			
		||||
		act->host_id = val;
 | 
			
		||||
 | 
			
		||||
	val = daemon_request_int(req, "align_mb", 0);
 | 
			
		||||
	if (val)
 | 
			
		||||
		act->align_mb = val;
 | 
			
		||||
 | 
			
		||||
	act->lv_size_bytes = (uint64_t)dm_config_find_int64(req.cft->root, "lv_size_bytes", 0);
 | 
			
		||||
 | 
			
		||||
	/* Create PV list for idm */
 | 
			
		||||
	if (lm == LD_LM_IDM) {
 | 
			
		||||
		memset(&pvs, 0x0, sizeof(pvs));
 | 
			
		||||
 
 | 
			
		||||
@@ -132,6 +132,7 @@ struct action {
 | 
			
		||||
	uint32_t flags;			/* LD_AF_ */
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
	uint64_t host_id;
 | 
			
		||||
	uint64_t lv_size_bytes;
 | 
			
		||||
	int8_t op;			/* operation type LD_OP_ */
 | 
			
		||||
	int8_t rt;			/* resource type LD_RT_ */
 | 
			
		||||
	int8_t mode;			/* lock mode LD_LK_ */
 | 
			
		||||
@@ -140,6 +141,7 @@ struct action {
 | 
			
		||||
	int max_retries;
 | 
			
		||||
	int result;
 | 
			
		||||
	int lm_rv;			/* return value from lm_ function */
 | 
			
		||||
	int align_mb;
 | 
			
		||||
	char *path;
 | 
			
		||||
	char vg_uuid[64];
 | 
			
		||||
	char vg_name[MAX_NAME+1];
 | 
			
		||||
@@ -191,8 +193,6 @@ struct lockspace {
 | 
			
		||||
	void *lm_data;
 | 
			
		||||
	uint64_t host_id;
 | 
			
		||||
	uint64_t free_lock_offset;	/* for sanlock, start search for free lock here */
 | 
			
		||||
	int free_lock_sector_size;	/* for sanlock */
 | 
			
		||||
	int free_lock_align_size;	/* for sanlock */
 | 
			
		||||
	struct pvs pvs;			/* for idm: PV list */
 | 
			
		||||
 | 
			
		||||
	uint32_t start_client_id;	/* client_id that started the lockspace */
 | 
			
		||||
@@ -505,8 +505,8 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
 | 
			
		||||
 | 
			
		||||
#ifdef LOCKDSANLOCK_SUPPORT
 | 
			
		||||
 | 
			
		||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
 | 
			
		||||
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset);
 | 
			
		||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb);
 | 
			
		||||
int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args);
 | 
			
		||||
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
 | 
			
		||||
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
 | 
			
		||||
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
 | 
			
		||||
@@ -527,7 +527,7 @@ int lm_gl_is_enabled(struct lockspace *ls);
 | 
			
		||||
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
 | 
			
		||||
int lm_data_size_sanlock(void);
 | 
			
		||||
int lm_is_running_sanlock(void);
 | 
			
		||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size);
 | 
			
		||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
 | 
			
		||||
 | 
			
		||||
static inline int lm_support_sanlock(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -536,12 +536,12 @@ static inline int lm_support_sanlock(void)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
 | 
			
		||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
 | 
			
		||||
{
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, int sector_size, int align_size, uint64_t free_offset)
 | 
			
		||||
static inline int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args)
 | 
			
		||||
{
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
@@ -630,7 +630,7 @@ static inline int lm_is_running_sanlock(void)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
 | 
			
		||||
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
 | 
			
		||||
{
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -145,6 +145,8 @@ struct lm_sanlock {
 | 
			
		||||
	int sector_size;
 | 
			
		||||
	int align_size;
 | 
			
		||||
	int sock; /* sanlock daemon connection */
 | 
			
		||||
	uint32_t ss_flags; /* sector and align flags for lockspace */
 | 
			
		||||
	uint32_t rs_flags; /* sector and align flags for resource */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rd_sanlock {
 | 
			
		||||
@@ -339,14 +341,16 @@ fail:
 | 
			
		||||
	return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _read_sysfs_size(dev_t devno, const char *name, unsigned int *val)
 | 
			
		||||
static void _read_sysfs_size(dev_t devno, const char *name, uint64_t *val)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	char buf[32];
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	size_t len;
 | 
			
		||||
 | 
			
		||||
	snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/queue/%s",
 | 
			
		||||
	*val = 0;
 | 
			
		||||
 | 
			
		||||
	snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s",
 | 
			
		||||
		 (int)major(devno), (int)minor(devno), name);
 | 
			
		||||
 | 
			
		||||
	if (!(fp = fopen(path, "r")))
 | 
			
		||||
@@ -359,20 +363,19 @@ static void _read_sysfs_size(dev_t devno, const char *name, unsigned int *val)
 | 
			
		||||
		buf[--len] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (strlen(buf))
 | 
			
		||||
		*val = atoi(buf);
 | 
			
		||||
		*val = strtoull(buf, NULL, 0);
 | 
			
		||||
out:
 | 
			
		||||
	if (fclose(fp))
 | 
			
		||||
		log_debug("Failed to fclose host id file %s (%s).", path, strerror(errno));
 | 
			
		||||
 | 
			
		||||
	(void)fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Select sector/align size for a new VG based on what the device reports for
 | 
			
		||||
   sector size of the lvmlock LV. */
 | 
			
		||||
 | 
			
		||||
static int get_sizes_device(char *path, int *sector_size, int *align_size)
 | 
			
		||||
static int get_sizes_device(char *path, uint64_t *dev_size, int *sector_size, int *align_size, int *align_mb)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int physical_block_size = 0;
 | 
			
		||||
	unsigned int logical_block_size = 0;
 | 
			
		||||
	uint64_t val;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	int rv;
 | 
			
		||||
 | 
			
		||||
@@ -382,18 +385,26 @@ static int get_sizes_device(char *path, int *sector_size, int *align_size)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_read_sysfs_size(st.st_rdev, "physical_block_size", &physical_block_size);
 | 
			
		||||
	_read_sysfs_size(st.st_rdev, "logical_block_size", &logical_block_size);
 | 
			
		||||
	_read_sysfs_size(st.st_rdev, "size", &val);
 | 
			
		||||
	*dev_size = val * 512;
 | 
			
		||||
 | 
			
		||||
	_read_sysfs_size(st.st_rdev, "queue/physical_block_size", &val);
 | 
			
		||||
	physical_block_size = (unsigned int)val;
 | 
			
		||||
 | 
			
		||||
	_read_sysfs_size(st.st_rdev, "queue/logical_block_size", &val);
 | 
			
		||||
	logical_block_size = (unsigned int)val;
 | 
			
		||||
 | 
			
		||||
	if ((physical_block_size == 512) && (logical_block_size == 512)) {
 | 
			
		||||
		*sector_size = 512;
 | 
			
		||||
		*align_size = ONE_MB;
 | 
			
		||||
		*align_mb = 1;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((physical_block_size == 4096) && (logical_block_size == 4096)) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_size = 8 * ONE_MB;
 | 
			
		||||
		*align_mb = 8;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -428,6 +439,7 @@ static int get_sizes_device(char *path, int *sector_size, int *align_size)
 | 
			
		||||
			 physical_block_size, logical_block_size, path);
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_size = 8 * ONE_MB;
 | 
			
		||||
		*align_mb = 8;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -436,18 +448,21 @@ static int get_sizes_device(char *path, int *sector_size, int *align_size)
 | 
			
		||||
			 physical_block_size, logical_block_size, path);
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_size = 8 * ONE_MB;
 | 
			
		||||
		*align_mb = 8;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (physical_block_size == 512) {
 | 
			
		||||
		*sector_size = 512;
 | 
			
		||||
		*align_size = ONE_MB;
 | 
			
		||||
		*align_mb = 1;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (physical_block_size == 4096) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_size = 8 * ONE_MB;
 | 
			
		||||
		*align_mb = 8;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -459,7 +474,8 @@ static int get_sizes_device(char *path, int *sector_size, int *align_size)
 | 
			
		||||
/* Get the sector/align sizes that were used to create an existing VG.
 | 
			
		||||
   sanlock encoded this in the lockspace/resource structs on disk. */
 | 
			
		||||
 | 
			
		||||
static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
 | 
			
		||||
static int get_sizes_lockspace(char *path, int *sector_size, int *align_size, int *align_mb,
 | 
			
		||||
			       uint32_t *ss_flags, uint32_t *rs_flags)
 | 
			
		||||
{
 | 
			
		||||
	struct sanlk_lockspace ss;
 | 
			
		||||
	uint32_t io_timeout = 0;
 | 
			
		||||
@@ -477,10 +493,38 @@ static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
 | 
			
		||||
 | 
			
		||||
	if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_mb = 8;
 | 
			
		||||
		*align_size = 8 * ONE_MB;
 | 
			
		||||
		*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
 | 
			
		||||
		*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M;
 | 
			
		||||
 | 
			
		||||
	} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN4M)) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_mb = 4;
 | 
			
		||||
		*align_size = 4 * ONE_MB;
 | 
			
		||||
		*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
 | 
			
		||||
		*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN4M;
 | 
			
		||||
 | 
			
		||||
	} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN2M)) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_mb = 2;
 | 
			
		||||
		*align_size = 2 * ONE_MB;
 | 
			
		||||
		*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
 | 
			
		||||
		*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN2M;
 | 
			
		||||
 | 
			
		||||
	} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN1M)) {
 | 
			
		||||
		*sector_size = 4096;
 | 
			
		||||
		*align_mb = 1;
 | 
			
		||||
		*align_size = ONE_MB;
 | 
			
		||||
		*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
 | 
			
		||||
		*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN1M;
 | 
			
		||||
 | 
			
		||||
	} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
 | 
			
		||||
		*sector_size = 512;
 | 
			
		||||
		*align_mb = 1;
 | 
			
		||||
		*align_size = ONE_MB;
 | 
			
		||||
		*ss_flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
 | 
			
		||||
		*rs_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("get_sizes_lockspace found %d %d", *sector_size, *align_size);
 | 
			
		||||
@@ -497,7 +541,7 @@ static int get_sizes_lockspace(char *path, int *sector_size, int *align_size)
 | 
			
		||||
 | 
			
		||||
#define MAX_VERSION 16
 | 
			
		||||
 | 
			
		||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
 | 
			
		||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
 | 
			
		||||
{
 | 
			
		||||
	struct sanlk_lockspace ss;
 | 
			
		||||
	struct sanlk_resourced rd;
 | 
			
		||||
@@ -505,11 +549,14 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
	char lock_lv_name[MAX_ARGS+1];
 | 
			
		||||
	char lock_args_version[MAX_VERSION+1];
 | 
			
		||||
	const char *gl_name = NULL;
 | 
			
		||||
	uint32_t rs_flags;
 | 
			
		||||
	uint32_t daemon_version;
 | 
			
		||||
	uint32_t daemon_proto;
 | 
			
		||||
	uint64_t offset;
 | 
			
		||||
	uint64_t dev_size;
 | 
			
		||||
	int sector_size = 0;
 | 
			
		||||
	int align_size = 0;
 | 
			
		||||
	int align_mb = 0;
 | 
			
		||||
	int i, rv;
 | 
			
		||||
 | 
			
		||||
	memset(&ss, 0, sizeof(ss));
 | 
			
		||||
@@ -534,7 +581,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
	if ((rv = build_dm_path(disk.path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
 | 
			
		||||
		return rv;
 | 
			
		||||
 | 
			
		||||
	log_debug("S %s init_vg_san path %s", ls_name, disk.path);
 | 
			
		||||
	log_debug("S %s init_vg_san path %s align %d", ls_name, disk.path, opt_align_mb);
 | 
			
		||||
 | 
			
		||||
	if (daemon_test) {
 | 
			
		||||
		if (!gl_lsname_sanlock[0])
 | 
			
		||||
@@ -555,7 +602,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
		  daemon_version, daemon_proto);
 | 
			
		||||
 | 
			
		||||
	/* Nothing formatted on disk yet, use what the device reports. */
 | 
			
		||||
	rv = get_sizes_device(disk.path, §or_size, &align_size);
 | 
			
		||||
	rv = get_sizes_device(disk.path, &dev_size, §or_size, &align_size, &align_mb);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		if (rv == -EACCES) {
 | 
			
		||||
			log_error("S %s init_vg_san sanlock error -EACCES: no permission to access %s",
 | 
			
		||||
@@ -568,11 +615,48 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Non-default lease size is requested. */
 | 
			
		||||
	if ((sector_size == 4096) && opt_align_mb && (opt_align_mb != 8)) {
 | 
			
		||||
		if (opt_align_mb != 1 && opt_align_mb != 2 && opt_align_mb != 4) {
 | 
			
		||||
			log_error("S %s init_vg_sanlock invalid align input %u", ls_name, opt_align_mb);
 | 
			
		||||
			return -EARGS;
 | 
			
		||||
		}
 | 
			
		||||
		align_mb = opt_align_mb;
 | 
			
		||||
		align_size = align_mb * ONE_MB;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("S %s init_vg_san %s dev_size %llu sector_size %u align_size %u",
 | 
			
		||||
		  ls_name, disk.path, (unsigned long long)dev_size, sector_size, align_size);
 | 
			
		||||
 | 
			
		||||
	strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
 | 
			
		||||
	memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
 | 
			
		||||
	ss.host_id_disk.offset = 0;
 | 
			
		||||
	ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
 | 
			
		||||
					   (SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
 | 
			
		||||
 | 
			
		||||
	if (sector_size == 512) {
 | 
			
		||||
		ss.flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
 | 
			
		||||
		rs_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
 | 
			
		||||
	} else if (sector_size == 4096) {
 | 
			
		||||
		if (align_mb == 8) {
 | 
			
		||||
			ss.flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
 | 
			
		||||
			rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M;
 | 
			
		||||
		} else if (align_mb == 4) {
 | 
			
		||||
			ss.flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
 | 
			
		||||
			rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN4M;
 | 
			
		||||
		} else if (align_mb == 2) {
 | 
			
		||||
			ss.flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
 | 
			
		||||
			rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN2M;
 | 
			
		||||
		} else if (align_mb == 1) {
 | 
			
		||||
			ss.flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
 | 
			
		||||
			rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN1M;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			log_error("Invalid sanlock align_size %d %d", align_size, align_mb);
 | 
			
		||||
			return -EARGS;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log_error("Invalid sanlock sector_size %d", sector_size);
 | 
			
		||||
		return -EARGS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
@@ -605,8 +689,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
 | 
			
		||||
	rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
					      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd.rs.flags = rs_flags;
 | 
			
		||||
 | 
			
		||||
	rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
@@ -620,8 +703,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
 | 
			
		||||
	rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
					      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd.rs.flags = rs_flags;
 | 
			
		||||
 | 
			
		||||
	rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
@@ -647,8 +729,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
 | 
			
		||||
	memset(&rd, 0, sizeof(rd));
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
					      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd.rs.flags = rs_flags;
 | 
			
		||||
	memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
 | 
			
		||||
	strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
 | 
			
		||||
	strcpy_name_len(rd.rs.name, "#unused", SANLK_NAME_LEN);
 | 
			
		||||
@@ -658,6 +739,9 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
	log_debug("S %s init_vg_san clearing lv lease areas", ls_name);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; ; i++) {
 | 
			
		||||
		if (dev_size && (offset + align_size > dev_size))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		rd.rs.disks[0].offset = offset;
 | 
			
		||||
 | 
			
		||||
		rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
 | 
			
		||||
@@ -686,14 +770,14 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
 | 
			
		||||
 * can be saved in the lv's lock_args in the vg metadata.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
		       char *vg_args, char *lv_args,
 | 
			
		||||
		       int sector_size, int align_size, uint64_t free_offset)
 | 
			
		||||
int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_args)
 | 
			
		||||
{
 | 
			
		||||
	struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
 | 
			
		||||
	struct sanlk_resourced rd;
 | 
			
		||||
	char lock_lv_name[MAX_ARGS+1];
 | 
			
		||||
	char lock_args_version[MAX_VERSION+1];
 | 
			
		||||
	uint64_t offset;
 | 
			
		||||
	int align_size = lms->align_size;
 | 
			
		||||
	int rv;
 | 
			
		||||
 | 
			
		||||
	memset(&rd, 0, sizeof(rd));
 | 
			
		||||
@@ -703,7 +787,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
	rv = lock_lv_name_from_args(vg_args, lock_lv_name);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
 | 
			
		||||
			  ls_name, rv, vg_args);
 | 
			
		||||
			  ls->name, rv, vg_args);
 | 
			
		||||
		return rv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -711,7 +795,6 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
		 LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
 | 
			
		||||
 | 
			
		||||
	if (daemon_test) {
 | 
			
		||||
		align_size = ONE_MB;
 | 
			
		||||
		snprintf(lv_args, MAX_ARGS, "%s:%llu",
 | 
			
		||||
			 lock_args_version,
 | 
			
		||||
			 (unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
 | 
			
		||||
@@ -719,42 +802,15 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
 | 
			
		||||
	strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
 | 
			
		||||
	if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, ls->vg_name, lock_lv_name)))
 | 
			
		||||
		return rv;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * These should not usually be zero, maybe only the first time this function is called?
 | 
			
		||||
	 * We need to use the same sector/align sizes that are already being used.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!sector_size || !align_size) {
 | 
			
		||||
		rv = get_sizes_lockspace(rd.rs.disks[0].path, §or_size, &align_size);
 | 
			
		||||
		if (rv < 0) {
 | 
			
		||||
			log_error("S %s init_lv_san read_lockspace error %d %s",
 | 
			
		||||
				  ls_name, rv, rd.rs.disks[0].path);
 | 
			
		||||
			return rv;
 | 
			
		||||
		}
 | 
			
		||||
	rd.rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
		if (sector_size)
 | 
			
		||||
			log_debug("S %s init_lv_san found ls sector_size %d align_size %d", ls_name, sector_size, align_size);
 | 
			
		||||
		else {
 | 
			
		||||
			/* use the old method */
 | 
			
		||||
			align_size = sanlock_align(&rd.rs.disks[0]);
 | 
			
		||||
			if (align_size <= 0) {
 | 
			
		||||
				log_error("S %s init_lv_san align error %d", ls_name, align_size);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			sector_size = (align_size == ONE_MB) ? 512 : 4096;
 | 
			
		||||
			log_debug("S %s init_lv_san found old sector_size %d align_size %d", ls_name, sector_size, align_size);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
					      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
 | 
			
		||||
	if (free_offset)
 | 
			
		||||
		offset = free_offset;
 | 
			
		||||
	if (ls->free_lock_offset)
 | 
			
		||||
		offset = ls->free_lock_offset;
 | 
			
		||||
	else
 | 
			
		||||
		offset = align_size * LV_LOCK_BEGIN;
 | 
			
		||||
	rd.rs.disks[0].offset = offset;
 | 
			
		||||
@@ -768,20 +824,20 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
		if (rv == -EMSGSIZE || rv == -ENOSPC) {
 | 
			
		||||
			/* This indicates the end of the device is reached. */
 | 
			
		||||
			log_debug("S %s init_lv_san read limit offset %llu",
 | 
			
		||||
				  ls_name, (unsigned long long)offset);
 | 
			
		||||
				  ls->name, (unsigned long long)offset);
 | 
			
		||||
			rv = -EMSGSIZE;
 | 
			
		||||
			return rv;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rv && rv != SANLK_LEADER_MAGIC) {
 | 
			
		||||
			log_error("S %s init_lv_san read error %d offset %llu",
 | 
			
		||||
				  ls_name, rv, (unsigned long long)offset);
 | 
			
		||||
				  ls->name, rv, (unsigned long long)offset);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!strncmp(rd.rs.name, lv_name, SANLK_NAME_LEN)) {
 | 
			
		||||
			log_error("S %s init_lv_san resource name %s already exists at %llu",
 | 
			
		||||
				  ls_name, lv_name, (unsigned long long)offset);
 | 
			
		||||
				  ls->name, lv_name, (unsigned long long)offset);
 | 
			
		||||
			return -EEXIST;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -792,11 +848,10 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
		 */
 | 
			
		||||
		if ((rv == SANLK_LEADER_MAGIC) || !strcmp(rd.rs.name, "#unused")) {
 | 
			
		||||
			log_debug("S %s init_lv_san %s found unused area at %llu",
 | 
			
		||||
				  ls_name, lv_name, (unsigned long long)offset);
 | 
			
		||||
				  ls->name, lv_name, (unsigned long long)offset);
 | 
			
		||||
 | 
			
		||||
			strcpy_name_len(rd.rs.name, lv_name, SANLK_NAME_LEN);
 | 
			
		||||
			rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
							      (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
			rd.rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
			rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
 | 
			
		||||
			if (!rv) {
 | 
			
		||||
@@ -804,7 +859,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
 | 
			
		||||
				         lock_args_version, (unsigned long long)offset);
 | 
			
		||||
			} else {
 | 
			
		||||
				log_error("S %s init_lv_san write error %d offset %llu",
 | 
			
		||||
					  ls_name, rv, (unsigned long long)rv);
 | 
			
		||||
					  ls->name, rv, (unsigned long long)rv);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
@@ -873,12 +928,19 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
 | 
			
		||||
		return rv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN8M)) {
 | 
			
		||||
		sector_size = 4096;
 | 
			
		||||
		align_size = 8 * ONE_MB;
 | 
			
		||||
	} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
 | 
			
		||||
	if (ss.flags & SANLK_LSF_SECTOR512) {
 | 
			
		||||
		sector_size = 512;
 | 
			
		||||
		align_size = ONE_MB;
 | 
			
		||||
	} else if (ss.flags & SANLK_LSF_SECTOR4K) {
 | 
			
		||||
		sector_size = 4096;
 | 
			
		||||
		if (ss.flags & SANLK_LSF_ALIGN8M)
 | 
			
		||||
			align_size = 8 * ONE_MB;
 | 
			
		||||
		else if (ss.flags & SANLK_LSF_ALIGN4M)
 | 
			
		||||
			align_size = 4 * ONE_MB;
 | 
			
		||||
		else if (ss.flags & SANLK_LSF_ALIGN2M)
 | 
			
		||||
			align_size = 2 * ONE_MB;
 | 
			
		||||
		else if (ss.flags & SANLK_LSF_ALIGN1M)
 | 
			
		||||
			align_size = ONE_MB;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* use the old method */
 | 
			
		||||
		align_size = sanlock_align(&ss.host_id_disk);
 | 
			
		||||
@@ -1047,10 +1109,8 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
 | 
			
		||||
	memcpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
 | 
			
		||||
	rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
 | 
			
		||||
	
 | 
			
		||||
	rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
						    (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd2.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
						    (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd1.rs.flags = lms->rs_flags;
 | 
			
		||||
	rd2.rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
	rv = sanlock_acquire(lms->sock, -1, 0, 1, &rs1, NULL);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
@@ -1112,8 +1172,7 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
 | 
			
		||||
	rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
 | 
			
		||||
	rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
						   (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd.rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
	rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
@@ -1197,7 +1256,7 @@ int lm_gl_is_enabled(struct lockspace *ls)
 | 
			
		||||
 * been disabled.)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
 | 
			
		||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
 | 
			
		||||
	struct sanlk_resourced rd;
 | 
			
		||||
@@ -1207,22 +1266,16 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
 | 
			
		||||
	int round = 0;
 | 
			
		||||
 | 
			
		||||
	if (daemon_test) {
 | 
			
		||||
		*free_offset = (ONE_MB * LV_LOCK_BEGIN) + (ONE_MB * (daemon_test_lv_count + 1));
 | 
			
		||||
		*sector_size = 512;
 | 
			
		||||
		*align_size = ONE_MB;
 | 
			
		||||
		ls->free_lock_offset = (ONE_MB * LV_LOCK_BEGIN) + (ONE_MB * (daemon_test_lv_count + 1));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*sector_size = lms->sector_size;
 | 
			
		||||
	*align_size = lms->align_size;
 | 
			
		||||
 | 
			
		||||
	memset(&rd, 0, sizeof(rd));
 | 
			
		||||
 | 
			
		||||
	strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
 | 
			
		||||
	rd.rs.num_disks = 1;
 | 
			
		||||
	memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
 | 
			
		||||
	rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
 | 
			
		||||
						   (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rd.rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
	if (ls->free_lock_offset)
 | 
			
		||||
		offset = ls->free_lock_offset;
 | 
			
		||||
@@ -1244,15 +1297,37 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
 | 
			
		||||
 | 
			
		||||
		memset(rd.rs.name, 0, SANLK_NAME_LEN);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * End of the device. Older lvm versions didn't pass lv_size_bytes
 | 
			
		||||
		 * and just relied on sanlock_read_resource returning an error when
 | 
			
		||||
		 * reading beyond the device.
 | 
			
		||||
		 */
 | 
			
		||||
		if (lv_size_bytes && (offset + lms->align_size > lv_size_bytes)) {
 | 
			
		||||
			/* end of the device */
 | 
			
		||||
			log_debug("S %s find_free_lock_san read limit offset %llu lv_size_bytes %llu",
 | 
			
		||||
				  ls->name, (unsigned long long)offset, (unsigned long long)lv_size_bytes);
 | 
			
		||||
 | 
			
		||||
			/* remember the NO SPACE offset, if no free area left,
 | 
			
		||||
			 * search from this offset after extend */
 | 
			
		||||
			ls->free_lock_offset = offset;
 | 
			
		||||
 | 
			
		||||
			offset = lms->align_size * LV_LOCK_BEGIN;
 | 
			
		||||
			round = 1;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rv = sanlock_read_resource(&rd.rs, 0);
 | 
			
		||||
		if (rv == -EMSGSIZE || rv == -ENOSPC) {
 | 
			
		||||
			/* This indicates the end of the device is reached. */
 | 
			
		||||
			/*
 | 
			
		||||
			 * These errors indicate the end of the device is reached.
 | 
			
		||||
			 * Still check this in case lv_size_bytes is not provided.
 | 
			
		||||
			 */
 | 
			
		||||
			log_debug("S %s find_free_lock_san read limit offset %llu",
 | 
			
		||||
				  ls->name, (unsigned long long)offset);
 | 
			
		||||
 | 
			
		||||
			/* remember the NO SPACE offset, if no free area left,
 | 
			
		||||
			 * search from this offset after extend */
 | 
			
		||||
			*free_offset = offset;
 | 
			
		||||
			ls->free_lock_offset = offset;
 | 
			
		||||
 | 
			
		||||
			offset = lms->align_size * LV_LOCK_BEGIN;
 | 
			
		||||
			round = 1;
 | 
			
		||||
@@ -1267,7 +1342,7 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
 | 
			
		||||
		if (rv == SANLK_LEADER_MAGIC) {
 | 
			
		||||
			log_debug("S %s find_free_lock_san found empty area at %llu",
 | 
			
		||||
				  ls->name, (unsigned long long)offset);
 | 
			
		||||
			*free_offset = offset;
 | 
			
		||||
			ls->free_lock_offset = offset;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1280,7 +1355,7 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
 | 
			
		||||
		if (!strcmp(rd.rs.name, "#unused")) {
 | 
			
		||||
			log_debug("S %s find_free_lock_san found unused area at %llu",
 | 
			
		||||
				  ls->name, (unsigned long long)offset);
 | 
			
		||||
			*free_offset = offset;
 | 
			
		||||
			ls->free_lock_offset = offset;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1322,8 +1397,11 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
 | 
			
		||||
	char disk_path[SANLK_PATH_LEN];
 | 
			
		||||
	char killpath[SANLK_PATH_LEN];
 | 
			
		||||
	char killargs[SANLK_PATH_LEN];
 | 
			
		||||
	uint32_t ss_flags = 0;
 | 
			
		||||
	uint32_t rs_flags = 0;
 | 
			
		||||
	int sector_size = 0;
 | 
			
		||||
	int align_size = 0;
 | 
			
		||||
	int align_mb = 0;
 | 
			
		||||
	int gl_found;
 | 
			
		||||
	int ret, rv;
 | 
			
		||||
 | 
			
		||||
@@ -1411,6 +1489,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
 | 
			
		||||
			strncpy(gl_lsname_sanlock, lsname, MAX_NAME);
 | 
			
		||||
			log_debug("S %s prepare_lockspace_san use global lock", lsname);
 | 
			
		||||
		}
 | 
			
		||||
		lms->align_size = ONE_MB;
 | 
			
		||||
		lms->sector_size = 512;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1438,7 +1518,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv = get_sizes_lockspace(disk_path, §or_size, &align_size);
 | 
			
		||||
	rv = get_sizes_lockspace(disk_path, §or_size, &align_size, &align_mb, &ss_flags, &rs_flags);
 | 
			
		||||
	if (rv < 0) {
 | 
			
		||||
		log_error("S %s prepare_lockspace_san cannot get sector/align sizes %d", lsname, rv);
 | 
			
		||||
		ret = -EMANAGER;
 | 
			
		||||
@@ -1458,13 +1538,27 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
 | 
			
		||||
		log_debug("S %s prepare_lockspace_san found old sector_size %d align_size %d", lsname, sector_size, align_size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("S %s prepare_lockspace_san sizes %d %d", lsname, sector_size, align_size);
 | 
			
		||||
	log_debug("S %s prepare_lockspace_san sector_size %d align_mb %d align_size %d",
 | 
			
		||||
		  lsname, sector_size, align_mb, align_size);
 | 
			
		||||
 | 
			
		||||
	if (sector_size == 4096) {
 | 
			
		||||
		if (((align_mb == 1) && (ls->host_id > 250)) ||
 | 
			
		||||
		    ((align_mb == 2) && (ls->host_id > 500)) ||
 | 
			
		||||
		    ((align_mb == 4) && (ls->host_id > 1000)) ||
 | 
			
		||||
		    ((align_mb == 8) && (ls->host_id > 2000))) {
 | 
			
		||||
			log_error("S %s prepare_lockspace_san invalid host_id %llu for align %d MiB",
 | 
			
		||||
				  lsname, (unsigned long long)ls->host_id, align_mb);
 | 
			
		||||
			ret = -EHOSTID;
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lms->align_size = align_size;
 | 
			
		||||
	lms->sector_size = sector_size;
 | 
			
		||||
	lms->ss_flags = ss_flags;
 | 
			
		||||
	lms->rs_flags = rs_flags;
 | 
			
		||||
 | 
			
		||||
	lms->ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
 | 
			
		||||
						(SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M);
 | 
			
		||||
	lms->ss.flags = ss_flags;
 | 
			
		||||
 | 
			
		||||
	gl_found = gl_is_enabled(ls, lms);
 | 
			
		||||
	if (gl_found < 0) {
 | 
			
		||||
@@ -1606,7 +1700,7 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
 | 
			
		||||
	strcpy_name_len(rds->rs.name, r->name, SANLK_NAME_LEN);
 | 
			
		||||
	rds->rs.num_disks = 1;
 | 
			
		||||
	memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
 | 
			
		||||
	rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
 | 
			
		||||
	rds->rs.flags = lms->rs_flags;
 | 
			
		||||
 | 
			
		||||
	if (r->type == LD_RT_GL)
 | 
			
		||||
		rds->rs.disks[0].offset = GL_LOCK_BEGIN * lms->align_size;
 | 
			
		||||
 
 | 
			
		||||
@@ -2167,7 +2167,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
 | 
			
		||||
 */
 | 
			
		||||
#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001
 | 
			
		||||
/*
 | 
			
		||||
 * DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable
 | 
			
		||||
 * DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG is set in case we need to disable
 | 
			
		||||
 * subsystem udev rules, but still we need the general DM udev rules to
 | 
			
		||||
 * be applied (to create the nodes and symlinks under /dev and /dev/disk).
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -2437,20 +2437,20 @@ static int _udev_notify_sem_inc(uint32_t cookie, int semid)
 | 
			
		||||
	int val;
 | 
			
		||||
 | 
			
		||||
	if (semop(semid, &sb, 1) < 0) {
 | 
			
		||||
		log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
		log_error("cookie inc: semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
		log_warn("cookie inc: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
 | 
			
		||||
		  cookie, semid, val);
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented.",
 | 
			
		||||
				      cookie, semid);
 | 
			
		||||
	} else
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
 | 
			
		||||
				     cookie, semid, val);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -2460,23 +2460,21 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
 | 
			
		||||
	struct sembuf sb = {0, -1, IPC_NOWAIT};
 | 
			
		||||
	int val;
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0)
 | 
			
		||||
		log_warn("cookie dec: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			 "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			 semid, cookie, strerror(errno));
 | 
			
		||||
 | 
			
		||||
	if (semop(semid, &sb, 1) < 0) {
 | 
			
		||||
		switch (errno) {
 | 
			
		||||
			case EAGAIN:
 | 
			
		||||
				log_error("semid %d: semop failed for cookie "
 | 
			
		||||
				log_error("cookie dec: semid %d: semop failed for cookie "
 | 
			
		||||
					  "0x%" PRIx32 ": "
 | 
			
		||||
					  "incorrect semaphore state",
 | 
			
		||||
					  semid, cookie);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				log_error("semid %d: semop failed for cookie "
 | 
			
		||||
				log_error("cookie dec: semid %d: semop failed for cookie "
 | 
			
		||||
					  "0x%" PRIx32 ": %s",
 | 
			
		||||
					  semid, cookie, strerror(errno));
 | 
			
		||||
				break;
 | 
			
		||||
@@ -2484,9 +2482,12 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
 | 
			
		||||
			     cookie, semid, val - 1);
 | 
			
		||||
 | 
			
		||||
	if (val < 0)
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented.",
 | 
			
		||||
				     cookie, semid);
 | 
			
		||||
	else
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
 | 
			
		||||
				     cookie, semid, val - 1);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2563,7 +2564,7 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
 | 
			
		||||
	sem_arg.val = 1;
 | 
			
		||||
 | 
			
		||||
	if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) {
 | 
			
		||||
		log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
 | 
			
		||||
		log_error("cookie create: semid %d: semctl failed: %s", gen_semid, strerror(errno));
 | 
			
		||||
		/* We have to destroy just created semaphore
 | 
			
		||||
		 * so it won't stay in the system. */
 | 
			
		||||
		(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
 | 
			
		||||
@@ -2571,9 +2572,10 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(gen_semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
		log_error("cookie create: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  gen_semid, gen_cookie, strerror(errno));
 | 
			
		||||
		(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								doc/release-notes/2.03.27.mdwn
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								doc/release-notes/2.03.27.mdwn
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<!-- Page title -->
 | 
			
		||||
[[!meta title="Version 2.03.27 - Bug Fix Release"]]
 | 
			
		||||
 | 
			
		||||
Version 2.03.27
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
* Deprecate vdo settings `vdo_write_policy` and `vdo_write_policy`.
 | 
			
		||||
* Do not accept duplicate device names for pvcreate.
 | 
			
		||||
* Fix swap device size detection using blkid for lvresize/lvreduce/lvextend.
 | 
			
		||||
* Detect GPT partition table and pass partition filter if no partitions defined.
 | 
			
		||||
* Add `global/sanlock_align_size` option to configure sanlock lease size.
 | 
			
		||||
* Disable mem locking when `activation/reserved_stack` or `reserved_memory` is `0`.
 | 
			
		||||
* Fix locking issues in lvmlockd leaving thin pool inactive but locked.
 | 
			
		||||
* Corrected integrity parameter `interleave_sectors` for DM table line.
 | 
			
		||||
* Ignore `-i|--stripes`, `-I|--stripesize` for lvextend on raid0 LV, like on raid10.
 | 
			
		||||
* Fix lot of typos across lvm2 code base (codespell).
 | 
			
		||||
* Cleanup udev sync semaphore if `dm_{udev_create,task_set}_cookie` fails.
 | 
			
		||||
* Improve error messages on failed udev cookie create/inc/dec operation.
 | 
			
		||||
 | 
			
		||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
 | 
			
		||||
[[!tag]]
 | 
			
		||||
<!--
 | 
			
		||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
 | 
			
		||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
@@ -203,7 +203,8 @@ static int _settings_text_export(const struct lv_segment *seg,
 | 
			
		||||
 | 
			
		||||
static int _cache_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
				   const struct dm_config_node *sn,
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
				   struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *data_lv, *meta_lv;
 | 
			
		||||
	const char *str = NULL;
 | 
			
		||||
@@ -212,7 +213,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
		return SEG_LOG_ERROR("Cache data not specified in");
 | 
			
		||||
	if (!(str = dm_config_find_str(sn, "data", NULL)))
 | 
			
		||||
		return SEG_LOG_ERROR("Cache data must be a string in");
 | 
			
		||||
	if (!(data_lv = find_lv(seg->lv->vg, str)))
 | 
			
		||||
	if (!(data_lv = dm_hash_lookup(lv_hash, str)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
				     "cache data in", str);
 | 
			
		||||
 | 
			
		||||
@@ -220,7 +221,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
		return SEG_LOG_ERROR("Cache metadata not specified in");
 | 
			
		||||
	if (!(str = dm_config_find_str(sn, "metadata", NULL)))
 | 
			
		||||
		return SEG_LOG_ERROR("Cache metadata must be a string in");
 | 
			
		||||
	if (!(meta_lv = find_lv(seg->lv->vg, str)))
 | 
			
		||||
	if (!(meta_lv = dm_hash_lookup(lv_hash, str)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
				     "cache metadata in", str);
 | 
			
		||||
 | 
			
		||||
@@ -439,7 +440,8 @@ static const struct segtype_handler _cache_pool_ops = {
 | 
			
		||||
 | 
			
		||||
static int _cache_text_import(struct lv_segment *seg,
 | 
			
		||||
			      const struct dm_config_node *sn,
 | 
			
		||||
			      struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
			      struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
			      struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *pool_lv, *origin_lv;
 | 
			
		||||
	const char *name;
 | 
			
		||||
@@ -449,7 +451,7 @@ static int _cache_text_import(struct lv_segment *seg,
 | 
			
		||||
		return SEG_LOG_ERROR("cache_pool not specified in");
 | 
			
		||||
	if (!(name = dm_config_find_str(sn, "cache_pool", NULL)))
 | 
			
		||||
		return SEG_LOG_ERROR("cache_pool must be a string in");
 | 
			
		||||
	if (!(pool_lv = find_lv(seg->lv->vg, name)))
 | 
			
		||||
	if (!(pool_lv = dm_hash_lookup(lv_hash, name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
				     "cache_pool in", name);
 | 
			
		||||
 | 
			
		||||
@@ -457,7 +459,7 @@ static int _cache_text_import(struct lv_segment *seg,
 | 
			
		||||
		return SEG_LOG_ERROR("Cache origin not specified in");
 | 
			
		||||
	if (!(name = dm_config_find_str(sn, "origin", NULL)))
 | 
			
		||||
		return SEG_LOG_ERROR("Cache origin must be a string in");
 | 
			
		||||
	if (!(origin_lv = find_lv(seg->lv->vg, name)))
 | 
			
		||||
	if (!(origin_lv = dm_hash_lookup(lv_hash, name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
				     "cache origin in", name);
 | 
			
		||||
	if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
 | 
			
		||||
 
 | 
			
		||||
@@ -271,7 +271,7 @@ struct cmd_context {
 | 
			
		||||
	/*
 | 
			
		||||
	 * Buffers.
 | 
			
		||||
	 */
 | 
			
		||||
	char display_buffer[NAME_LEN * 10];	/* ring buffer for upto 10 longest vg/lv names */
 | 
			
		||||
	char display_buffer[NAME_LEN * 10];	/* ring buffer for up to 10 longest vg/lv names */
 | 
			
		||||
	unsigned display_lvname_idx;		/* index to ring buffer */
 | 
			
		||||
	char *linebuffer;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2558,3 +2558,18 @@ uint64_t get_default_allocation_cache_pool_max_chunks_CFG(struct cmd_context *cm
 | 
			
		||||
 | 
			
		||||
	return max_chunks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_default_allocation_vdo_use_metadata_hints_CFG(struct cmd_context *cmd, struct profile *profile)
 | 
			
		||||
{
 | 
			
		||||
	unsigned maj, min;
 | 
			
		||||
 | 
			
		||||
	if ((sscanf(cmd->kernel_vsn, "%u.%u", &maj, &min) == 2) &&
 | 
			
		||||
	    ((maj > 6) || ((maj == 6) && (min > 8)))) {
 | 
			
		||||
		/* With kernels > 6.8 this feature is considered deprecated.
 | 
			
		||||
		 * Return false as default setting. */
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* With older kernels use the configured default setting. */
 | 
			
		||||
	return DEFAULT_VDO_USE_METADATA_HINTS;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -312,6 +312,8 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
 | 
			
		||||
const char *get_default_allocation_cache_policy_CFG(struct cmd_context *cmd, struct profile *profile);
 | 
			
		||||
#define get_default_unconfigured_allocation_cache_policy_CFG NULL
 | 
			
		||||
uint64_t get_default_allocation_cache_pool_max_chunks_CFG(struct cmd_context *cmd, struct profile *profile);
 | 
			
		||||
int get_default_allocation_vdo_use_metadata_hints_CFG(struct cmd_context *cmd, struct profile *profile);
 | 
			
		||||
#define get_default_unconfigured_allocation_vdo_use_metadata_hints_CFG NULL
 | 
			
		||||
int get_default_metadata_pvmetadatasize_CFG(struct cmd_context *cmd, struct profile *profile);
 | 
			
		||||
#define get_default_unconfigured_metadata_pvmetadatasize_CFG NULL
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -728,8 +728,8 @@ cfg(allocation_vdo_use_deduplication_CFG, "vdo_use_deduplication", allocation_CF
 | 
			
		||||
	"Deduplication may be disabled in instances where data is not expected\n"
 | 
			
		||||
	"to have good deduplication rates but compression is still desired.\n")
 | 
			
		||||
 | 
			
		||||
cfg(allocation_vdo_use_metadata_hints_CFG, "vdo_use_metadata_hints", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_USE_METADATA_HINTS, VDO_1ST_VSN, NULL, 0, NULL,
 | 
			
		||||
	"Enables or disables whether VDO volume should tag its latency-critical\n"
 | 
			
		||||
cfg_runtime(allocation_vdo_use_metadata_hints_CFG, "vdo_use_metadata_hints", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, VDO_1ST_VSN, vsn(2, 3, 27), NULL,
 | 
			
		||||
	"Deprecated enablement whether VDO volume should tag its latency-critical\n"
 | 
			
		||||
	"writes with the REQ_SYNC flag. Some device mapper targets such as dm-raid5\n"
 | 
			
		||||
	"process writes with this flag at a higher priority.\n")
 | 
			
		||||
 | 
			
		||||
@@ -821,8 +821,8 @@ cfg(allocation_vdo_physical_threads_CFG, "vdo_physical_threads", allocation_CFG_
 | 
			
		||||
	"vdo_hash_zone_threads, vdo_logical_threads and vdo_physical_threads must be\n"
 | 
			
		||||
	"either all zero or all non-zero.\n")
 | 
			
		||||
 | 
			
		||||
cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_WRITE_POLICY, VDO_1ST_VSN, NULL, 0, NULL,
 | 
			
		||||
	"Specifies the write policy:\n"
 | 
			
		||||
cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_WRITE_POLICY, VDO_1ST_VSN, NULL, vsn(2, 3, 27), NULL,
 | 
			
		||||
	"Deprecated option to specify the write policy with these accepted values:\n"
 | 
			
		||||
	"auto  - VDO will check the storage device and determine whether it supports flushes.\n"
 | 
			
		||||
	"        If it does, VDO will run in async mode, otherwise it will run in sync mode.\n"
 | 
			
		||||
	"sync  - Writes are acknowledged only after data is stably written.\n"
 | 
			
		||||
@@ -1189,6 +1189,14 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
 | 
			
		||||
	"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
 | 
			
		||||
	"with lockd support\n")
 | 
			
		||||
 | 
			
		||||
cfg(global_sanlock_align_size_CFG, "sanlock_align_size", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SANLOCK_ALIGN_SIZE, vsn(2, 3, 27), NULL, 0, NULL,
 | 
			
		||||
	"The sanlock lease size in MiB to use on disks with a 4K sector size.\n"
 | 
			
		||||
	"Possible values are 1,2,4,8.  The default is 8, which supports up to\n"
 | 
			
		||||
	"2000 hosts (and max host_id 2000.)  Smaller values support smaller\n"
 | 
			
		||||
	"numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for\n"
 | 
			
		||||
	"lease sizes 1,2,4,8.  Disks with 512 byte sectors always use 1MiB\n"
 | 
			
		||||
	"leases and support 2000 hosts, and are not affected by this setting.\n")
 | 
			
		||||
 | 
			
		||||
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
 | 
			
		||||
	"The command that lvmlockctl --kill should use to force LVs offline.\n"
 | 
			
		||||
	"The lvmlockctl --kill command is run when a shared VG has lost\n"
 | 
			
		||||
@@ -1424,11 +1432,14 @@ cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTIO
 | 
			
		||||
 | 
			
		||||
cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL,
 | 
			
		||||
	"Stack size in KiB to reserve for use while devices are suspended.\n"
 | 
			
		||||
	"Insufficient reserve risks I/O deadlock during device suspension.\n")
 | 
			
		||||
	"Insufficient reserve risks I/O deadlock during device suspension.\n"
 | 
			
		||||
	"Value 0 disables memory locking.\n")
 | 
			
		||||
 | 
			
		||||
cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL,
 | 
			
		||||
	"Memory size in KiB to reserve for use while devices are suspended.\n"
 | 
			
		||||
	"Insufficient reserve risks I/O deadlock during device suspension.\n")
 | 
			
		||||
	"Insufficient reserve risks I/O deadlock during device suspension.\n"
 | 
			
		||||
	"Value 0 disables memory locking.\n")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL,
 | 
			
		||||
	"Nice value used while devices are suspended.\n"
 | 
			
		||||
@@ -2264,8 +2275,9 @@ cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG
 | 
			
		||||
	"correct usage and possible dangers.\n")
 | 
			
		||||
 | 
			
		||||
cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 124), NULL, 0, NULL,
 | 
			
		||||
	"The lvmlockd sanlock host_id.\n"
 | 
			
		||||
	"This must be unique among all hosts, and must be between 1 and 2000.\n"
 | 
			
		||||
	"Applicable only if LVM is compiled with lockd support\n")
 | 
			
		||||
	"The sanlock host_id used by lvmlockd. This must be unique among all the hosts\n"
 | 
			
		||||
	"using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size\n"
 | 
			
		||||
	"is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.\n"
 | 
			
		||||
	"Applicable only if LVM is compiled with support for lvmlockd+sanlock.\n")
 | 
			
		||||
 | 
			
		||||
cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,7 @@
 | 
			
		||||
#define DEFAULT_USE_AIO 1
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_SANLOCK_LV_EXTEND_MB 256
 | 
			
		||||
#define DEFAULT_SANLOCK_ALIGN_SIZE 8 /* in MiB, applies to 4K disks only */
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_MIRRORLOG MIRROR_LOG_DISK
 | 
			
		||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
 | 
			
		||||
 
 | 
			
		||||
@@ -502,9 +502,14 @@ int dev_get_partition_number(struct device *dev, int *num)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* See linux/genhd.h and fs/partitions/msdos */
 | 
			
		||||
#define PART_MAGIC 0xAA55
 | 
			
		||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
 | 
			
		||||
#define PART_OFFSET UINT64_C(0x1BE)
 | 
			
		||||
#define PART_MSDOS_MAGIC 0xAA55
 | 
			
		||||
#define PART_MSDOS_MAGIC_OFFSET UINT64_C(0x1FE)
 | 
			
		||||
#define PART_MSDOS_OFFSET UINT64_C(0x1BE)
 | 
			
		||||
#define PART_MSDOS_TYPE_GPT_PMBR UINT8_C(0xEE)
 | 
			
		||||
 | 
			
		||||
#define PART_GPT_HEADER_OFFSET_LBA 0x01
 | 
			
		||||
#define PART_GPT_MAGIC 0x5452415020494645UL /* "EFI PART" string */
 | 
			
		||||
#define PART_GPT_ENTRIES_FIELDS_OFFSET UINT64_C(0x48)
 | 
			
		||||
 | 
			
		||||
struct partition {
 | 
			
		||||
	uint8_t boot_ind;
 | 
			
		||||
@@ -570,12 +575,71 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _has_gpt_partition_table(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int pbs, lbs;
 | 
			
		||||
	uint64_t entries_start;
 | 
			
		||||
	uint32_t nr_entries, sz_entry, i;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		uint64_t magic;
 | 
			
		||||
		/* skip fields we're not interested in */
 | 
			
		||||
		uint8_t skip[PART_GPT_ENTRIES_FIELDS_OFFSET - sizeof(uint64_t)];
 | 
			
		||||
		uint64_t part_entries_lba;
 | 
			
		||||
		uint32_t nr_part_entries;
 | 
			
		||||
		uint32_t sz_part_entry;
 | 
			
		||||
	} __attribute__((packed)) gpt_header;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		uint64_t part_type_guid;
 | 
			
		||||
		/* not interested in any other fields */
 | 
			
		||||
	} __attribute__((packed)) gpt_part_entry;
 | 
			
		||||
 | 
			
		||||
	if (!dev_get_direct_block_sizes(dev, &pbs, &lbs))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (!dev_read_bytes(dev, PART_GPT_HEADER_OFFSET_LBA * lbs, sizeof(gpt_header), &gpt_header))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/* the gpt table is always written using LE on disk */
 | 
			
		||||
 | 
			
		||||
	if (le64_to_cpu(gpt_header.magic) != PART_GPT_MAGIC)
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	entries_start = le64_to_cpu(gpt_header.part_entries_lba) * lbs;
 | 
			
		||||
	nr_entries = le32_to_cpu(gpt_header.nr_part_entries);
 | 
			
		||||
	sz_entry = le32_to_cpu(gpt_header.sz_part_entry);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < nr_entries; i++) {
 | 
			
		||||
		if (!dev_read_bytes(dev, entries_start + i * sz_entry,
 | 
			
		||||
				    sizeof(gpt_part_entry), &gpt_part_entry))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
		/* just check if the guid is nonzero, no need to call le64_to_cpu here */
 | 
			
		||||
		if (gpt_part_entry.part_type_guid)
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Check if there's a partition table present on the device dev, either msdos or gpt.
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *
 | 
			
		||||
 *   1 - if it has a partition table with at least one real partition defined
 | 
			
		||||
 *       (note: the gpt's PMBR partition alone does not count as a real partition)
 | 
			
		||||
 *
 | 
			
		||||
 *   0 - if it has no partition table,
 | 
			
		||||
 *     - or if it does have a partition table, but without any partition defined,
 | 
			
		||||
 *     - or on error
 | 
			
		||||
 */
 | 
			
		||||
static int _has_partition_table(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	unsigned p;
 | 
			
		||||
	struct {
 | 
			
		||||
		uint8_t skip[PART_OFFSET];
 | 
			
		||||
		uint8_t skip[PART_MSDOS_OFFSET];
 | 
			
		||||
		struct partition part[4];
 | 
			
		||||
		uint16_t magic;
 | 
			
		||||
	} __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
 | 
			
		||||
@@ -586,7 +650,7 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
	/* FIXME Check for other types of partition table too */
 | 
			
		||||
 | 
			
		||||
	/* Check for msdos partition table */
 | 
			
		||||
	if (buf.magic == xlate16(PART_MAGIC)) {
 | 
			
		||||
	if (buf.magic == xlate16(PART_MSDOS_MAGIC)) {
 | 
			
		||||
		for (p = 0; p < 4; ++p) {
 | 
			
		||||
			/* Table is invalid if boot indicator not 0 or 0x80 */
 | 
			
		||||
			if (buf.part[p].boot_ind & 0x7f) {
 | 
			
		||||
@@ -594,10 +658,20 @@ static int _has_partition_table(struct device *dev)
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			/* Must have at least one non-empty partition */
 | 
			
		||||
			if (buf.part[p].nr_sects)
 | 
			
		||||
				ret = 1;
 | 
			
		||||
			if (buf.part[p].nr_sects) {
 | 
			
		||||
				/*
 | 
			
		||||
				 * If this is GPT's PMBR, then also
 | 
			
		||||
				 * check for gpt partition table.
 | 
			
		||||
				 */
 | 
			
		||||
				if (buf.part[p].sys_ind == PART_MSDOS_TYPE_GPT_PMBR)
 | 
			
		||||
					ret = _has_gpt_partition_table(dev);
 | 
			
		||||
				else
 | 
			
		||||
					ret = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	} else
 | 
			
		||||
		/* Check for gpt partition table. */
 | 
			
		||||
		ret = _has_gpt_partition_table(dev);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
@@ -869,6 +943,7 @@ int fs_get_blkid(const char *pathname, struct fs_info *fsi)
 | 
			
		||||
	const char *str = "";
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	uint64_t fslastblock = 0;
 | 
			
		||||
	uint64_t fssize = 0;
 | 
			
		||||
	unsigned int fsblocksize = 0;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
@@ -919,10 +994,25 @@ int fs_get_blkid(const char *pathname, struct fs_info *fsi)
 | 
			
		||||
	if (!blkid_probe_lookup_value(probe, "FSBLOCKSIZE", &str, &len) && len)
 | 
			
		||||
		fsblocksize = (unsigned int)atoi(str);
 | 
			
		||||
 | 
			
		||||
	if (!blkid_probe_lookup_value(probe, "FSSIZE", &str, &len) && len)
 | 
			
		||||
		fssize = strtoull(str, NULL, 0);
 | 
			
		||||
 | 
			
		||||
	blkid_free_probe(probe);
 | 
			
		||||
 | 
			
		||||
	if (fslastblock && fsblocksize)
 | 
			
		||||
		fsi->fs_last_byte = fslastblock * fsblocksize;
 | 
			
		||||
	else if (fssize) {
 | 
			
		||||
		fsi->fs_last_byte = fssize;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * For swap, there's no FSLASTBLOCK reported by blkid. We do have FSSIZE reported though.
 | 
			
		||||
		 * The last block is then calculated as:
 | 
			
		||||
		 *    FSSIZE (== size of the usable swap area) + FSBLOCKSIZE (== size of the swap header)
 | 
			
		||||
		 */
 | 
			
		||||
		if (!strcmp(fsi->fstype, "swap"))
 | 
			
		||||
			fsi->fs_last_byte += fsblocksize;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("libblkid TYPE %s BLOCK_SIZE %d FSLASTBLOCK %llu FSBLOCKSIZE %u fs_last_byte %llu",
 | 
			
		||||
		  fsi->fstype, fsi->fs_block_size_bytes, (unsigned long long)fslastblock, fsblocksize,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#define DEV_REGULAR		0x00000002	/* Regular file? */
 | 
			
		||||
#define DEV_ALLOCED		0x00000004	/* malloc used */
 | 
			
		||||
#define DEV_ALLOCATED		0x00000004	/* malloc used */
 | 
			
		||||
#define DEV_OPENED_RW		0x00000008	/* Opened RW */
 | 
			
		||||
#define DEV_OPENED_EXCL		0x00000010	/* Opened EXCL */
 | 
			
		||||
#define DEV_O_DIRECT		0x00000020	/* Use O_DIRECT */
 | 
			
		||||
 
 | 
			
		||||
@@ -201,6 +201,13 @@ int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	if (!include_mount)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Note: used swap devices are not considered as mount points,
 | 
			
		||||
	 * hence they're not listed in /etc/mtab, we'd need to read the
 | 
			
		||||
	 * /proc/swaps instead. We don't need it at this moment though,
 | 
			
		||||
	 * but if we do once, read the /proc/swaps here if fsi->fstype == "swap".
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (!(fme = setmntent("/etc/mtab", "r")))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -376,7 +376,8 @@ static int _read_segment(struct cmd_context *cmd,
 | 
			
		||||
			 struct format_instance *fid,
 | 
			
		||||
			 struct dm_pool *mem,
 | 
			
		||||
			 struct logical_volume *lv, const struct dm_config_node *sn,
 | 
			
		||||
			 struct dm_hash_table *pv_hash)
 | 
			
		||||
			 struct dm_hash_table *pv_hash,
 | 
			
		||||
			 struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t area_count = 0u;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
@@ -449,7 +450,7 @@ static int _read_segment(struct cmd_context *cmd,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (seg->segtype->ops->text_import &&
 | 
			
		||||
	    !seg->segtype->ops->text_import(seg, sn_child, pv_hash))
 | 
			
		||||
	    !seg->segtype->ops->text_import(seg, sn_child, pv_hash, lv_hash))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	/* Optional tags */
 | 
			
		||||
@@ -551,7 +552,8 @@ static int _read_segments(struct cmd_context *cmd,
 | 
			
		||||
			  struct format_instance *fid,
 | 
			
		||||
			  struct dm_pool *mem,
 | 
			
		||||
			  struct logical_volume *lv, const struct dm_config_node *lvn,
 | 
			
		||||
			  struct dm_hash_table *pv_hash)
 | 
			
		||||
			  struct dm_hash_table *pv_hash,
 | 
			
		||||
			  struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const struct dm_config_node *sn;
 | 
			
		||||
	int count = 0, seg_count;
 | 
			
		||||
@@ -562,7 +564,7 @@ static int _read_segments(struct cmd_context *cmd,
 | 
			
		||||
		 * All sub-sections are assumed to be segments.
 | 
			
		||||
		 */
 | 
			
		||||
		if (!sn->v) {
 | 
			
		||||
			if (!_read_segment(cmd, fmt, fid, mem, lv, sn, pv_hash))
 | 
			
		||||
			if (!_read_segment(cmd, fmt, fid, mem, lv, sn, pv_hash, lv_hash))
 | 
			
		||||
				return_0;
 | 
			
		||||
 | 
			
		||||
			count++;
 | 
			
		||||
@@ -979,7 +981,7 @@ static int _read_lvsegs(struct cmd_context *cmd,
 | 
			
		||||
 | 
			
		||||
	memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
 | 
			
		||||
 | 
			
		||||
	if (!_read_segments(cmd, fmt, fid, mem, lv, lvn, pv_hash))
 | 
			
		||||
	if (!_read_segments(cmd, fmt, fid, mem, lv, lvn, pv_hash, lv_hash))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,8 @@ static void _integrity_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
static int _integrity_text_import(struct lv_segment *seg,
 | 
			
		||||
				   const struct dm_config_node *sn,
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
				   struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct integrity_settings *set;
 | 
			
		||||
	struct logical_volume *origin_lv = NULL;
 | 
			
		||||
@@ -58,7 +59,7 @@ static int _integrity_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_get_str(sn, "origin", &origin_name))
 | 
			
		||||
		return SEG_LOG_ERROR("origin must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(origin_lv = find_lv(seg->lv->vg, origin_name)))
 | 
			
		||||
	if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown LV specified for integrity origin %s in", origin_name);
 | 
			
		||||
 | 
			
		||||
	if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
 | 
			
		||||
@@ -103,7 +104,7 @@ static int _integrity_text_import(struct lv_segment *seg,
 | 
			
		||||
		if (!dm_config_get_str(sn, "meta_dev", &meta_dev))
 | 
			
		||||
			return SEG_LOG_ERROR("meta_dev must be a string in");
 | 
			
		||||
 | 
			
		||||
		if (!(meta_lv = find_lv(seg->lv->vg, meta_dev)))
 | 
			
		||||
		if (!(meta_lv = dm_hash_lookup(lv_hash, meta_dev)))
 | 
			
		||||
			return SEG_LOG_ERROR("Unknown logical volume %s specified for integrity in", meta_dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
#include "daemons/lvmlockd/lvmlockd-client.h"
 | 
			
		||||
 | 
			
		||||
#include <mntent.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
 | 
			
		||||
static daemon_handle _lvmlockd;
 | 
			
		||||
static const char *_lvmlockd_socket = NULL;
 | 
			
		||||
@@ -493,7 +494,7 @@ static int _lockd_request(struct cmd_context *cmd,
 | 
			
		||||
static int _create_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
			      const char *lock_lv_name, int num_mb)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t lv_size_bytes;
 | 
			
		||||
	uint64_t lv_size_bytes;
 | 
			
		||||
	uint32_t extent_bytes;
 | 
			
		||||
	uint32_t total_extents;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
@@ -511,14 +512,24 @@ static int _create_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
		.zero = 1,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	lv_size_bytes = num_mb * ONE_MB_IN_BYTES;  /* size of sanlock LV in bytes */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Make the lvmlock lv a multiple of 8 MB, i.e. a multiple of any
 | 
			
		||||
	 * sanlock align_size, to avoid having unused space at the end of the
 | 
			
		||||
	 * lvmlock LV.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (num_mb % 8)
 | 
			
		||||
		num_mb += (8 - (num_mb % 8));
 | 
			
		||||
 | 
			
		||||
	lv_size_bytes = (uint64_t)num_mb * ONE_MB_IN_BYTES;  /* size of sanlock LV in bytes */
 | 
			
		||||
	extent_bytes = vg->extent_size * SECTOR_SIZE; /* size of one extent in bytes */
 | 
			
		||||
	total_extents = dm_div_up(lv_size_bytes, extent_bytes); /* number of extents in sanlock LV */
 | 
			
		||||
	lp.extents = total_extents;
 | 
			
		||||
 | 
			
		||||
	lv_size_bytes = total_extents * extent_bytes;
 | 
			
		||||
	lv_size_bytes = (uint64_t)total_extents * extent_bytes;
 | 
			
		||||
	num_mb = lv_size_bytes / ONE_MB_IN_BYTES;
 | 
			
		||||
	log_debug("Creating lvmlock LV for sanlock with size %um %ub %u extents", num_mb, lv_size_bytes, lp.extents);
 | 
			
		||||
	log_debug("Creating lvmlock LV for sanlock with size %um %llub %u extents",
 | 
			
		||||
		  num_mb, (unsigned long long)lv_size_bytes, lp.extents);
 | 
			
		||||
 | 
			
		||||
	dm_list_init(&lp.tags);
 | 
			
		||||
 | 
			
		||||
@@ -547,11 +558,9 @@ static int _remove_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg, unsigned extend_mb)
 | 
			
		||||
static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg, unsigned extend_mb, char *lvmlock_path)
 | 
			
		||||
{
 | 
			
		||||
	struct device *dev;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	char *name;
 | 
			
		||||
	uint64_t old_size_bytes;
 | 
			
		||||
	uint64_t new_size_bytes;
 | 
			
		||||
	uint32_t extend_bytes;
 | 
			
		||||
@@ -594,23 +603,14 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
 | 
			
		||||
	new_size_bytes = lv->size * SECTOR_SIZE;
 | 
			
		||||
 | 
			
		||||
	if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (dm_snprintf(path, sizeof(path), "%s/%s", dm_dir(), name) < 0) {
 | 
			
		||||
		log_error("Extend sanlock LV %s name too long - extended size not zeroed.",
 | 
			
		||||
			  display_lvname(lv));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("Extend sanlock LV zeroing %u bytes from offset %llu to %llu",
 | 
			
		||||
		  (uint32_t)(new_size_bytes - old_size_bytes),
 | 
			
		||||
		  (unsigned long long)old_size_bytes,
 | 
			
		||||
		  (unsigned long long)new_size_bytes);
 | 
			
		||||
 | 
			
		||||
	log_print_unless_silent("Zeroing %u MiB on extended internal lvmlock LV...", extend_mb);
 | 
			
		||||
	log_debug("Zeroing %u MiB on extended internal lvmlock LV...", extend_mb);
 | 
			
		||||
 | 
			
		||||
	if (!(dev = dev_cache_get(cmd, path, NULL))) {
 | 
			
		||||
	if (!(dev = dev_cache_get(cmd, lvmlock_path, NULL))) {
 | 
			
		||||
		log_error("Extend sanlock LV %s cannot find device.", display_lvname(lv));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -653,16 +653,27 @@ static int _refresh_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
int handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *lv = vg->sanlock_lv;
 | 
			
		||||
	daemon_reply reply;
 | 
			
		||||
	char *lvmlock_name;
 | 
			
		||||
	char lvmlock_path[PATH_MAX];
 | 
			
		||||
	unsigned extend_mb;
 | 
			
		||||
	uint64_t lv_size_bytes;
 | 
			
		||||
	uint64_t dm_size_bytes;
 | 
			
		||||
	int result;
 | 
			
		||||
	int ret;
 | 
			
		||||
	int fd;
 | 
			
		||||
 | 
			
		||||
	if (!_use_lvmlockd)
 | 
			
		||||
		return 1;
 | 
			
		||||
	if (!_lvmlockd_connected)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!lv) {
 | 
			
		||||
		log_error("No internal lvmlock LV found.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	extend_mb = (unsigned) find_config_tree_int(cmd, global_sanlock_lv_extend_CFG, NULL);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -672,13 +683,46 @@ int handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
	if (!extend_mb)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Another host may have extended the lvmlock LV already.
 | 
			
		||||
	 * Refresh so that we'll find the new space they added
 | 
			
		||||
	 * when we search for new space.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!_refresh_sanlock_lv(cmd, vg))
 | 
			
		||||
	lv_size_bytes = lv->size * SECTOR_SIZE;
 | 
			
		||||
 | 
			
		||||
	if (!(lvmlock_name = dm_build_dm_name(cmd->mem, vg->name, lv->name, NULL)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	if (dm_snprintf(lvmlock_path, sizeof(lvmlock_path), "%s/%s", dm_dir(), lvmlock_name) < 0) {
 | 
			
		||||
		log_error("Handle sanlock LV %s path too long.", lvmlock_name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd = open(lvmlock_path, O_RDONLY);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		log_error("Cannot open sanlock LV %s.", lvmlock_path);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ioctl(fd, BLKGETSIZE64, &dm_size_bytes) < 0) {
 | 
			
		||||
		log_error("Cannot get size of sanlock LV %s.", lvmlock_path);
 | 
			
		||||
		if (close(fd))
 | 
			
		||||
			stack;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (close(fd))
 | 
			
		||||
		stack;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Another host may have extended the lvmlock LV.
 | 
			
		||||
	 * If so the lvmlock LV size in metadata will be
 | 
			
		||||
	 * larger than our active lvmlock LV, and we need
 | 
			
		||||
	 * to refresh our lvmlock LV to use the new space.
 | 
			
		||||
	 */
 | 
			
		||||
	if (lv_size_bytes > dm_size_bytes) {
 | 
			
		||||
		log_debug("Refresh sanlock lv %llu dm %llu",
 | 
			
		||||
			  (unsigned long long)lv_size_bytes,
 | 
			
		||||
			  (unsigned long long)dm_size_bytes);
 | 
			
		||||
 | 
			
		||||
		if (!_refresh_sanlock_lv(cmd, vg))
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Ask lvmlockd/sanlock to look for an unused lock.
 | 
			
		||||
@@ -686,6 +730,7 @@ int handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
	reply = _lockd_send("find_free_lock",
 | 
			
		||||
			"pid = " FMTd64, (int64_t) getpid(),
 | 
			
		||||
			"vg_name = %s", vg->name,
 | 
			
		||||
			"lv_size_bytes = " FMTd64, (int64_t) lv_size_bytes,
 | 
			
		||||
			NULL);
 | 
			
		||||
 | 
			
		||||
	if (!_lockd_result(reply, &result, NULL)) {
 | 
			
		||||
@@ -696,7 +741,7 @@ int handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	/* No space on the lvmlock lv for a new lease. */
 | 
			
		||||
	if (result == -EMSGSIZE)
 | 
			
		||||
		ret = _extend_sanlock_lv(cmd, vg, extend_mb);
 | 
			
		||||
		ret = _extend_sanlock_lv(cmd, vg, extend_mb, lvmlock_path);
 | 
			
		||||
 | 
			
		||||
	daemon_reply_destroy(reply);
 | 
			
		||||
 | 
			
		||||
@@ -822,7 +867,9 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
 | 
			
		||||
	const char *opts = NULL;
 | 
			
		||||
	struct pv_list *pvl;
 | 
			
		||||
	uint32_t sector_size = 0;
 | 
			
		||||
	uint32_t align_size = 0;
 | 
			
		||||
	unsigned int physical_block_size, logical_block_size;
 | 
			
		||||
	int host_id;
 | 
			
		||||
	int num_mb = 0;
 | 
			
		||||
	int result;
 | 
			
		||||
	int ret;
 | 
			
		||||
@@ -849,11 +896,54 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
 | 
			
		||||
 | 
			
		||||
	log_debug("Using sector size %u for sanlock LV", sector_size);
 | 
			
		||||
 | 
			
		||||
	/* Base starting size of sanlock LV is 256MB/1GB for 512/4K sectors */
 | 
			
		||||
	switch (sector_size) {
 | 
			
		||||
	case 512: num_mb = 256; break;
 | 
			
		||||
	case 4096: num_mb = 1024; break;
 | 
			
		||||
	default: log_error("Unknown sector size %u.", sector_size); return 0;
 | 
			
		||||
	host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Starting size of lvmlock LV is 256MB/512MB/1GB depending
 | 
			
		||||
	 * on sector_size/align_size, and max valid host_id depends
 | 
			
		||||
	 * on sector_size/align_size.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if (sector_size == 4096) {
 | 
			
		||||
		align_size = find_config_tree_int(cmd, global_sanlock_align_size_CFG, NULL);
 | 
			
		||||
 | 
			
		||||
		if (align_size == 1) {
 | 
			
		||||
			num_mb = 256;
 | 
			
		||||
			if (host_id < 1 || host_id > 250) {
 | 
			
		||||
				log_error("Invalid host_id %d, use 1-250 (sanlock_align_size is 1MiB).", host_id);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (align_size == 2) {
 | 
			
		||||
			num_mb = 512;
 | 
			
		||||
			if (host_id < 1 || host_id > 500) {
 | 
			
		||||
				log_error("Invalid host_id %d, use 1-500 (sanlock_align_size is 2MiB).", host_id);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (align_size == 4) {
 | 
			
		||||
			num_mb = 1024;
 | 
			
		||||
			if (host_id < 1 || host_id > 1000) {
 | 
			
		||||
				log_error("Invalid host_id %d, use 1-1000 (sanlock_align_size is 4MiB).", host_id);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (align_size == 8) {
 | 
			
		||||
			num_mb = 1024;
 | 
			
		||||
			if (host_id < 1 || host_id > 2000) {
 | 
			
		||||
				log_error("Invalid host_id %d, use 1-2000 (sanlock_align_size is 8MiB).", host_id);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			log_error("Invalid sanlock_align_size %u, use 1,2,4,8.", align_size);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (sector_size == 512) {
 | 
			
		||||
		num_mb = 256;
 | 
			
		||||
		if (host_id < 1 || host_id > 2000) {
 | 
			
		||||
			log_error("Invalid host_id %d, use 1-2000.", host_id);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log_error("Unsupported sector size %u.", sector_size);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -891,6 +981,7 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
 | 
			
		||||
				"vg_name = %s", vg->name,
 | 
			
		||||
				"vg_lock_type = %s", "sanlock",
 | 
			
		||||
				"vg_lock_args = %s", vg->sanlock_lv->name,
 | 
			
		||||
				"align_mb = " FMTd64, (int64_t) align_size,
 | 
			
		||||
				"opts = %s", opts ?: "none",
 | 
			
		||||
				NULL);
 | 
			
		||||
 | 
			
		||||
@@ -2575,7 +2666,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 retry:
 | 
			
		||||
	log_debug("lockd LV %s/%s mode %s uuid %s", vg->name, lv_name, mode, lv_uuid);
 | 
			
		||||
	log_debug("lockd LV %s/%s mode %s uuid %s %s", vg->name, lv_name, mode, lv_uuid, opts ?: "");
 | 
			
		||||
 | 
			
		||||
	/* Pass PV list for IDM lock type */
 | 
			
		||||
	if (!strcmp(vg->lock_type, "idm")) {
 | 
			
		||||
@@ -3178,7 +3269,7 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
 | 
			
		||||
 | 
			
		||||
	} else if (seg_is_thin(lp)) {
 | 
			
		||||
		if ((seg_is_thin_volume(lp) && !lp->create_pool) ||
 | 
			
		||||
		    (!seg_is_thin_volume(lp) && lp->snapshot)) {
 | 
			
		||||
		    (!seg_is_thin_volume(lp) && lp->origin_name)) {
 | 
			
		||||
			struct lv_list *lvl;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
@@ -3186,12 +3277,13 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
 | 
			
		||||
			 * their own lock but use the pool lock.  If an lv does not
 | 
			
		||||
			 * use its own lock, its lock_args is set to NULL.
 | 
			
		||||
			 */
 | 
			
		||||
			log_debug("lockd_init_lv thin %s locking thin pool", display_lvname(lv));
 | 
			
		||||
 | 
			
		||||
			if (!(lvl = find_lv_in_vg(vg, lp->pool_name))) {
 | 
			
		||||
				log_error("Failed to find thin pool %s/%s", vg->name, lp->pool_name);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			if (!lockd_lv(cmd, lvl->lv, "ex", LDLV_PERSISTENT)) {
 | 
			
		||||
			if (!lockd_lv(cmd, lvl->lv, "ex", 0)) {
 | 
			
		||||
				log_error("Failed to lock thin pool %s/%s", vg->name, lp->pool_name);
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -258,7 +258,7 @@ static int _get_pid_starttime(int *pid, unsigned long long *starttime)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Support envvar LVM_LOG_FILE_EPOCH and allow to attach
 | 
			
		||||
 * extra keyword (consist of upto 32 alpha chars) to
 | 
			
		||||
 * extra keyword (consist of up to 32 alpha chars) to
 | 
			
		||||
 * opened log file. After this 'epoch' word pid and starttime
 | 
			
		||||
 * (in kernel units, read from /proc/self/stat)
 | 
			
		||||
 * is automatically attached.
 | 
			
		||||
@@ -591,6 +591,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
 | 
			
		||||
	    (_log_report.report && !log_bypass_report && (use_stderr || (level <=_LOG_WARN))) ||
 | 
			
		||||
	    log_once) {
 | 
			
		||||
		va_copy(ap, orig_ap);
 | 
			
		||||
		/* coverity[format_string_injection] our code expectes this behavior. */
 | 
			
		||||
		n = vsnprintf(message, sizeof(message), trformat, ap);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1558,8 +1558,6 @@ bad:
 | 
			
		||||
int lv_set_creation(struct logical_volume *lv,
 | 
			
		||||
		    const char *hostname, uint64_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
	const char *hn;
 | 
			
		||||
 | 
			
		||||
	if (!hostname) {
 | 
			
		||||
		if (!_utsinit) {
 | 
			
		||||
			if (uname(&_utsname)) {
 | 
			
		||||
@@ -1573,17 +1571,7 @@ int lv_set_creation(struct logical_volume *lv,
 | 
			
		||||
		hostname = _utsname.nodename;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(hn = dm_hash_lookup(lv->vg->hostnames, hostname))) {
 | 
			
		||||
		if (!(hn = dm_pool_strdup(lv->vg->vgmem, hostname))) {
 | 
			
		||||
			log_error("Failed to duplicate hostname");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!dm_hash_insert(lv->vg->hostnames, hostname, (void*)hn))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lv->hostname = hn;
 | 
			
		||||
	lv->hostname = dm_pool_strdup(lv->vg->vgmem, hostname);
 | 
			
		||||
	lv->timestamp = timestamp ? : (uint64_t) time(NULL);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -49,10 +49,10 @@ typedef enum {
 | 
			
		||||
#define RAID_METADATA_AREA_LEN 1
 | 
			
		||||
 | 
			
		||||
/* FIXME These ended up getting used differently from first intended.  Refactor. */
 | 
			
		||||
/* Only one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG, A_CLING_TO_ALLOCED may be set */
 | 
			
		||||
/* Only one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG, A_CLING_TO_ALLOCATED may be set */
 | 
			
		||||
#define A_CONTIGUOUS_TO_LVSEG	0x01	/* Must be contiguous to an existing segment */
 | 
			
		||||
#define A_CLING_TO_LVSEG	0x02	/* Must use same disks as existing LV segment */
 | 
			
		||||
#define A_CLING_TO_ALLOCED	0x04	/* Must use same disks as already-allocated segment */
 | 
			
		||||
#define A_CLING_TO_ALLOCATED	0x04	/* Must use same disks as already-allocated segment */
 | 
			
		||||
 | 
			
		||||
#define A_CLING_BY_TAGS		0x08	/* Must match tags against existing segment */
 | 
			
		||||
#define A_CAN_SPLIT		0x10
 | 
			
		||||
@@ -1044,7 +1044,7 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
 | 
			
		||||
 | 
			
		||||
	if (segtype_is_raid_with_meta(segtype) &&
 | 
			
		||||
	    !(seg->meta_areas = dm_pool_zalloc(mem, areas_sz))) {
 | 
			
		||||
		dm_pool_free(mem, seg); /* frees everything alloced since seg */
 | 
			
		||||
		dm_pool_free(mem, seg); /* frees everything allocated since seg */
 | 
			
		||||
		return_NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1846,7 +1846,7 @@ int lv_remove(struct logical_volume *lv)
 | 
			
		||||
/*
 | 
			
		||||
 * A set of contiguous physical extents allocated
 | 
			
		||||
 */
 | 
			
		||||
struct alloced_area {
 | 
			
		||||
struct allocated_area {
 | 
			
		||||
	struct dm_list list;
 | 
			
		||||
 | 
			
		||||
	struct physical_volume *pv;
 | 
			
		||||
@@ -1897,7 +1897,7 @@ struct alloc_handle {
 | 
			
		||||
	 * Contains area_count lists of areas allocated to data stripes
 | 
			
		||||
	 * followed by log_area_count lists of areas allocated to log stripes.
 | 
			
		||||
	 */
 | 
			
		||||
	struct dm_list alloced_areas[];
 | 
			
		||||
	struct dm_list allocated_areas[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -2001,7 +2001,7 @@ static void _init_alloc_parms(struct alloc_handle *ah,
 | 
			
		||||
		 */
 | 
			
		||||
		if ((alloc_parms->alloc == ALLOC_CLING) ||
 | 
			
		||||
		    (alloc_parms->alloc == ALLOC_CLING_BY_TAGS)) {
 | 
			
		||||
			alloc_parms->flags |= A_CLING_TO_ALLOCED;
 | 
			
		||||
			alloc_parms->flags |= A_CLING_TO_ALLOCATED;
 | 
			
		||||
			alloc_parms->flags |= A_POSITIONAL_FILL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -2021,17 +2021,17 @@ static void _init_alloc_parms(struct alloc_handle *ah,
 | 
			
		||||
	if (ah->maximise_cling &&
 | 
			
		||||
	    (alloc_parms->alloc == ALLOC_NORMAL) &&
 | 
			
		||||
	    (allocated != alloc_parms->extents_still_needed))
 | 
			
		||||
		alloc_parms->flags |= A_CLING_TO_ALLOCED;
 | 
			
		||||
		alloc_parms->flags |= A_CLING_TO_ALLOCATED;
 | 
			
		||||
 | 
			
		||||
	if (can_split)
 | 
			
		||||
		alloc_parms->flags |= A_CAN_SPLIT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
 | 
			
		||||
static int _setup_allocated_segment(struct logical_volume *lv, uint64_t status,
 | 
			
		||||
				  uint32_t area_count,
 | 
			
		||||
				  uint32_t stripe_size,
 | 
			
		||||
				  const struct segment_type *segtype,
 | 
			
		||||
				  struct alloced_area *aa,
 | 
			
		||||
				  struct allocated_area *aa,
 | 
			
		||||
				  uint32_t region_size)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t s, extents, area_multiple;
 | 
			
		||||
@@ -2062,18 +2062,18 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _setup_alloced_segments(struct logical_volume *lv,
 | 
			
		||||
				   struct dm_list *alloced_areas,
 | 
			
		||||
static int _setup_allocated_segments(struct logical_volume *lv,
 | 
			
		||||
				   struct dm_list *allocated_areas,
 | 
			
		||||
				   uint32_t area_count,
 | 
			
		||||
				   uint64_t status,
 | 
			
		||||
				   uint32_t stripe_size,
 | 
			
		||||
				   const struct segment_type *segtype,
 | 
			
		||||
				   uint32_t region_size)
 | 
			
		||||
{
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
 | 
			
		||||
	dm_list_iterate_items(aa, &alloced_areas[0]) {
 | 
			
		||||
		if (!_setup_alloced_segment(lv, status, area_count,
 | 
			
		||||
	dm_list_iterate_items(aa, &allocated_areas[0]) {
 | 
			
		||||
		if (!_setup_allocated_segment(lv, status, area_count,
 | 
			
		||||
					    stripe_size, segtype, aa,
 | 
			
		||||
					    region_size))
 | 
			
		||||
			return_0;
 | 
			
		||||
@@ -2094,7 +2094,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
 | 
			
		||||
	uint32_t s, smeta;
 | 
			
		||||
	uint32_t ix_log_skip = 0; /* How many areas to skip in middle of array to reach log areas */
 | 
			
		||||
	uint32_t total_area_count;
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
	struct pv_area *pva;
 | 
			
		||||
 | 
			
		||||
	total_area_count = ah->area_count + ah->parity_count + alloc_state->log_area_count_still_needed;
 | 
			
		||||
@@ -2113,7 +2113,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
 | 
			
		||||
	len = (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? total_area_count * 2 : total_area_count;
 | 
			
		||||
	len *= sizeof(*aa);
 | 
			
		||||
	if (!(aa = dm_pool_alloc(ah->mem, len))) {
 | 
			
		||||
		log_error("alloced_area allocation failed");
 | 
			
		||||
		log_error("allocated_area allocation failed");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -2156,7 +2156,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
 | 
			
		||||
					aa[smeta].len);
 | 
			
		||||
 | 
			
		||||
			consume_pv_area(pva, aa[smeta].len);
 | 
			
		||||
			dm_list_add(&ah->alloced_areas[smeta], &aa[smeta].list);
 | 
			
		||||
			dm_list_add(&ah->allocated_areas[smeta], &aa[smeta].list);
 | 
			
		||||
		}
 | 
			
		||||
		aa[s].len = (ah->alloc_and_split_meta && !ah->split_metadata_is_allocated) ? len - ah->log_len : len;
 | 
			
		||||
		/* Skip empty allocations */
 | 
			
		||||
@@ -2172,7 +2172,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t max_to_allocat
 | 
			
		||||
 | 
			
		||||
		consume_pv_area(pva, aa[s].len);
 | 
			
		||||
 | 
			
		||||
		dm_list_add(&ah->alloced_areas[s], &aa[s].list);
 | 
			
		||||
		dm_list_add(&ah->allocated_areas[s], &aa[s].list);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only need to alloc metadata from the first batch */
 | 
			
		||||
@@ -2728,11 +2728,11 @@ static int _check_contiguous(struct alloc_handle *ah,
 | 
			
		||||
/*
 | 
			
		||||
 * Is pva on same PV as any areas already used in this allocation attempt?
 | 
			
		||||
 */
 | 
			
		||||
static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_config_node *cling_tag_list_cn,
 | 
			
		||||
static int _check_cling_to_allocated(struct alloc_handle *ah, const struct dm_config_node *cling_tag_list_cn,
 | 
			
		||||
				   struct pv_area *pva, struct alloc_state *alloc_state)
 | 
			
		||||
{
 | 
			
		||||
	unsigned s;
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
	int positional = alloc_state->alloc_parms->flags & A_POSITIONAL_FILL;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -2745,7 +2745,7 @@ static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_conf
 | 
			
		||||
	for (s = 0; s < ah->area_count; s++) {
 | 
			
		||||
		if (positional && alloc_state->areas[s].pva)
 | 
			
		||||
			continue;	/* Area already assigned */
 | 
			
		||||
		dm_list_iterate_items(aa, &ah->alloced_areas[s]) {
 | 
			
		||||
		dm_list_iterate_items(aa, &ah->allocated_areas[s]) {
 | 
			
		||||
			if ((!cling_tag_list_cn && (pva->map->pv == aa[0].pv)) ||
 | 
			
		||||
			    (cling_tag_list_cn && _pvs_have_matching_tag(cling_tag_list_cn, pva->map->pv, aa[0].pv, 0))) {
 | 
			
		||||
				if (positional &&
 | 
			
		||||
@@ -2802,7 +2802,7 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
 | 
			
		||||
				return NEXT_AREA;
 | 
			
		||||
 | 
			
		||||
	/* If maximise_cling is set, perform several checks, otherwise perform exactly one. */
 | 
			
		||||
	if (!iteration_count && !log_iteration_count && alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG | A_CLING_TO_ALLOCED)) {
 | 
			
		||||
	if (!iteration_count && !log_iteration_count && alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG | A_CLING_TO_ALLOCATED)) {
 | 
			
		||||
		/* Contiguous? */
 | 
			
		||||
		if (((alloc_parms->flags & A_CONTIGUOUS_TO_LVSEG) ||
 | 
			
		||||
		     (ah->maximise_cling && (alloc_parms->flags & A_AREA_COUNT_MATCHES))) &&
 | 
			
		||||
@@ -2820,9 +2820,9 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
 | 
			
		||||
			/* If this PV is suitable, use this first area */
 | 
			
		||||
			goto found;
 | 
			
		||||
 | 
			
		||||
		/* Cling_to_alloced? */
 | 
			
		||||
		if ((alloc_parms->flags & A_CLING_TO_ALLOCED) &&
 | 
			
		||||
		    _check_cling_to_alloced(ah, NULL, pva, alloc_state))
 | 
			
		||||
		/* Cling_to_allocated? */
 | 
			
		||||
		if ((alloc_parms->flags & A_CLING_TO_ALLOCATED) &&
 | 
			
		||||
		    _check_cling_to_allocated(ah, NULL, pva, alloc_state))
 | 
			
		||||
			goto found;
 | 
			
		||||
 | 
			
		||||
		/* Cling_by_tags? */
 | 
			
		||||
@@ -2832,7 +2832,7 @@ static area_use_t _check_pva(struct alloc_handle *ah, struct pv_area *pva, uint3
 | 
			
		||||
		if ((alloc_parms->flags & A_AREA_COUNT_MATCHES)) {
 | 
			
		||||
			if (_check_cling(ah, ah->cling_tag_list_cn, alloc_parms->prev_lvseg, pva, alloc_state))
 | 
			
		||||
				goto found;
 | 
			
		||||
		} else if (_check_cling_to_alloced(ah, ah->cling_tag_list_cn, pva, alloc_state))
 | 
			
		||||
		} else if (_check_cling_to_allocated(ah, ah->cling_tag_list_cn, pva, alloc_state))
 | 
			
		||||
			goto found;
 | 
			
		||||
 | 
			
		||||
		/* All areas on this PV give same result so pointless checking more */
 | 
			
		||||
@@ -2993,9 +2993,9 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 | 
			
		||||
	unsigned already_found_one;
 | 
			
		||||
	unsigned ix_log_offset; /* Offset to start of areas to use for log */
 | 
			
		||||
	unsigned too_small_for_log_count; /* How many too small for log? */
 | 
			
		||||
	unsigned iteration_count = 0; /* cling_to_alloced may need 2 iterations */
 | 
			
		||||
	unsigned iteration_count = 0; /* cling_to_allocated may need 2 iterations */
 | 
			
		||||
	unsigned log_iteration_count = 0; /* extra iteration for logs on data devices */
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
	uint32_t devices_needed = ah->area_count + ah->parity_count;
 | 
			
		||||
	uint32_t required;
 | 
			
		||||
@@ -3005,17 +3005,17 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 | 
			
		||||
 | 
			
		||||
	/* num_positional_areas holds the number of parallel allocations that must be contiguous/cling */
 | 
			
		||||
	/* These appear first in the array, so it is also the offset to the non-preferred allocations */
 | 
			
		||||
	/* At most one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG or A_CLING_TO_ALLOCED may be set */
 | 
			
		||||
	/* At most one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG or A_CLING_TO_ALLOCATED may be set */
 | 
			
		||||
	if (!(alloc_parms->flags & A_POSITIONAL_FILL))
 | 
			
		||||
		alloc_state->num_positional_areas = 0;
 | 
			
		||||
	else if (alloc_parms->flags & (A_CONTIGUOUS_TO_LVSEG | A_CLING_TO_LVSEG))
 | 
			
		||||
		alloc_state->num_positional_areas = _stripes_per_mimage(alloc_parms->prev_lvseg) * alloc_parms->prev_lvseg->area_count;
 | 
			
		||||
	else if (alloc_parms->flags & A_CLING_TO_ALLOCED)
 | 
			
		||||
	else if (alloc_parms->flags & A_CLING_TO_ALLOCATED)
 | 
			
		||||
		alloc_state->num_positional_areas = ah->area_count;
 | 
			
		||||
 | 
			
		||||
	if (alloc_parms->alloc == ALLOC_NORMAL || (alloc_parms->flags & A_CLING_TO_ALLOCED))
 | 
			
		||||
	if (alloc_parms->alloc == ALLOC_NORMAL || (alloc_parms->flags & A_CLING_TO_ALLOCATED))
 | 
			
		||||
		log_debug_alloc("Cling_to_allocated is %sset",
 | 
			
		||||
				alloc_parms->flags & A_CLING_TO_ALLOCED ? "" : "not ");
 | 
			
		||||
				alloc_parms->flags & A_CLING_TO_ALLOCATED ? "" : "not ");
 | 
			
		||||
 | 
			
		||||
	if (alloc_parms->flags & A_POSITIONAL_FILL)
 | 
			
		||||
		log_debug_alloc("%u preferred area(s) to be filled positionally.", alloc_state->num_positional_areas);
 | 
			
		||||
@@ -3053,7 +3053,7 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 | 
			
		||||
			if (alloc_parms->alloc != ALLOC_ANYWHERE) {
 | 
			
		||||
				/* Don't allocate onto the log PVs */
 | 
			
		||||
				if (ah->log_area_count)
 | 
			
		||||
					dm_list_iterate_items(aa, &ah->alloced_areas[ah->area_count])
 | 
			
		||||
					dm_list_iterate_items(aa, &ah->allocated_areas[ah->area_count])
 | 
			
		||||
						for (s = 0; s < ah->log_area_count; s++)
 | 
			
		||||
							if (!aa[s].pv)
 | 
			
		||||
								goto next_pv;
 | 
			
		||||
@@ -3136,17 +3136,17 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
	} while ((alloc_parms->alloc == ALLOC_ANYWHERE && last_ix != ix && ix < devices_needed + alloc_state->log_area_count_still_needed) ||
 | 
			
		||||
		/* With cling_to_alloced and normal, if there were gaps in the preferred areas, have a second iteration */
 | 
			
		||||
		/* With cling_to_allocated and normal, if there were gaps in the preferred areas, have a second iteration */
 | 
			
		||||
		 (alloc_parms->alloc == ALLOC_NORMAL && preferred_count &&
 | 
			
		||||
		  (preferred_count < alloc_state->num_positional_areas || alloc_state->log_area_count_still_needed) &&
 | 
			
		||||
		  (alloc_parms->flags & A_CLING_TO_ALLOCED) && !iteration_count++) ||
 | 
			
		||||
		  (alloc_parms->flags & A_CLING_TO_ALLOCATED) && !iteration_count++) ||
 | 
			
		||||
		/* Extra iteration needed to fill log areas on PVs already used? */
 | 
			
		||||
		 (alloc_parms->alloc == ALLOC_NORMAL && preferred_count == alloc_state->num_positional_areas && !ah->mirror_logs_separate &&
 | 
			
		||||
		  (ix + preferred_count >= devices_needed) &&
 | 
			
		||||
		  (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed) && !log_iteration_count++));
 | 
			
		||||
 | 
			
		||||
	/* Non-zero ix means at least one USE_AREA was returned */
 | 
			
		||||
	if (preferred_count < alloc_state->num_positional_areas && !(alloc_parms->flags & A_CLING_TO_ALLOCED) && !ix)
 | 
			
		||||
	if (preferred_count < alloc_state->num_positional_areas && !(alloc_parms->flags & A_CLING_TO_ALLOCATED) && !ix)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed)
 | 
			
		||||
@@ -3313,7 +3313,7 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
 | 
			
		||||
		 * set we allow two passes, first with A_POSITIONAL_FILL then without.
 | 
			
		||||
		 *
 | 
			
		||||
		 * If we didn't allocate anything this time with ALLOC_NORMAL and had
 | 
			
		||||
		 * A_CLING_TO_ALLOCED set, try again without it.
 | 
			
		||||
		 * A_CLING_TO_ALLOCATED set, try again without it.
 | 
			
		||||
		 *
 | 
			
		||||
		 * For ALLOC_NORMAL, if we did allocate something without the
 | 
			
		||||
		 * flag set, set it and continue so that further allocations
 | 
			
		||||
@@ -3323,13 +3323,13 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, stru
 | 
			
		||||
			if (ah->maximise_cling && ((alloc_parms->alloc == ALLOC_CLING) || (alloc_parms->alloc == ALLOC_CLING_BY_TAGS)) &&
 | 
			
		||||
			    (alloc_parms->flags & A_CLING_TO_LVSEG) && (alloc_parms->flags & A_POSITIONAL_FILL))
 | 
			
		||||
				alloc_parms->flags &= ~A_POSITIONAL_FILL;
 | 
			
		||||
			else if ((alloc_parms->alloc == ALLOC_NORMAL) && (alloc_parms->flags & A_CLING_TO_ALLOCED))
 | 
			
		||||
				alloc_parms->flags &= ~A_CLING_TO_ALLOCED;
 | 
			
		||||
			else if ((alloc_parms->alloc == ALLOC_NORMAL) && (alloc_parms->flags & A_CLING_TO_ALLOCATED))
 | 
			
		||||
				alloc_parms->flags &= ~A_CLING_TO_ALLOCATED;
 | 
			
		||||
			else
 | 
			
		||||
				break;	/* Give up */
 | 
			
		||||
		} else if (ah->maximise_cling && alloc_parms->alloc == ALLOC_NORMAL &&
 | 
			
		||||
			   !(alloc_parms->flags & A_CLING_TO_ALLOCED))
 | 
			
		||||
			alloc_parms->flags |= A_CLING_TO_ALLOCED;
 | 
			
		||||
			   !(alloc_parms->flags & A_CLING_TO_ALLOCATED))
 | 
			
		||||
			alloc_parms->flags |= A_CLING_TO_ALLOCATED;
 | 
			
		||||
	} while ((alloc_parms->alloc != ALLOC_CONTIGUOUS) && alloc_state->allocated != alloc_parms->extents_still_needed && (alloc_parms->flags & A_CAN_SPLIT) && (!ah->approx_alloc || pv_maps_size(pvms)));
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -3622,7 +3622,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
 | 
			
		||||
		/* mirrors specify their exact log count */
 | 
			
		||||
		alloc_count += metadata_area_count;
 | 
			
		||||
 | 
			
		||||
	size += sizeof(ah->alloced_areas[0]) * alloc_count;
 | 
			
		||||
	size += sizeof(ah->allocated_areas[0]) * alloc_count;
 | 
			
		||||
 | 
			
		||||
	if (!(mem = dm_pool_create("allocation", 1024))) {
 | 
			
		||||
		log_error("allocation pool creation failed");
 | 
			
		||||
@@ -3727,7 +3727,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
 | 
			
		||||
	ah->new_extents = total_extents;
 | 
			
		||||
 | 
			
		||||
	for (s = 0; s < alloc_count; s++)
 | 
			
		||||
		dm_list_init(&ah->alloced_areas[s]);
 | 
			
		||||
		dm_list_init(&ah->allocated_areas[s]);
 | 
			
		||||
 | 
			
		||||
	ah->parallel_areas = parallel_areas;
 | 
			
		||||
 | 
			
		||||
@@ -3825,7 +3825,7 @@ int lv_add_segment(struct alloc_handle *ah,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_setup_alloced_segments(lv, &ah->alloced_areas[first_area],
 | 
			
		||||
	if (!_setup_allocated_segments(lv, &ah->allocated_areas[first_area],
 | 
			
		||||
				     num_areas, status,
 | 
			
		||||
				     stripe_size, segtype,
 | 
			
		||||
				     region_size))
 | 
			
		||||
@@ -3898,7 +3898,7 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
 | 
			
		||||
				  uint32_t region_size)
 | 
			
		||||
{
 | 
			
		||||
	char *image_name;
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
	struct lv_segment *seg, *new_seg;
 | 
			
		||||
	uint32_t current_le = le;
 | 
			
		||||
	uint32_t s;
 | 
			
		||||
@@ -3923,7 +3923,7 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
 | 
			
		||||
	 * single segment of the original LV, that LV segment must be
 | 
			
		||||
	 * split up to match.
 | 
			
		||||
	 */
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->alloced_areas[0]) {
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->allocated_areas[0]) {
 | 
			
		||||
		if (!(seg = find_seg_by_le(lv, current_le))) {
 | 
			
		||||
			log_error("Failed to find segment for %s extent " FMTu32 ".",
 | 
			
		||||
				  display_lvname(lv), current_le);
 | 
			
		||||
@@ -3965,7 +3965,7 @@ int lv_add_segmented_mirror_image(struct alloc_handle *ah,
 | 
			
		||||
	if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->alloced_areas[0]) {
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->allocated_areas[0]) {
 | 
			
		||||
		if (!(seg = find_seg_by_le(orig_lv, current_le))) {
 | 
			
		||||
			log_error("Failed to find segment for %s extent " FMTu32 ".",
 | 
			
		||||
				  display_lvname(lv), current_le);
 | 
			
		||||
@@ -4007,12 +4007,12 @@ int lv_add_mirror_areas(struct alloc_handle *ah,
 | 
			
		||||
			struct logical_volume *lv, uint32_t le,
 | 
			
		||||
			uint32_t region_size)
 | 
			
		||||
{
 | 
			
		||||
	struct alloced_area *aa;
 | 
			
		||||
	struct allocated_area *aa;
 | 
			
		||||
	struct lv_segment *seg;
 | 
			
		||||
	uint32_t current_le = le;
 | 
			
		||||
	uint32_t s, old_area_count, new_area_count;
 | 
			
		||||
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->alloced_areas[0]) {
 | 
			
		||||
	dm_list_iterate_items(aa, &ah->allocated_areas[0]) {
 | 
			
		||||
		if (!(seg = find_seg_by_le(lv, current_le))) {
 | 
			
		||||
			log_error("Failed to find segment for %s extent " FMTu32 ".",
 | 
			
		||||
				  display_lvname(lv), current_le);
 | 
			
		||||
@@ -5889,8 +5889,8 @@ static int _lv_resize_volume(struct logical_volume *lv,
 | 
			
		||||
	alloc_policy_t alloc = lp->alloc ? : lv->alloc;
 | 
			
		||||
 | 
			
		||||
	old_extents = lv->le_count;
 | 
			
		||||
	log_verbose("%sing logical volume %s to %s%s",
 | 
			
		||||
		    (lp->resize == LV_REDUCE) ? "Reduc" : "Extend",
 | 
			
		||||
	log_verbose("%s logical volume %s to %s%s",
 | 
			
		||||
		    (lp->resize == LV_REDUCE) ? "Reducing" : "Extending",
 | 
			
		||||
		    display_lvname(lv), lp->approx_alloc ? "up to " : "",
 | 
			
		||||
		    display_size(cmd, (uint64_t) lp->extents * vg->extent_size));
 | 
			
		||||
 | 
			
		||||
@@ -6144,6 +6144,8 @@ static int _fs_reduce_allow(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		if (fsi->mounted)
 | 
			
		||||
			fsi->needs_unmount = 1;
 | 
			
		||||
 | 
			
		||||
		fsi->needs_reduce = 1;
 | 
			
		||||
	} else if (!strcmp(fsi->fstype, "swap")) {
 | 
			
		||||
		fsi->needs_reduce = 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		/*
 | 
			
		||||
@@ -6314,6 +6316,8 @@ static int _fs_extend_allow(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		if (lp->nofsck)
 | 
			
		||||
			fsi->needs_fsck = 0;
 | 
			
		||||
 | 
			
		||||
	} else if (!strcmp(fsi->fstype, "swap")) {
 | 
			
		||||
		fsi->needs_extend = 1;
 | 
			
		||||
	} else if (!strcmp(fsi->fstype, "xfs")) {
 | 
			
		||||
		fs_extend_cmd = " xfs_growfs";
 | 
			
		||||
 | 
			
		||||
@@ -6887,6 +6891,10 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the LV is locked due to being active, this lock call is a no-op.
 | 
			
		||||
	 * Otherwise, this acquires a transient lock on the lv (not PERSISTENT)
 | 
			
		||||
	 * FIXME: should probably use a persistent lock in case the command
 | 
			
		||||
	 * crashes while the lv is active, in which case we'd want the active
 | 
			
		||||
	 * lv to remain locked. This means then adding lockd_lv("un") at the
 | 
			
		||||
	 * end.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!lockd_lv_resize(cmd, lv_top, "ex", 0, lp))
 | 
			
		||||
		return_0;
 | 
			
		||||
@@ -7549,6 +7557,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
	int visible, historical;
 | 
			
		||||
	struct logical_volume *pool_lv = NULL;
 | 
			
		||||
	struct logical_volume *lock_lv = lv;
 | 
			
		||||
	struct logical_volume *lockd_pool = NULL;
 | 
			
		||||
	struct lv_segment *cache_seg = NULL;
 | 
			
		||||
	struct seg_list *sl;
 | 
			
		||||
	struct lv_segment *seg = first_seg(lv);
 | 
			
		||||
@@ -7613,8 +7622,21 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lockd_lv(cmd, lock_lv, "ex", LDLV_PERSISTENT))
 | 
			
		||||
		return_0;
 | 
			
		||||
	if (vg_is_shared(vg)) {
 | 
			
		||||
		if (lv_is_thin_type(lv)) {
 | 
			
		||||
			/* FIXME: is this also needed for other types? */
 | 
			
		||||
			/* Thin is special because it needs to be active and locked to remove. */
 | 
			
		||||
			if (lv_is_thin_volume(lv))
 | 
			
		||||
				lockd_pool = first_seg(lv)->pool_lv;
 | 
			
		||||
			else if (lv_is_thin_pool(lv))
 | 
			
		||||
				lockd_pool = lv;
 | 
			
		||||
			if (!lockd_lv(cmd, lock_lv, "ex", LDLV_PERSISTENT))
 | 
			
		||||
				return_0;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (!lockd_lv(cmd, lock_lv, "ex", LDLV_PERSISTENT))
 | 
			
		||||
				return_0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lv_is_cache_vol(lv)) {
 | 
			
		||||
		if (!_lv_remove_check_in_use(lv, force))
 | 
			
		||||
@@ -7763,8 +7785,13 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
 | 
			
		||||
					display_lvname(pool_lv));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!lockd_lv(cmd, lv, "un", LDLV_PERSISTENT))
 | 
			
		||||
		log_warn("WARNING: Failed to unlock %s.", display_lvname(lv));
 | 
			
		||||
	if (lockd_pool && !thin_pool_is_active(lockd_pool)) {
 | 
			
		||||
		if (!lockd_lv_name(cmd, vg, lockd_pool->name, &lockd_pool->lvid.id[1], lockd_pool->lock_args, "un", LDLV_PERSISTENT))
 | 
			
		||||
			log_warn("WARNING: Failed to unlock %s.", display_lvname(lockd_pool));
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!lockd_lv(cmd, lv, "un", LDLV_PERSISTENT))
 | 
			
		||||
			log_warn("WARNING: Failed to unlock %s.", display_lvname(lv));
 | 
			
		||||
	}
 | 
			
		||||
	lockd_free_lv(cmd, vg, lv->name, &lv->lvid.id[1], lv->lock_args);
 | 
			
		||||
 | 
			
		||||
	if (!suppress_remove_message && (visible || historical)) {
 | 
			
		||||
@@ -9243,6 +9270,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
 | 
			
		||||
					return_NULL;
 | 
			
		||||
				/* New pool is now inactive */
 | 
			
		||||
			} else {
 | 
			
		||||
				if (!lockd_lv(cmd, pool_lv, "ex", LDLV_PERSISTENT)) {
 | 
			
		||||
					log_error("Failed to lock thin pool.");
 | 
			
		||||
					return NULL;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!activate_lv(cmd, pool_lv)) {
 | 
			
		||||
					log_error("Aborting. Failed to locally activate thin pool %s.",
 | 
			
		||||
						  display_lvname(pool_lv));
 | 
			
		||||
@@ -9624,6 +9656,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
 | 
			
		||||
				/* Avoid multiple thin-pool activations in this case */
 | 
			
		||||
				if (thin_pool_was_active < 0)
 | 
			
		||||
					thin_pool_was_active = 0;
 | 
			
		||||
				if (!lockd_lv(cmd, pool_lv, "ex", LDLV_PERSISTENT)) {
 | 
			
		||||
					log_error("Failed to lock thin pool.");
 | 
			
		||||
					return NULL;
 | 
			
		||||
				}
 | 
			
		||||
				if (!activate_lv(cmd, pool_lv)) {
 | 
			
		||||
					log_error("Failed to activate thin pool %s.",
 | 
			
		||||
						  display_lvname(pool_lv));
 | 
			
		||||
@@ -9648,11 +9684,15 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Restore inactive state if needed */
 | 
			
		||||
		if (!thin_pool_was_active &&
 | 
			
		||||
		    !deactivate_lv(cmd, pool_lv)) {
 | 
			
		||||
			log_error("Failed to deactivate thin pool %s.",
 | 
			
		||||
				  display_lvname(pool_lv));
 | 
			
		||||
			return NULL;
 | 
			
		||||
		if (!thin_pool_was_active) {
 | 
			
		||||
			if (!deactivate_lv(cmd, pool_lv)) {
 | 
			
		||||
				log_error("Failed to deactivate thin pool %s.", display_lvname(pool_lv));
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
			if (!lockd_lv(cmd, pool_lv, "un", LDLV_PERSISTENT)) {
 | 
			
		||||
				log_error("Failed to unlock thin pool.");
 | 
			
		||||
				return NULL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if (lp->snapshot) {
 | 
			
		||||
		lv->status |= LV_TEMPORARY;
 | 
			
		||||
 
 | 
			
		||||
@@ -255,7 +255,8 @@ struct segtype_handler {
 | 
			
		||||
				       uint32_t *area_count);
 | 
			
		||||
	int (*text_import) (struct lv_segment * seg,
 | 
			
		||||
			    const struct dm_config_node * sn,
 | 
			
		||||
			    struct dm_hash_table * pv_hash);
 | 
			
		||||
			    struct dm_hash_table * pv_hash,
 | 
			
		||||
			    struct dm_hash_table * lv_hash);
 | 
			
		||||
	int (*merge_segments) (struct lv_segment * seg1,
 | 
			
		||||
			       struct lv_segment * seg2);
 | 
			
		||||
	int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
 | 
			
		||||
 
 | 
			
		||||
@@ -572,6 +572,9 @@ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (*vwp != DM_VDO_WRITE_POLICY_AUTO)
 | 
			
		||||
		log_info("Deprecated VDO setting write_policy specified.");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -626,6 +629,9 @@ int fill_vdo_target_params(struct cmd_context *cmd,
 | 
			
		||||
 | 
			
		||||
	*vdo_pool_header_size = 2 * find_config_tree_int64(cmd, allocation_vdo_pool_header_size_CFG, profile);
 | 
			
		||||
 | 
			
		||||
	if (vtp->use_metadata_hints)
 | 
			
		||||
		log_info("Deprecated VDO setting use_metadata_hints specified.");
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,12 +46,6 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
 | 
			
		||||
	vg->vgmem = vgmem;
 | 
			
		||||
	vg->alloc = ALLOC_NORMAL;
 | 
			
		||||
 | 
			
		||||
	if (!(vg->hostnames = dm_hash_create(14))) {
 | 
			
		||||
		log_error("Failed to allocate VG hostname hashtable.");
 | 
			
		||||
		dm_pool_destroy(vgmem);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dm_list_init(&vg->pvs);
 | 
			
		||||
	dm_list_init(&vg->pv_write_list);
 | 
			
		||||
	dm_list_init(&vg->lvs);
 | 
			
		||||
@@ -81,7 +75,6 @@ static void _free_vg(struct volume_group *vg)
 | 
			
		||||
 | 
			
		||||
	if (vg->committed_cft)
 | 
			
		||||
		config_destroy(vg->committed_cft);
 | 
			
		||||
	dm_hash_destroy(vg->hostnames);
 | 
			
		||||
	dm_pool_destroy(vg->vgmem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -129,7 +129,6 @@ struct volume_group {
 | 
			
		||||
 | 
			
		||||
	uint32_t mda_copies; /* target number of mdas for this VG */
 | 
			
		||||
 | 
			
		||||
	struct dm_hash_table *hostnames; /* map of creation hostnames */
 | 
			
		||||
	struct logical_volume *pool_metadata_spare_lv; /* one per VG */
 | 
			
		||||
	struct logical_volume *sanlock_lv; /* one per VG */
 | 
			
		||||
	struct dm_list msg_list;
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,8 @@ static int _mirrored_text_import_area_count(const struct dm_config_node *sn, uin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
 | 
			
		||||
			struct dm_hash_table *pv_hash)
 | 
			
		||||
			struct dm_hash_table *pv_hash,
 | 
			
		||||
			struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const struct dm_config_value *cv;
 | 
			
		||||
	const char *logname = NULL;
 | 
			
		||||
@@ -102,7 +103,7 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dm_config_get_str(sn, "mirror_log", &logname)) {
 | 
			
		||||
		if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
 | 
			
		||||
		if (!(seg->log_lv = dm_hash_lookup(lv_hash, logname))) {
 | 
			
		||||
			log_error("Unrecognised mirror log in "
 | 
			
		||||
				  "segment %s of logical volume %s.",
 | 
			
		||||
				  dm_config_parent_name(sn), seg->lv->name);
 | 
			
		||||
 
 | 
			
		||||
@@ -517,6 +517,13 @@ static void _restore_priority_if_possible(struct cmd_context *cmd)
 | 
			
		||||
/* Stop memory getting swapped out */
 | 
			
		||||
static void _lock_mem(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	if (!_size_stack || _size_malloc_tmp) {
 | 
			
		||||
		log_debug_mem("Skipping memory locking (reserved memory: "
 | 
			
		||||
			      FMTsize_t "  stack: " FMTsize_t ").",
 | 
			
		||||
			      _size_malloc_tmp, _size_stack);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!cmd->running_on_valgrind)
 | 
			
		||||
		 _allocate_memory();
 | 
			
		||||
	(void)strerror(0);		/* Force libc.mo load */
 | 
			
		||||
@@ -557,6 +564,13 @@ static void _unlock_mem(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	size_t unlock_mstats = 0;
 | 
			
		||||
 | 
			
		||||
	if (!_size_stack || _size_malloc_tmp) {
 | 
			
		||||
		log_debug_mem("Skipping memory unlocking (reserved memory: "
 | 
			
		||||
			      FMTsize_t "  stack: " FMTsize_t ").",
 | 
			
		||||
			      _size_malloc_tmp, _size_stack);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_very_verbose("Unlocking memory");
 | 
			
		||||
 | 
			
		||||
	if (!_memlock_maps(cmd, LVM_MUNLOCK, &unlock_mstats))
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ void lvmnotify_send(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* If lvmdbusd isn't running, don't notify as you will start it as it will auto activate */
 | 
			
		||||
	if (!lvmdbusd_running()) {
 | 
			
		||||
		log_debug_dbus("dbus damon not running, not notifying");
 | 
			
		||||
		log_debug_dbus("dbus daemon not running, not notifying");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,8 @@ static int _raid_text_import_area_count(const struct dm_config_node *sn,
 | 
			
		||||
 | 
			
		||||
static int _raid_text_import_areas(struct lv_segment *seg,
 | 
			
		||||
				   const struct dm_config_node *sn,
 | 
			
		||||
				   const struct dm_config_value *cv)
 | 
			
		||||
				   const struct dm_config_value *cv,
 | 
			
		||||
				   struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int s;
 | 
			
		||||
	struct logical_volume *lv;
 | 
			
		||||
@@ -88,7 +89,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Metadata device comes first. */
 | 
			
		||||
		if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
 | 
			
		||||
		if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) {
 | 
			
		||||
			log_error("Couldn't find volume '%s' for segment '%s'.",
 | 
			
		||||
				  cv->v.str ? : "NULL", seg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -106,7 +107,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Data device comes second */
 | 
			
		||||
		if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
 | 
			
		||||
		if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) {
 | 
			
		||||
			log_error("Couldn't find volume '%s' for segment '%s'.",
 | 
			
		||||
				  cv->v.str ? : "NULL", seg_name);
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -129,7 +130,8 @@ static int _raid_text_import_areas(struct lv_segment *seg,
 | 
			
		||||
 | 
			
		||||
static int _raid_text_import(struct lv_segment *seg,
 | 
			
		||||
			     const struct dm_config_node *sn,
 | 
			
		||||
			     struct dm_hash_table *pv_hash)
 | 
			
		||||
			     struct dm_hash_table *pv_hash,
 | 
			
		||||
			     struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const struct dm_config_value *cv;
 | 
			
		||||
	const struct {
 | 
			
		||||
@@ -171,7 +173,7 @@ static int _raid_text_import(struct lv_segment *seg,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_raid_text_import_areas(seg, sn, cv)) {
 | 
			
		||||
	if (!_raid_text_import_areas(seg, sn, cv, lv_hash)) {
 | 
			
		||||
		log_error("Failed to import RAID component pairs.");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -295,7 +295,6 @@ FIELD(SEGS, seg, STR_LIST, "IntegSettings", list, 0, integrity_settings, integri
 | 
			
		||||
 | 
			
		||||
FIELD(SEGS, seg, BIN, "VDOCompression", list, 0, vdo_compression, vdo_compression, "Set for compressed LV (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, BIN, "VDODeduplication", list, 0, vdo_deduplication, vdo_deduplication, "Set for deduplicated LV (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, BIN, "VDOMetadataHints", list, 0, vdo_use_metadata_hints, vdo_use_metadata_hints, "Use REQ_SYNC for writes (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, NUM, "VDOMinimumIOSize", list, 0, vdo_minimum_io_size, vdo_minimum_io_size, "Minimum acceptable IO size (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, SIZ, "VDOBlockMapCacheSize", list, 0, vdo_block_map_cache_size, vdo_block_map_cache_size, "Allocated caching size (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, NUM, "VDOBlockMapEraLength", list, 0, vdo_block_map_era_length, vdo_block_map_era_length, "Speed of cache writes (vdopool).", 0)
 | 
			
		||||
@@ -310,8 +309,9 @@ FIELD(SEGS, seg, NUM, "VDOHashZoneThreads", list, 0, vdo_hash_zone_threads, vdo_
 | 
			
		||||
FIELD(SEGS, seg, NUM, "VDOLogicalThreads", list, 0, vdo_logical_threads, vdo_logical_threads, "Logical threads for subdivide parts (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, NUM, "VDOPhysicalThreads", list, 0, vdo_physical_threads, vdo_physical_threads, "Physical threads for subdivide parts (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, NUM, "VDOMaxDiscard", list, 0, vdo_max_discard, vdo_max_discard, "Maximum discard size volume can receive (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, STR, "VDOWritePolicy", list, 0, vdo_write_policy, vdo_write_policy, "Specified write policy (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, SIZ, "VDOHeaderSize", list, 0, vdo_header_size, vdo_header_size, "Header size at front of vdopool.", 0)
 | 
			
		||||
FIELD(SEGS, seg, BIN, "VDOMetadataHints", list, 0, vdo_use_metadata_hints, vdo_use_metadata_hints, "Deprecated use of REQ_SYNC for writes (vdopool).", 0)
 | 
			
		||||
FIELD(SEGS, seg, STR, "VDOWritePolicy", list, 0, vdo_write_policy, vdo_write_policy, "Deprecated write policy (vdopool).", 0)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * End of SEGS type fields
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,8 @@ static const char *_snap_target_name(const struct lv_segment *seg,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
 | 
			
		||||
			struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
			struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
			struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t chunk_size;
 | 
			
		||||
	struct logical_volume *org, *cow;
 | 
			
		||||
@@ -71,11 +72,11 @@ static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node
 | 
			
		||||
	if (!(org_name = dm_config_find_str(sn, "origin", NULL)))
 | 
			
		||||
		return SEG_LOG_ERROR("Snapshot origin must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(cow = find_lv(seg->lv->vg, cow_name)))
 | 
			
		||||
	if (!(cow = dm_hash_lookup(lv_hash, cow_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
				     "snapshot cow store in", cow_name);
 | 
			
		||||
 | 
			
		||||
	if (!(org = find_lv(seg->lv->vg, org_name)))
 | 
			
		||||
	if (!(org = dm_hash_lookup(lv_hash, org_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for "
 | 
			
		||||
			  "snapshot origin in", org_name);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,8 @@ static int _striped_text_import_area_count(const struct dm_config_node *sn, uint
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
 | 
			
		||||
			struct dm_hash_table *pv_hash)
 | 
			
		||||
			struct dm_hash_table *pv_hash,
 | 
			
		||||
			struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const struct dm_config_value *cv;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,8 @@ static void _thin_pool_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
static int _thin_pool_add_message(struct lv_segment *seg,
 | 
			
		||||
				  const char *key,
 | 
			
		||||
				  const struct dm_config_node *sn)
 | 
			
		||||
				  const struct dm_config_node *sn,
 | 
			
		||||
				  struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const char *lv_name = NULL;
 | 
			
		||||
	struct logical_volume *lv = NULL;
 | 
			
		||||
@@ -62,7 +63,7 @@ static int _thin_pool_add_message(struct lv_segment *seg,
 | 
			
		||||
 | 
			
		||||
	/* Message must have only one from: create, delete */
 | 
			
		||||
	if (dm_config_get_str(sn, "create", &lv_name)) {
 | 
			
		||||
		if (!(lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
		if (!(lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
			return SEG_LOG_ERROR("Unknown LV %s for create message in",
 | 
			
		||||
					     lv_name);
 | 
			
		||||
		/* FIXME: switch to _SNAP later, if the created LV has an origin */
 | 
			
		||||
@@ -80,7 +81,8 @@ static int _thin_pool_add_message(struct lv_segment *seg,
 | 
			
		||||
 | 
			
		||||
static int _thin_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
				  const struct dm_config_node *sn,
 | 
			
		||||
				  struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
				  struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
				  struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const char *lv_name;
 | 
			
		||||
	struct logical_volume *pool_data_lv, *pool_metadata_lv;
 | 
			
		||||
@@ -91,13 +93,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_get_str(sn, "metadata", &lv_name))
 | 
			
		||||
		return SEG_LOG_ERROR("Metadata must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(pool_metadata_lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
	if (!(pool_metadata_lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown metadata %s in", lv_name);
 | 
			
		||||
 | 
			
		||||
	if (!dm_config_get_str(sn, "pool", &lv_name))
 | 
			
		||||
		return SEG_LOG_ERROR("Pool must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(pool_data_lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
	if (!(pool_data_lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown pool %s in", lv_name);
 | 
			
		||||
 | 
			
		||||
	if (!attach_pool_data_lv(seg, pool_data_lv))
 | 
			
		||||
@@ -141,7 +143,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
 | 
			
		||||
	/* Read messages */
 | 
			
		||||
	for (; sn; sn = sn->sib)
 | 
			
		||||
		if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
 | 
			
		||||
		if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child, lv_hash))
 | 
			
		||||
			return_0;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -468,7 +470,8 @@ static void _thin_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
static int _thin_text_import(struct lv_segment *seg,
 | 
			
		||||
			     const struct dm_config_node *sn,
 | 
			
		||||
			     struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
			     struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
			     struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	const char *lv_name;
 | 
			
		||||
	struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL, *merge_lv = NULL;
 | 
			
		||||
@@ -477,7 +480,7 @@ static int _thin_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_get_str(sn, "thin_pool", &lv_name))
 | 
			
		||||
		return SEG_LOG_ERROR("Thin pool must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(pool_lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
	if (!(pool_lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown thin pool %s in", lv_name);
 | 
			
		||||
 | 
			
		||||
	if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id))
 | 
			
		||||
@@ -487,14 +490,14 @@ static int _thin_text_import(struct lv_segment *seg,
 | 
			
		||||
		if (!dm_config_get_str(sn, "origin", &lv_name))
 | 
			
		||||
			return SEG_LOG_ERROR("Origin must be a string in");
 | 
			
		||||
 | 
			
		||||
		if (!(origin = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
		if (!(origin = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
			return SEG_LOG_ERROR("Unknown origin %s in", lv_name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dm_config_has_node(sn, "merge")) {
 | 
			
		||||
		if (!dm_config_get_str(sn, "merge", &lv_name))
 | 
			
		||||
			return SEG_LOG_ERROR("Merge lv must be a string in");
 | 
			
		||||
		if (!(merge_lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
		if (!(merge_lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
			return SEG_LOG_ERROR("Unknown merge lv %s in", lv_name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -509,7 +512,7 @@ static int _thin_text_import(struct lv_segment *seg,
 | 
			
		||||
		if (!dm_config_get_str(sn, "external_origin", &lv_name))
 | 
			
		||||
			return SEG_LOG_ERROR("External origin must be a string in");
 | 
			
		||||
 | 
			
		||||
		if (!(external_lv = find_lv(seg->lv->vg, lv_name)))
 | 
			
		||||
		if (!(external_lv = dm_hash_lookup(lv_hash, lv_name)))
 | 
			
		||||
			return SEG_LOG_ERROR("Unknown external origin %s in", lv_name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,8 @@
 | 
			
		||||
#include "lib/config/config.h"
 | 
			
		||||
 | 
			
		||||
static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
 | 
			
		||||
				struct dm_hash_table *pv_hash)
 | 
			
		||||
				struct dm_hash_table *pv_hash,
 | 
			
		||||
				struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_config_node *new, *last = NULL, *head = NULL;
 | 
			
		||||
	const struct dm_config_node *current;
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,8 @@ static void _vdo_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
static int _vdo_text_import(struct lv_segment *seg,
 | 
			
		||||
			    const struct dm_config_node *n,
 | 
			
		||||
			    struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
			    struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
			    struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *vdo_pool_lv;
 | 
			
		||||
	const char *str;
 | 
			
		||||
@@ -84,7 +85,7 @@ static int _vdo_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_has_node(n, "vdo_pool") ||
 | 
			
		||||
	    !(str = dm_config_find_str(n, "vdo_pool", NULL)))
 | 
			
		||||
		return _bad_field("vdo_pool");
 | 
			
		||||
	if (!(vdo_pool_lv = find_lv(seg->lv->vg, str))) {
 | 
			
		||||
	if (!(vdo_pool_lv = dm_hash_lookup(lv_hash, str))) {
 | 
			
		||||
		log_error("Unknown VDO pool logical volume %s.", str);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -167,7 +168,8 @@ static void _vdo_pool_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
	_print_yes_no("Compression\t", vtp->use_compression);
 | 
			
		||||
	_print_yes_no("Deduplication", vtp->use_deduplication);
 | 
			
		||||
	_print_yes_no("Metadata hints", vtp->use_metadata_hints);
 | 
			
		||||
	if (vtp->use_metadata_hints)
 | 
			
		||||
		_print_yes_no("Metadata hints", vtp->use_metadata_hints);
 | 
			
		||||
 | 
			
		||||
	log_print("  Minimum IO size\t%s",
 | 
			
		||||
		  display_size(cmd, vtp->minimum_io_size));
 | 
			
		||||
@@ -191,7 +193,8 @@ static void _vdo_pool_display(const struct lv_segment *seg)
 | 
			
		||||
	log_print("  # Logical threads\t%u", (unsigned) vtp->logical_threads);
 | 
			
		||||
	log_print("  # Physical threads\t%u", (unsigned) vtp->physical_threads);
 | 
			
		||||
	log_print("  Max discard\t\t%u", (unsigned) vtp->max_discard);
 | 
			
		||||
	log_print("  Write policy\t%s", get_vdo_write_policy_name(vtp->write_policy));
 | 
			
		||||
	if (vtp->write_policy != DM_VDO_WRITE_POLICY_AUTO)
 | 
			
		||||
		log_print("  Write policy\t%s", get_vdo_write_policy_name(vtp->write_policy));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* reused as _vdo_text_import_area_count */
 | 
			
		||||
@@ -205,7 +208,8 @@ static int _vdo_pool_text_import_area_count(const struct dm_config_node *sn __at
 | 
			
		||||
 | 
			
		||||
static int _vdo_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
				 const struct dm_config_node *n,
 | 
			
		||||
				 struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
				 struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
				 struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct dm_vdo_target_params *vtp = &seg->vdo_params;
 | 
			
		||||
	struct logical_volume *data_lv;
 | 
			
		||||
@@ -214,7 +218,7 @@ static int _vdo_pool_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_has_node(n, "data") ||
 | 
			
		||||
	    !(str = dm_config_find_str(n, "data", NULL)))
 | 
			
		||||
		return _bad_field("data");
 | 
			
		||||
	if (!(data_lv = find_lv(seg->lv->vg, str))) {
 | 
			
		||||
	if (!(data_lv = dm_hash_lookup(lv_hash, str))) {
 | 
			
		||||
		log_error("Unknown logical volume %s.", str);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,8 @@ static void _writecache_display(const struct lv_segment *seg)
 | 
			
		||||
 | 
			
		||||
static int _writecache_text_import(struct lv_segment *seg,
 | 
			
		||||
				   const struct dm_config_node *sn,
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)))
 | 
			
		||||
				   struct dm_hash_table *pv_hash __attribute__((unused)),
 | 
			
		||||
				   struct dm_hash_table *lv_hash)
 | 
			
		||||
{
 | 
			
		||||
	struct logical_volume *origin_lv = NULL;
 | 
			
		||||
	struct logical_volume *fast_lv;
 | 
			
		||||
@@ -53,7 +54,7 @@ static int _writecache_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_get_str(sn, "origin", &origin_name))
 | 
			
		||||
		return SEG_LOG_ERROR("origin must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(origin_lv = find_lv(seg->lv->vg, origin_name)))
 | 
			
		||||
	if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown LV specified for writecache origin %s in", origin_name);
 | 
			
		||||
 | 
			
		||||
	if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
 | 
			
		||||
@@ -65,7 +66,7 @@ static int _writecache_text_import(struct lv_segment *seg,
 | 
			
		||||
	if (!dm_config_get_str(sn, "writecache", &fast_name))
 | 
			
		||||
		return SEG_LOG_ERROR("writecache must be a string in");
 | 
			
		||||
 | 
			
		||||
	if (!(fast_lv = find_lv(seg->lv->vg, fast_name)))
 | 
			
		||||
	if (!(fast_lv = dm_hash_lookup(lv_hash, fast_name)))
 | 
			
		||||
		return SEG_LOG_ERROR("Unknown logical volume %s specified for writecache in",
 | 
			
		||||
				     fast_name);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3670,7 +3670,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
 | 
			
		||||
 */
 | 
			
		||||
#define DM_UDEV_DISABLE_DM_RULES_FLAG 0x0001
 | 
			
		||||
/*
 | 
			
		||||
 * DM_UDEV_DISABLE_SUBSYTEM_RULES_FLAG is set in case we need to disable
 | 
			
		||||
 * DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG is set in case we need to disable
 | 
			
		||||
 * subsystem udev rules, but still we need the general DM udev rules to
 | 
			
		||||
 * be applied (to create the nodes and symlinks under /dev and /dev/disk).
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -2436,20 +2436,20 @@ static int _udev_notify_sem_inc(uint32_t cookie, int semid)
 | 
			
		||||
	int val;
 | 
			
		||||
 | 
			
		||||
	if (semop(semid, &sb, 1) < 0) {
 | 
			
		||||
		log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
		log_error("cookie inc: semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
		log_warn("cookie inc: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
 | 
			
		||||
		  cookie, semid, val);
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented.",
 | 
			
		||||
				      cookie, semid);
 | 
			
		||||
	} else
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) incremented to %d",
 | 
			
		||||
				     cookie, semid, val);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -2459,23 +2459,21 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
 | 
			
		||||
	struct sembuf sb = {0, -1, IPC_NOWAIT};
 | 
			
		||||
	int val;
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  semid, cookie, strerror(errno));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 	if ((val = semctl(semid, 0, GETVAL)) < 0)
 | 
			
		||||
		log_warn("cookie dec: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			 "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			 semid, cookie, strerror(errno));
 | 
			
		||||
 | 
			
		||||
	if (semop(semid, &sb, 1) < 0) {
 | 
			
		||||
		switch (errno) {
 | 
			
		||||
			case EAGAIN:
 | 
			
		||||
				log_error("semid %d: semop failed for cookie "
 | 
			
		||||
				log_error("cookie dec: semid %d: semop failed for cookie "
 | 
			
		||||
					  "0x%" PRIx32 ": "
 | 
			
		||||
					  "incorrect semaphore state",
 | 
			
		||||
					  semid, cookie);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				log_error("semid %d: semop failed for cookie "
 | 
			
		||||
				log_error("cookie dec: semid %d: semop failed for cookie "
 | 
			
		||||
					  "0x%" PRIx32 ": %s",
 | 
			
		||||
					  semid, cookie, strerror(errno));
 | 
			
		||||
				break;
 | 
			
		||||
@@ -2483,9 +2481,12 @@ static int _udev_notify_sem_dec(uint32_t cookie, int semid)
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
 | 
			
		||||
			     cookie, semid, val - 1);
 | 
			
		||||
 | 
			
		||||
	if (val < 0)
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented.",
 | 
			
		||||
				     cookie, semid);
 | 
			
		||||
	else
 | 
			
		||||
		log_debug_activation("Udev cookie 0x%" PRIx32 " (semid %d) decremented to %d",
 | 
			
		||||
				     cookie, semid, val - 1);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2562,7 +2563,7 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
 | 
			
		||||
	sem_arg.val = 1;
 | 
			
		||||
 | 
			
		||||
	if (semctl(gen_semid, 0, SETVAL, sem_arg) < 0) {
 | 
			
		||||
		log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
 | 
			
		||||
		log_error("cookie create: semid %d: semctl failed: %s", gen_semid, strerror(errno));
 | 
			
		||||
		/* We have to destroy just created semaphore
 | 
			
		||||
		 * so it won't stay in the system. */
 | 
			
		||||
		(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
 | 
			
		||||
@@ -2570,9 +2571,10 @@ static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 	if ((val = semctl(gen_semid, 0, GETVAL)) < 0) {
 | 
			
		||||
		log_error("semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
		log_error("cookie create: semid %d: sem_ctl GETVAL failed for "
 | 
			
		||||
			  "cookie 0x%" PRIx32 ": %s",
 | 
			
		||||
			  gen_semid, gen_cookie, strerror(errno));
 | 
			
		||||
		(void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -832,7 +832,7 @@ a suitable value automatically.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--rebuild\fP \fIPV\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -325,7 +325,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--segments\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -311,7 +311,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +182,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB-t\fP|\fB--test\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -41,12 +41,11 @@ block addresses that are mapped to the shared physical block are not
 | 
			
		||||
modified.
 | 
			
		||||
.P
 | 
			
		||||
To use VDO with \fBlvm\fP(8), you must install the standard VDO user-space tools
 | 
			
		||||
\fBvdoformat\fP(8) and the currently non-standard kernel VDO module
 | 
			
		||||
"\fIkvdo\fP".
 | 
			
		||||
\fBvdoformat\fP(8) and kernel module "\fIdm_vdo\fP" (For older kernels <6.9
 | 
			
		||||
the out of tree kernel VDO module "\fIkvdo\fP" is necessary).
 | 
			
		||||
.P
 | 
			
		||||
The "\fIkvdo\fP" module implements fine-grained storage virtualization,
 | 
			
		||||
thin provisioning, block sharing, and compression.
 | 
			
		||||
The "\fIuds\fP" module provides memory-efficient duplicate
 | 
			
		||||
The kernel module implements fine-grained storage virtualization,
 | 
			
		||||
thin provisioning, block sharing, compression and memory-efficient duplicate
 | 
			
		||||
identification. The user-space tools include \fBvdostats\fP(8)
 | 
			
		||||
for extracting statistics from VDO volumes.
 | 
			
		||||
.
 | 
			
		||||
@@ -161,7 +160,6 @@ allocation {
 | 
			
		||||
.RS
 | 
			
		||||
vdo_use_compression=1
 | 
			
		||||
vdo_use_deduplication=1
 | 
			
		||||
vdo_use_metadata_hints=1
 | 
			
		||||
vdo_minimum_io_size=4096
 | 
			
		||||
vdo_block_map_cache_size_mb=128
 | 
			
		||||
vdo_block_map_period=16380
 | 
			
		||||
@@ -175,7 +173,6 @@ vdo_cpu_threads=2
 | 
			
		||||
vdo_hash_zone_threads=1
 | 
			
		||||
vdo_logical_threads=1
 | 
			
		||||
vdo_physical_threads=1
 | 
			
		||||
vdo_write_policy="auto"
 | 
			
		||||
vdo_max_discard=1
 | 
			
		||||
.RE
 | 
			
		||||
}
 | 
			
		||||
@@ -192,7 +189,7 @@ or repeat --vdosettings for each option being set.
 | 
			
		||||
Options are listed in the Example section above, for the full description see
 | 
			
		||||
.BR lvm.conf (5).
 | 
			
		||||
Options can omit 'vdo_' and 'vdo_use_' prefixes and all its underscores.
 | 
			
		||||
So i.e.  vdo_use_metadata_hints=1  and  metadatahints=1 are equivalent.
 | 
			
		||||
So i.e. vdo_use_deduplication=1 and deduplication=1 are equivalent.
 | 
			
		||||
To change the option for an already existing VDOPoolLV use
 | 
			
		||||
.BR lvchange (8)
 | 
			
		||||
command. However not all option can be changed.
 | 
			
		||||
@@ -307,6 +304,7 @@ volume types: linear, stripe, raid and cache with cachepool.
 | 
			
		||||
You can convert existing VDO LV into a thin volume. After this conversion
 | 
			
		||||
you can create a thin snapshot or you can add more thin volumes
 | 
			
		||||
with thin-pool named after original LV name LV_tpool0.
 | 
			
		||||
See \fBlvmthin\fP(7) for more details.
 | 
			
		||||
.P
 | 
			
		||||
.I Example
 | 
			
		||||
.nf
 | 
			
		||||
@@ -441,6 +439,7 @@ a dense UDS index uses 17 GiB of storage and a sparse UDS index will use
 | 
			
		||||
.BR lvremove (8),
 | 
			
		||||
.BR lvs (8),
 | 
			
		||||
.P
 | 
			
		||||
.BR lvmthin (7),
 | 
			
		||||
.BR vdoformat (8),
 | 
			
		||||
.BR vdostats (8),
 | 
			
		||||
.P
 | 
			
		||||
 
 | 
			
		||||
@@ -321,7 +321,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -200,7 +200,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -315,7 +315,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -319,7 +319,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -217,7 +217,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -777,7 +777,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--refresh\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -305,7 +305,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB-S\fP|\fB--select\fP \fIString\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -308,7 +308,7 @@ Repeat once to also suppress any prompts with answer 'no'.
 | 
			
		||||
\fB--readonly\fP
 | 
			
		||||
.br
 | 
			
		||||
Prevent the command from making changes, including activation and
 | 
			
		||||
metadata updates.
 | 
			
		||||
metadata updates.  (See --permission r for read only LVs.)
 | 
			
		||||
.
 | 
			
		||||
.HP
 | 
			
		||||
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP|\fBjson_std\fP
 | 
			
		||||
 
 | 
			
		||||
@@ -63,11 +63,13 @@
 | 
			
		||||
%if %{fedora} >= 27 || %{rhel} >= 7
 | 
			
		||||
 %service lvmlockd 1
 | 
			
		||||
# For RH7 require 7.4 for sanlock
 | 
			
		||||
 %if %{rhel} != 7 || 0%{?rhel_minor_version} > 4
 | 
			
		||||
 %if %{rhel} > 7 || 0%{?rhel_minor_version} > 4
 | 
			
		||||
   %global enable_lvmlockd_sanlock 1
 | 
			
		||||
 %endif
 | 
			
		||||
 %global sanlock_version 3.7.0-1
 | 
			
		||||
 %global enable_lvmlockd_dlm 1
 | 
			
		||||
 %if %{rhel} <= 9
 | 
			
		||||
   %global enable_lvmlockd_dlm 1
 | 
			
		||||
 %endif
 | 
			
		||||
 # FIXME: Check these conditions against RHEL builds!
 | 
			
		||||
 %if %{rhel}
 | 
			
		||||
  %ifnarch i686 x86_64 s390x
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	int pecent = atoi(argv[1]);
 | 
			
		||||
	int percent = atoi(argv[1]);
 | 
			
		||||
	int ret, s;
 | 
			
		||||
 | 
			
		||||
	ret = ilm_connect(&s);
 | 
			
		||||
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
 | 
			
		||||
		exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = ilm_inject_fault(s, pecent);
 | 
			
		||||
	ret = ilm_inject_fault(s, percent);
 | 
			
		||||
	if (ret == 0) {
 | 
			
		||||
		printf("ilm_inject_fault (100): SUCCESS\n");
 | 
			
		||||
	} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ SKIP_WITH_LVMPOLLD=1
 | 
			
		||||
 | 
			
		||||
which mkfs.ext4 || skip
 | 
			
		||||
which resize2fs || skip
 | 
			
		||||
which mkswap || skip
 | 
			
		||||
 | 
			
		||||
aux prepare_vg 2 100
 | 
			
		||||
 | 
			
		||||
@@ -299,7 +300,7 @@ dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=8 oflag=direct
 | 
			
		||||
lvextend --fs resize --fsmode offline -L+10M $vg/$lv
 | 
			
		||||
check lv_field $vg/$lv lv_size "30.00m"
 | 
			
		||||
# fsmode offline leaves fs unmounted
 | 
			
		||||
df -a | tee dfa
 | 
			
		||||
df | tee dfa
 | 
			
		||||
not grep "$mount_dir" dfa
 | 
			
		||||
mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
 | 
			
		||||
df --output=size "$mount_dir" |tee df2
 | 
			
		||||
@@ -649,5 +650,32 @@ df --output=size "$mount_dir" |tee df7
 | 
			
		||||
not diff df6 df7
 | 
			
		||||
umount "$mount_dir"
 | 
			
		||||
 | 
			
		||||
lvremove -f $vg
 | 
			
		||||
 | 
			
		||||
######################################
 | 
			
		||||
#
 | 
			
		||||
# lvreduce, lvextend with swap device
 | 
			
		||||
#
 | 
			
		||||
######################################
 | 
			
		||||
 | 
			
		||||
lvcreate -n $lv -L 16M $vg
 | 
			
		||||
mkswap /dev/$vg/$lv
 | 
			
		||||
 | 
			
		||||
# lvreduce not allowed if LV size < swap size
 | 
			
		||||
not lvreduce --fs checksize -L8m $vg/$lv
 | 
			
		||||
check lv_field $vg/$lv lv_size "16.00m"
 | 
			
		||||
 | 
			
		||||
# lvreduce not allowed if LV size < swap size,
 | 
			
		||||
# even with --fs resize, this is not supported
 | 
			
		||||
not lvreduce --fs resize $vg/$lv
 | 
			
		||||
check lv_field $vg/$lv lv_size "16.00m"
 | 
			
		||||
 | 
			
		||||
# lvextend allowed if LV size > swap size
 | 
			
		||||
lvextend -L32m $vg/$lv
 | 
			
		||||
check lv_field $vg/$lv lv_size "32.00m"
 | 
			
		||||
 | 
			
		||||
# lvreduce allowed if LV size == swap size
 | 
			
		||||
lvreduce -L16m $vg/$lv
 | 
			
		||||
check lv_field $vg/$lv lv_size "16.00m"
 | 
			
		||||
 | 
			
		||||
vgremove -ff $vg
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										42
									
								
								test/shell/pvcreate-partition.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								test/shell/pvcreate-partition.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (C) 2024 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
 | 
			
		||||
SKIP_WITH_LVMLOCKD=1
 | 
			
		||||
 | 
			
		||||
. lib/inittest
 | 
			
		||||
 | 
			
		||||
which sfdisk || skip
 | 
			
		||||
 | 
			
		||||
aux prepare_devs 1 4
 | 
			
		||||
 | 
			
		||||
pvcreate_on_dev_with_part_table() {
 | 
			
		||||
	local dev=$1
 | 
			
		||||
	local type=$2
 | 
			
		||||
 | 
			
		||||
	# pvcreate passes on empty partition table
 | 
			
		||||
	echo "label:$type" | sfdisk "$dev"
 | 
			
		||||
	pvcreate -y "$dev"
 | 
			
		||||
	pvremove "$dev"
 | 
			
		||||
 | 
			
		||||
	# pvcreate fails if there's at least 1 partition
 | 
			
		||||
	echo "label:$type" | sfdisk "$dev"
 | 
			
		||||
	echo "1MiB 1" | sfdisk "$dev"
 | 
			
		||||
	not pvcreate "$dev" 2>err
 | 
			
		||||
	grep "device is partitioned" err
 | 
			
		||||
 | 
			
		||||
	aux wipefs_a "$dev"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pvcreate_on_dev_with_part_table "$dev1" "dos"
 | 
			
		||||
pvcreate_on_dev_with_part_table "$dev1" "gpt"
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
# along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
			
		||||
 | 
			
		||||
# Check very large device size (upto 15Exa bytes)
 | 
			
		||||
# Check very large device size (up to 15Exa bytes)
 | 
			
		||||
# this needs 64bit arch
 | 
			
		||||
 | 
			
		||||
SKIP_WITH_LVMLOCKD=1
 | 
			
		||||
 
 | 
			
		||||
@@ -673,7 +673,7 @@ arg(raidintegritymode_ARG, '\0', "raidintegritymode", string_VAL, 0, 0,
 | 
			
		||||
 | 
			
		||||
arg(readonly_ARG, '\0', "readonly", 0, 0, 0,
 | 
			
		||||
    "Prevent the command from making changes, including activation and\n"
 | 
			
		||||
    "metadata updates.\n")
 | 
			
		||||
    "metadata updates.  (See --permission r for read only LVs.)\n")
 | 
			
		||||
 | 
			
		||||
arg(refresh_ARG, '\0', "refresh", 0, 0, 0,
 | 
			
		||||
    "#lvmdevices\n"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user