1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-11-03 08:23:48 +03:00

Compare commits

...

34 Commits

Author SHA1 Message Date
Marian Csontos
207990a877 pre-release 2024-10-02 14:21:09 +02:00
Marian Csontos
ec965dde39 WHATS_NEW and release-notes update 2024-10-02 14:18:35 +02:00
Peter Rajnoha
b77f7acac8 WHATS_NEW: update 2024-10-02 13:49:45 +02:00
Marian Csontos
ca02546649 [WIP] Disable dlm for RHEL10 2024-10-02 13:48:11 +02:00
Tobias Stoeckmann
493d8908fb lvmdbusd: Fix Python script
The thread does not contain field "damon" but "daemon".

Actually found with codespell.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-10-02 11:34:22 +00:00
Peter Rajnoha
9d6a3ee547 filesystem: add note about swap devices 2024-10-02 13:31:54 +02:00
Peter Rajnoha
bd5ca83c43 tests: also test swap devices in lvresize-fs.sh 2024-10-02 13:31:54 +02:00
Peter Rajnoha
5096335277 lv_manip: handle swap devices in fs-related checks for lvreduce/lvextend
This provides better hints when trying to resize the fs on top of an LV.
Also needs a3f6d2f593 for proper operation.

❯  lvs -o name,size vg/swap
  lv_name lv_size
  swap     60.00m

Before:

❯  lvextend -L72m vg/swap
  Size of logical volume vg/swap changed from 60.00 MiB (15 extents) to 72.00 MiB (18 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L60m vg/swap
  File system swap found on vg/swap.
  File system device usage is not available from libblkid.

❯  lvreduce -L50m vg/swap
  Rounding size to boundary between physical extents: 52.00 MiB.
  File system swap found on vg/swap.
  File system device usage is not available from libblkid.

After:

❯  lvextend -L72m vg/swap
  Size of logical volume vg/swap changed from 60.00 MiB (15 extents) to 72.00 MiB (18 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L60m vg/swap
  File system swap found on vg/swap.
  File system size (60.00 MiB) is equal to the requested size (60.00 MiB).
  File system reduce is not needed, skipping.
  Size of logical volume vg/swap changed from 72.00 MiB (18 extents) to 60.00 MiB (15 extents).
  Logical volume vg/swap successfully resized.

❯  lvreduce -L50m vg/swap
  Rounding size to boundary between physical extents: 52.00 MiB.
  File system swap found on vg/swap.
  File system size (60.00 MiB) is larger than the requested size (52.00 MiB).
  File system reduce is required and not supported (swap).
2024-10-02 13:31:54 +02:00
Peter Rajnoha
e009becd73 dev-type: get swap device size from blkid using FSSIZE
blkid does not report FSLASTBLOCK for a swap device. However, blkid
does report FSSIZE for swap devices, so use this field (and including
the header size which is of FSBLOCKSIZE for the swap) instead to
set the "filesystem last block" which is used subsequently for
further calculations and conditions.
2024-10-02 13:31:54 +02:00
Peter Rajnoha
4524778b23 tests: add pvcreate-partition.sh 2024-10-02 12:02:35 +02:00
Peter Rajnoha
d5d2c98980 dev-type: add prefix to differentiate msdos and gpt constants 2024-10-02 12:02:34 +02:00
Peter Rajnoha
84cabd068b filter: partitioned: also detect non-empty GPT partition table
We already detect msdos partition table. If it is empty, that is, there
is just the partition header and no actual partitions defined, then the
filter-partitioned passes, otherwise not.

Do the same for GPT partition table.
2024-10-02 11:54:01 +02:00
Zdenek Kabelac
4708a354f6 make: generate 2024-09-30 15:00:03 +02:00
Zdenek Kabelac
28e7be9f39 cov: annotate 2024-09-30 15:00:03 +02:00
Zdenek Kabelac
0e1e220c3d cov: potentially overflowing expression
Use 64bit arithmentic.
2024-09-30 15:00:03 +02:00
David Teigland
7f29afdb06 lvmlockd: configurable sanlock lease sizes on 4K disks
New config setting sanlock_align_size can be used to configure
the sanlock lease size that lvmlockd will use on 4K disks.

By default, lvmlockd and sanlock use 8MiB align_size (lease size)
on 4K disks, which supports up to 2000 hosts (and max host_id.)

This can be reduced to 1, 2 or 4 (in MiB), to reduce lease i/o.
The reduced sizes correspond to smaller max hosts/host_id:

1 MiB = 250 hosts
2 MiB = 500 hosts
4 MiB = 1000 hosts
8 MiB = 2000 hosts (default)

(Disks with 512 byte sectors always use 1MiB leases and support
2000 hosts/host_id, and are not affected by this.)
2024-09-27 17:59:03 -05:00
Zdenek Kabelac
6816366ff1 WHATS_NEW: update 2024-09-27 13:44:59 +02:00
zkabelac
7447634c26 cleanup: replace use of alloced with allocated 2024-09-27 13:42:45 +02:00
zkabelac
0862e2b150 cleanup: typos in libdm 2024-09-27 13:42:45 +02:00
zkabelac
74f607952d cleanup: more typos in WHATS_NEW 2024-09-27 13:42:45 +02:00
Tobias Stoeckmann
cb781b3e1d cleanup: fix typos
Typos found with codespell.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-27 13:42:45 +02:00
Zdenek Kabelac
964012fdb9 memlock: use value of 0 to disable memory locking
In cases user is sure he is not using his 'rootfs' or 'swap' on LVs
managed with his command - it possible to completely bypass pinning
process to RAM which may eventually slightly speedup command execution,
(however at the risk the process can be eventually delayed by swapping).
Basicaly use this only at your risk...

TODO: add some dmeventd support for this.
2024-09-27 13:42:45 +02:00
Zdenek Kabelac
7e2bb2a35e vdo: depcreate unused settings 2024-09-26 16:25:12 +02:00
David Teigland
e9413fb211 lvmlockd: use lvmlock LV size
Previously, lvmlockd detected the end of the lvmlock LV
by doing i/o to it until an i/o error was returned.
This triggered sanlock warning messages, so use the LV
size to avoid accessing beyond the end of the device.

Previously, every lvcreate would refresh the lvmlock LV
in case another machine had extended it.  This involves
a lot of unnecessary work in most cases, so now compare
the LV size and device size to detect when a refresh is
needed.
2024-09-26 08:53:09 -05:00
David Teigland
9d7c19c2ce lvmlockd: fix previous thin locking fix
Restore the original lvremove locking for non-thin LVs
that were changed in the thin locking fix.
2024-09-23 17:15:42 -05:00
David Teigland
d7a028aaad vg: remove unused hostnames hash table
The hash table of lv creation hostnames was not used for anything,
so remove it.
2024-09-23 15:04:53 -05:00
David Teigland
1c3d7dfb07 lvmlockd: fix locking for thin
lvremove of a thin lv while the pool is inactive would
leave the pool locked but inactive.

lvcreate of a thin snapshot while the pool is inactive
would leave the pool locked but inactive.

lvcreate of a thin lv could activate the pool to check
a threshold before the pool lock was acquired in lvmlockd.
2024-09-23 14:57:07 -05:00
Peter Rajnoha
86a9db05cf tests: remove superfluous -a option for df used in lvresize-fs.sh 2024-09-19 15:12:44 +02:00
David Teigland
f42aef4706 metadata: use lv_hash in segment-specific metadata parsing
The lv_hash wasn't being passed to the seg-specific text import
functions, so they were doing many find_lv() calls which consumes
a lot of time when there are many LVs in the metadata.
2024-09-10 11:51:15 -05:00
David Teigland
1b68841605 args: readonly description update
Include reference to --permission r.
2024-09-06 08:44:06 -05:00
Peter Rajnoha
e8383073a9 WHATS_NEW_DM: update 2024-09-05 12:14:42 +02:00
Peter Rajnoha
1e48599193 libdm: do not fail if GETVAL semctl fails for udev sync inc and dec
While performing udev sync semaphore's inc/dec operation, we use the
result from GETVAL semctl just to print a debug message with current
value of that sempahore, nothing else.

If the GETVAL fails for whetever reason while the actual inc/dec
completes successfully, just log a warning message about the GETVAL
(and print the debug messages without the actual semaphore value)
and return success for the inc/dec operation as a whole.
2024-09-05 12:14:42 +02:00
Peter Rajnoha
f7f08ba881 libdm: clean up udev sync semaphore on fail path during its creation
Clean up udev sync semaphore on fail path during its creation, otherwise
the caller will have no handle returned to clean it up itself and the
semaphore will keep staying in the system. The only way to clean it up
would be to call `dmsetup udevcomplete_all` which would destroy all
udev sync semaphores, not just the failed one, which we don't want.
2024-09-05 12:14:42 +02:00
Peter Rajnoha
de196f4b60 libdm: add 'cookie create/inc/dec' log prefix if GETVAL fails for udev sync ops
The same message is printed while performing create/inc/dec operation and
the GETVAL semctl fails. Add a prefix so we know exactly in which of
these functions the issue actually happened.
2024-09-05 12:14:37 +02:00
65 changed files with 886 additions and 414 deletions

View File

@@ -1 +1 @@
2.03.27(2)-git (2024-08-23)
2.03.27(2) (2024-10-02)

View File

@@ -1 +1 @@
1.02.201-git (2024-08-23)
1.02.201 (2024-10-02)

View File

@@ -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.

View File

@@ -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
===================================

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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, &sector_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));

View File

@@ -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;
}

View File

@@ -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, &sector_size, &align_size);
rv = get_sizes_device(disk.path, &dev_size, &sector_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, &sector_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, &sector_size, &align_size);
rv = get_sizes_lockspace(disk_path, &sector_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;

View File

@@ -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).
*/

View File

@@ -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;
}

View 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"]]
-->

View File

@@ -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))

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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).
*/

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View 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"

View File

@@ -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

View File

@@ -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"