mirror of
git://sourceware.org/git/lvm2.git
synced 2026-02-10 08:32:46 +03:00
Compare commits
15 Commits
dev-dct-se
...
dev-dct-se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37a628db52 | ||
|
|
687b1a780f | ||
|
|
57bf48c058 | ||
|
|
ab1405034d | ||
|
|
1f18ee1388 | ||
|
|
f5852f2c9e | ||
|
|
b6df5bf9d6 | ||
|
|
55fda3afa5 | ||
|
|
6013977043 | ||
|
|
b4a49811cd | ||
|
|
09ceb425b7 | ||
|
|
fb708004fe | ||
|
|
b9e6337f04 | ||
|
|
edd8b52967 | ||
|
|
58c534ba57 |
@@ -1,5 +1,6 @@
|
||||
Version 2.03.36 -
|
||||
==================
|
||||
Detect and use existing XFS quota mount options for lvresize --fs resize.
|
||||
|
||||
Version 2.03.35 - 09th September 2025
|
||||
=====================================
|
||||
|
||||
@@ -39,7 +39,7 @@ local {
|
||||
# system_id = ""
|
||||
|
||||
# Configuration option local/pr_key.
|
||||
# The local persistent reservation key in hexidecimal.
|
||||
# The local persistent reservation key in hexadecimal.
|
||||
# The value must be unique among all hosts using the same VG.
|
||||
# The max length is 16 hex characters (8 bytes), plus an optional
|
||||
# 0x prefix. If pr_key is not set, host_id will be used to create a key.
|
||||
|
||||
@@ -182,10 +182,10 @@ static int listen_fd;
|
||||
static int restart_pi;
|
||||
static int restart_fds[2];
|
||||
|
||||
static int helper_send_fd; /* main loop sends requests to helper */
|
||||
static int helper_recv_fd; /* main loop receives results from helper */
|
||||
static int helper_pid;
|
||||
static int helper_pi;
|
||||
static int helper_send_fd = -1; /* main loop sends requests to helper */
|
||||
static int helper_recv_fd = -1; /* main loop receives results from helper */
|
||||
static int helper_pid = -1;
|
||||
static int helper_pi = -1;
|
||||
static uint32_t helper_msg_id = 1;
|
||||
|
||||
/*
|
||||
@@ -3013,11 +3013,6 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
|
||||
/* return success, allow the change */
|
||||
/* list_del act and add_client_result done after rem_lockspace */
|
||||
/*
|
||||
list_del(&act->list);
|
||||
act->result = 0;
|
||||
add_client_result(act);
|
||||
*/
|
||||
|
||||
/* the lockspace needs to be stopped for setlockargs_final */
|
||||
ls->thread_work = 0;
|
||||
@@ -4265,9 +4260,14 @@ static void work_fence(struct action *act, int *retry)
|
||||
if (!found_done && !found_busy) {
|
||||
rv = send_helper_request(act, ls_name, new_msg_id);
|
||||
if (rv < 0) {
|
||||
/* TODO: change act to FENCE_RESULT with error and move it to ls->actions */
|
||||
/* change act to FENCE_RESULT error and move it to ls->actions */
|
||||
log_error("work_fence %s failed to send helper request %u", vg_name, new_msg_id);
|
||||
free_action(act);
|
||||
pthread_mutex_lock(&ls->mutex);
|
||||
list_del(&act->list);
|
||||
act->op = LD_OP_FENCE_RESULT;
|
||||
act->result = -ENOTCONN;
|
||||
list_add_tail(&act->list, &ls->actions);
|
||||
pthread_mutex_unlock(&ls->mutex);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
@@ -72,6 +72,7 @@ incorrectly!
|
||||
|
||||
Make one by running `pvcreate /dev/sdX`.
|
||||
See [pvcreate(8)](https://man7.org/linux/man-pages/man8/pvcreate.8.html). This step is optional.
|
||||
|
||||
* Volume Group (VG) consisting of one or more PVs is used as a pool from which LVs are allocated.
|
||||
List VGs using [vgs(8)](https://man7.org/linux/man-pages/man8/vgs.8.html) or
|
||||
[vgdisplay(8)](https://man7.org/linux/man-pages/man8/vgdisplay.8.html).
|
||||
@@ -80,27 +81,34 @@ incorrectly!
|
||||
To use LVM at least one Volume Group must be present on the system.
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html), and
|
||||
[vgextend(8)](https://man7.org/linux/man-pages/man8/vgextend.8.html).
|
||||
|
||||
* Logical Volume (LV) is the block device usually visible to user to be used for file system.
|
||||
List PVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
|
||||
List LVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
|
||||
[lvdisplay(8)](https://man7.org/linux/man-pages/man8/lvdisplay.8.html).
|
||||
|
||||
Make one by running `lvcreate [-n LVNAME] -L SIZE VGNAME`, and you are done!
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html).
|
||||
See [lvcreate(8)](https://man7.org/linux/man-pages/man8/lvcreate.8.html).
|
||||
|
||||
To change size of LV it is recommended to use [lvresize(8)](https://man7.org/linux/man-pages/man8/lvresize.8.html) with `--resizefs` option.
|
||||
|
||||
To change properties of LV (e.g. to acivate/deactivate a volume, or change it to read only) use [lvchange(8)](https://man7.org/linux/man-pages/man8/lvchange.8.html).
|
||||
|
||||
To change the type of LV (e.g. change a linear volume to a RAID) use [lvconvert(8)](https://man7.org/linux/man-pages/man8/lvconvert.8.html).
|
||||
|
||||
## Avoiding Problems
|
||||
|
||||
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
|
||||
Good start is to **avoid using `{--force|-f}` and `{--yes|-y}` options** which are
|
||||
often seen on internet discussions.
|
||||
there is a possibility of data loss, LVM tools usually ask, so read the prompts
|
||||
carefully! Using `--yes` removes these safety.
|
||||
Also in some cases where it is too dangerous to proceed, e.g. device is used,
|
||||
LVM refuses to do so, which can be overridden by `--force`.
|
||||
|
||||
Second, when resizing and especially when shrinking LVs it is always a good
|
||||
idea to use `--resizefs` option which ensures the devices are resized in
|
||||
Second, when **resizing** and especially when shrinking LVs it is always a good
|
||||
idea to **use `--resizefs` option** which ensures the devices are resized in
|
||||
correct order.
|
||||
|
||||
Third, if you still make a mess, never ever run fsck on damaged LV/FS, this is
|
||||
Third, if you still make a mess, **never ever run fsck on damaged LV/FS**, this is
|
||||
usually the final blow to your data. It is always better to ask first!
|
||||
|
||||
|
||||
|
||||
@@ -2280,7 +2280,7 @@ cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_D
|
||||
"#\n")
|
||||
|
||||
cfg(local_pr_key_CFG, "pr_key", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, 0, vsn(2, 3, 32), NULL, 0, NULL,
|
||||
"The local persistent reservation key in hexidecimal.\n"
|
||||
"The local persistent reservation key in hexadecimal.\n"
|
||||
"The value must be unique among all hosts using the same VG.\n"
|
||||
"The max length is 16 hex characters (8 bytes), plus an optional\n"
|
||||
"0x prefix. If pr_key is not set, host_id will be used to create a key.\n")
|
||||
|
||||
@@ -1056,7 +1056,7 @@ static int get_our_key_sanlock_start(struct cmd_context *cmd, struct volume_grou
|
||||
/*
|
||||
* Called after sanlock lockstart to check if a registered PR key contains the
|
||||
* latest generation number (from sanlock) for the host, and if not to update
|
||||
* the PR key. The sanlock lockstart atually returns the previous generation
|
||||
* the PR key. The sanlock lockstart actually returns the previous generation
|
||||
* number that was used for this host_id in the lockspace, and we expect that
|
||||
* the next generation number just will be +1.
|
||||
*
|
||||
@@ -1572,23 +1572,78 @@ static int _run_stop(struct cmd_context *cmd, struct volume_group *vg, struct dm
|
||||
}
|
||||
|
||||
/*
|
||||
* Separate persist_stop_prepare() and persist_stop_run() is needed
|
||||
* for vgremove, where prepare is needed before the normal vgremove,
|
||||
* and run should happen after the normal vgremove.
|
||||
* - prepare cannot happen after normal vgremove, because the list
|
||||
* For vgremove, separate persist_stop into before and after parts:
|
||||
* - before cannot happen after normal vgremove, because the list
|
||||
* of PVs is no longer available.
|
||||
* - run cannot happen before normal vgremove, because removing the
|
||||
* - after cannot happen before normal vgremove, because removing the
|
||||
* reservation will prevent writing metadata for normal vgremove if
|
||||
* another host has a PR key registered (which may not happen in the
|
||||
* normal usage pattern, but is still possible.)
|
||||
*/
|
||||
|
||||
int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key)
|
||||
int persist_vgremove_before(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key)
|
||||
{
|
||||
char *local_key = (char *)find_config_tree_str(cmd, local_pr_key_CFG, NULL);
|
||||
int local_host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
|
||||
char our_key_buf[PR_KEY_BUF_SIZE] = { 0 };
|
||||
uint64_t our_key_val = 0;
|
||||
|
||||
if (!local_key && !local_host_id)
|
||||
return 1;
|
||||
|
||||
if (!get_our_key(cmd, vg, local_key, local_host_id, our_key_buf, &our_key_val))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* When removing a shared VG, verify that other hosts
|
||||
* have stopped PR to avoid leaving dangling reservations.
|
||||
*/
|
||||
if (vg_is_shared(vg)) {
|
||||
struct pv_list *pvl;
|
||||
struct device *dev;
|
||||
int found_key_count;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(dev = pvl->pv->dev))
|
||||
continue;
|
||||
|
||||
found_key_count = 0;
|
||||
|
||||
if (!dev_find_key(cmd, dev, 0, 0, NULL, 0, NULL, 1, &found_key_count, NULL)) {
|
||||
/* shouldn't happen */
|
||||
log_error("Failed to get PR keys from %s", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
if (found_key_count > 1) {
|
||||
log_error("Found %d PR keys on %s", found_key_count, dev_name(dev));
|
||||
log_error("Stop PR for VG %s on other hosts (vgchange --persist stop)", vg->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, devs))
|
||||
return_0;
|
||||
|
||||
if (!(*key = dm_pool_strdup(cmd->mem, our_key_buf)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void persist_vgremove_after(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key)
|
||||
{
|
||||
_run_stop(cmd, vg, devs, key, 0);
|
||||
persist_key_file_remove(cmd, vg);
|
||||
}
|
||||
|
||||
int persist_stop(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
DM_LIST_INIT(devs);
|
||||
char *local_key = (char *)find_config_tree_str(cmd, local_pr_key_CFG, NULL);
|
||||
int local_host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
|
||||
char our_key_buf[PR_KEY_BUF_SIZE] = { 0 };
|
||||
uint64_t our_key_val = 0;
|
||||
uint32_t cur_gen = 0;
|
||||
|
||||
if (!local_key && !local_host_id)
|
||||
@@ -1602,34 +1657,15 @@ int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struc
|
||||
if (!get_our_key(cmd, vg, local_key, local_host_id, our_key_buf, &our_key_val))
|
||||
return_0;
|
||||
|
||||
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, devs))
|
||||
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, &devs))
|
||||
return_0;
|
||||
|
||||
if (!(*key = dm_pool_strdup(cmd->mem, our_key_buf)))
|
||||
if (!_run_stop(cmd, vg, &devs, our_key_buf, 0))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int persist_stop_run(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key)
|
||||
{
|
||||
if (!_run_stop(cmd, vg, devs, key, 0))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int persist_stop(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
DM_LIST_INIT(devs);
|
||||
char *key = NULL;
|
||||
|
||||
if (!persist_stop_prepare(cmd, vg, &devs, &key))
|
||||
return_0;
|
||||
if (!persist_stop_run(cmd, vg, &devs, key))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _persist_extend_shared(struct cmd_context *cmd, struct volume_group *vg,
|
||||
uint64_t our_key_val, struct device *check_dev)
|
||||
{
|
||||
@@ -1965,7 +2001,8 @@ int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_k
|
||||
* access PR (typically WE), and starts PR with the normal sh access
|
||||
* PR (typically WEAR), allowing other hosts to also use the new VG.
|
||||
*/
|
||||
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags)
|
||||
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
|
||||
uint64_t *our_key_ret)
|
||||
{
|
||||
DM_LIST_INIT(devs);
|
||||
struct device_list *devl;
|
||||
@@ -2032,7 +2069,7 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
|
||||
log_debug("stop PR on %d devs with local key %s", pv_count, our_key_buf_stop);
|
||||
|
||||
if (!_run_stop(cmd, vg, &devs, our_key_buf_stop, 0))
|
||||
log_warn("WARNING: failed to stop PR");
|
||||
log_warn("WARNING: failed to stop PR with key %s", our_key_buf_stop);
|
||||
|
||||
log_debug("start PR on %d devs with local key %llx", pv_count, (unsigned long long)our_key_val);
|
||||
|
||||
@@ -2073,6 +2110,9 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
|
||||
if (!write_key_file(cmd, vg, our_key_val))
|
||||
stack;
|
||||
|
||||
if (our_key_ret)
|
||||
*our_key_ret = our_key_val;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,9 @@ int persist_start(struct cmd_context *cmd, struct volume_group *vg,
|
||||
char *local_key, int local_host_id, const char *remkey);
|
||||
|
||||
int persist_stop(struct cmd_context *cmd, struct volume_group *vg);
|
||||
int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key);
|
||||
int persist_stop_run(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key);
|
||||
|
||||
int persist_vgremove_before(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key);
|
||||
void persist_vgremove_after(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key);
|
||||
|
||||
int persist_remove(struct cmd_context *cmd, struct volume_group *vg,
|
||||
char *local_key, int local_host_id, const char *remkey);
|
||||
@@ -61,7 +62,8 @@ int persist_start_extend(struct cmd_context *cmd, struct volume_group *vg);
|
||||
|
||||
int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_key, int local_host_id,
|
||||
uint32_t set_flags, struct dm_list *devs);
|
||||
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags);
|
||||
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
|
||||
uint64_t *our_key_ret);
|
||||
|
||||
int persist_upgrade_ex(struct cmd_context *cmd, struct volume_group *vg, uint64_t *our_key_held);
|
||||
int persist_upgrade_stop(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key_val);
|
||||
|
||||
@@ -1446,7 +1446,7 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
|
||||
case LOCK_TYPE_CLVM:
|
||||
break;
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
persist_key_file_remove(cmd, vg->name);
|
||||
persist_key_file_remove(cmd, vg);
|
||||
break;
|
||||
case LOCK_TYPE_DLM:
|
||||
_free_vg_dlm(cmd, vg);
|
||||
|
||||
@@ -341,4 +341,3 @@ void split_line(char *buf, int *argc, char **argv, int max_args, char sep)
|
||||
}
|
||||
*argc = i;
|
||||
}
|
||||
|
||||
|
||||
@@ -175,9 +175,7 @@ is reserved for udev output.)
|
||||
.
|
||||
Autoactivation commands use a number of temp files in
|
||||
.I #DEFAULT_RUN_DIR#
|
||||
(with the expectation that
|
||||
.I #DEFAULT_PID_DIR#
|
||||
is cleared between boots).
|
||||
(with the expectation that it is cleared between boots).
|
||||
.
|
||||
.TP
|
||||
.B pvs_online
|
||||
|
||||
@@ -258,7 +258,7 @@ Display the settings.
|
||||
.P
|
||||
.SS VG PR commands
|
||||
.P
|
||||
vgchange --persist is used to perfom PR operations on the VG's devices.
|
||||
vgchange --persist is used to perform PR operations on the VG's devices.
|
||||
.P
|
||||
.B vgchange --persist start
|
||||
.I VG
|
||||
|
||||
@@ -609,7 +609,7 @@ Activate or deactivate LVs.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstart\fP
|
||||
]
|
||||
.br
|
||||
[
|
||||
@@ -698,7 +698,7 @@ Change the system ID of a VG.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fIString\fP
|
||||
]
|
||||
.br
|
||||
[
|
||||
@@ -723,7 +723,7 @@ Set or clear flags to control persistent reservation behavior.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstart\fP
|
||||
]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
@@ -772,7 +772,7 @@ Start the lockspace of a shared VG in lvmlockd.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstart\fP
|
||||
]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
@@ -794,7 +794,7 @@ Stop the lockspace of a shared VG in lvmlockd.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstop\fP
|
||||
]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
|
||||
@@ -162,7 +162,7 @@ Export specified VGs.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstop\fP
|
||||
]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
|
||||
@@ -152,7 +152,7 @@ Import specified VGs.
|
||||
]
|
||||
.br
|
||||
[
|
||||
.O_persist
|
||||
\fB--persist\fP \fBstart\fP
|
||||
]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
|
||||
@@ -866,6 +866,7 @@ do_remove() {
|
||||
for dev in "${DEVICES[@]}"; do
|
||||
if ! key_is_on_device "$dev" "$OURKEY" ; then
|
||||
logmsg "cannot remove $REMKEY from $dev without ourkey $OURKEY being registered"
|
||||
err=1
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ errorexit() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
logerror() {
|
||||
echo "$1" >&2
|
||||
logger "${SCRIPTNAME}: $1"
|
||||
}
|
||||
|
||||
logmsg() {
|
||||
echo "$1"
|
||||
logger "${SCRIPTNAME}: $1"
|
||||
@@ -68,6 +73,72 @@ TMP_MOUNT_DONE=0
|
||||
# Set to 1 if the fs resize command fails
|
||||
RESIZEFS_FAILED=0
|
||||
|
||||
# Function to detect XFS mount options
|
||||
detect_xfs_mount_options() {
|
||||
local device=$1
|
||||
local qflags_output qflags_hex
|
||||
MOUNT_OPTIONS=""
|
||||
|
||||
# Get quota flags using xfs_db.
|
||||
if ! qflags_output=$(xfs_db -r "$device" -c 'sb 0' -c 'p qflags'); then
|
||||
logerror "xfs_db failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Extract the hex value from output that is in format "qflags = 0x<hex_number>".
|
||||
qflags_hex="${qflags_output#qflags = }"
|
||||
|
||||
# No flags set, no extra mount options needed.
|
||||
if [[ "$qflags_hex" == "0" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ ! "$qflags_hex" =~ ^0x[0-9a-fA-F]+$ ]]; then
|
||||
logerror "xfs_db unexpected output"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check XFS quota flags and set MOUNT_OPTIONS appropriately
|
||||
# The quota flags as defined in Linux kernel source: fs/xfs/libxfs/xfs_log_format.h:
|
||||
# XFS_UQUOTA_ACCT = 0x0001
|
||||
# XFS_UQUOTA_ENFD = 0x0002
|
||||
# XFS_GQUOTA_ACCT = 0x0040
|
||||
# XFS_GQUOTA_ENFD = 0x0080
|
||||
# XFS_PQUOTA_ACCT = 0x0008
|
||||
# XFS_PQUOTA_ENFD = 0x0200
|
||||
|
||||
if [ $(($qflags_hex & 0x0001)) -ne 0 ]; then
|
||||
if [ $(($qflags_hex & 0x0002)) -ne 0 ]; then
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}uquota,"
|
||||
else
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}uqnoenforce,"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $(($qflags_hex & 0x0040)) -ne 0 ]; then
|
||||
if [ $(($qflags_hex & 0x0080)) -ne 0 ]; then
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}gquota,"
|
||||
else
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}gqnoenforce,"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $(($qflags_hex & 0x0008)) -ne 0 ]; then
|
||||
if [ $(($qflags_hex & 0x0200)) -ne 0 ]; then
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}pquota,"
|
||||
else
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS}pqnoenforce,"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Trim trailing comma
|
||||
MOUNT_OPTIONS="${MOUNT_OPTIONS%,}"
|
||||
|
||||
if [[ -n "$MOUNT_OPTIONS" ]]; then
|
||||
logmsg "mount options for xfs: ${MOUNT_OPTIONS}"
|
||||
fi
|
||||
}
|
||||
|
||||
fsextend() {
|
||||
if [ "$DO_UNMOUNT" -eq 1 ]; then
|
||||
logmsg "unmount ${MOUNTDIR}"
|
||||
@@ -98,7 +169,7 @@ fsextend() {
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
|
||||
logmsg "cryptsetup resize ${DEVPATH}"
|
||||
if cryptsetup resize "$DEVPATH"; then
|
||||
@@ -110,8 +181,12 @@ fsextend() {
|
||||
fi
|
||||
|
||||
if [ "$DO_MOUNT" -eq 1 ]; then
|
||||
if [[ "$FSTYPE" == "xfs" ]]; then
|
||||
detect_xfs_mount_options "$DEVPATH" || logmsg "not using XFS mount options"
|
||||
fi
|
||||
|
||||
logmsg "mount ${DEVPATH} ${TMPDIR}"
|
||||
if mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"; then
|
||||
if mount -t "$FSTYPE" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$TMPDIR"; then
|
||||
logmsg "mount done"
|
||||
TMP_MOUNT_DONE=1
|
||||
else
|
||||
@@ -170,8 +245,12 @@ fsextend() {
|
||||
# If the fs was temporarily unmounted, now remount it.
|
||||
# Not considered a command failure if this fails.
|
||||
if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
|
||||
if [[ "$FSTYPE" == "xfs" ]]; then
|
||||
detect_xfs_mount_options "$DEVPATH" || logmsg "not using XFS mount options"
|
||||
fi
|
||||
|
||||
logmsg "remount ${DEVPATH} ${MOUNTDIR}"
|
||||
if mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"; then
|
||||
if mount -t "$FSTYPE" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$MOUNTDIR"; then
|
||||
logmsg "remount done"
|
||||
else
|
||||
logmsg "remount failed"
|
||||
@@ -384,6 +463,9 @@ DO_FSCK=0
|
||||
# mounted and the script unmounted it.
|
||||
REMOUNT=0
|
||||
|
||||
# Initialize MOUNT_OPTIONS to ensure clean state
|
||||
MOUNT_OPTIONS=""
|
||||
|
||||
if [ "$UID" != 0 ] && [ "$EUID" != 0 ]; then
|
||||
errorexit "${SCRIPTNAME} must be run as root."
|
||||
fi
|
||||
|
||||
@@ -89,12 +89,24 @@ check lv_field $vg/$lv lv_size "380.00m"
|
||||
df --output=size "$mount_dir" |tee df2
|
||||
not diff df1 df2
|
||||
|
||||
# lvextend, xfs, active, not mounted, quotas defined, --fs resize
|
||||
umount "$mount_dir"
|
||||
mount -o uquota,gquota,pquota "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
|
||||
umount "$mount_dir"
|
||||
lvextend -y --fs resize -L+10M $vg/$lv | tee out
|
||||
grep "mount options for xfs: uquota,gquota,pquota" out # must preserve the mount options!
|
||||
|
||||
# lvextend, xfs, active, not mounted, quotas not defined, --fs resize
|
||||
mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
|
||||
umount "$mount_dir"
|
||||
lvextend -y --fs resize -L+10M $vg/$lv | tee out
|
||||
not grep "mount options for xfs" out # mount options not needed
|
||||
|
||||
lvchange -an $vg/$lv
|
||||
|
||||
# lvextend, xfs, inactive, --fs ignore
|
||||
lvextend --fs ignore -L+20M $vg/$lv
|
||||
check lv_field $vg/$lv lv_size "400.00m"
|
||||
check lv_field $vg/$lv lv_size "420.00m"
|
||||
|
||||
lvremove -f $vg/$lv
|
||||
|
||||
|
||||
@@ -1815,7 +1815,7 @@ DESC: Start or stop processing LV conversions.
|
||||
vgchange --activate Active
|
||||
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit,
|
||||
--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool,
|
||||
--autoactivation String, --persist start, OO_VGCHANGE
|
||||
--autoactivation String, --persist String, OO_VGCHANGE
|
||||
OP: VG|Tag|Select ...
|
||||
IO: --ignoreskippedcluster
|
||||
ID: vgchange_activate
|
||||
|
||||
@@ -691,7 +691,22 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
|
||||
if (_is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
_print_bracket_ds_opt_name(opt_enum);
|
||||
switch (opt_enum) {
|
||||
case persist_ARG:
|
||||
/* --persist may require specific argument (printed in bold) */
|
||||
printf("[\n");
|
||||
|
||||
_print_man_option(cmd->name, opt_enum);
|
||||
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
_print_def_man(cname, opt_enum, &cmd->optional_opt_args[oo].def, 1, NULL);
|
||||
}
|
||||
printf("\n]\n");
|
||||
break;
|
||||
default:
|
||||
_print_bracket_ds_opt_name(opt_enum);
|
||||
}
|
||||
printf(".br\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
const struct lv_list *lvl;
|
||||
struct pv_list *pvl;
|
||||
int do_activate = is_change_activating(activate);
|
||||
const char *pr_op = NULL;
|
||||
|
||||
/*
|
||||
* We can get here in the odd case where an LV is already active in
|
||||
@@ -233,8 +234,23 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
}
|
||||
}
|
||||
|
||||
if (do_activate && !persist_start_include(cmd, vg, (activate == CHANGE_AAY), 0, NULL))
|
||||
return 0;
|
||||
if (arg_is_set(cmd, persist_ARG))
|
||||
pr_op = arg_str_value(cmd, persist_ARG, NULL);
|
||||
|
||||
/*
|
||||
* vgchange -ay --persist start
|
||||
* This command bypasses the persist_is_started check in vg_read (disable_pr_required.)
|
||||
* It is not permitted for shared VGs, where PR start happens before lockstart.
|
||||
* For non-shared VGs, require a successful persist_start() here before activating.
|
||||
*/
|
||||
if (do_activate && pr_op && !strcmp(pr_op, "start") && cmd->disable_pr_required) {
|
||||
if (vg_is_shared(vg)) {
|
||||
log_error("Activation with persist start not permitted for shared VG %s.", vg->name);
|
||||
return 0;;
|
||||
}
|
||||
if (!persist_start_include(cmd, vg, (activate == CHANGE_AAY), 0, NULL))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe, since we never write out new metadata here. Required for
|
||||
@@ -284,6 +300,18 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (!do_activate && pr_op && !strcmp(pr_op, "stop")) {
|
||||
/* For a shared VG, PR stop happens after lockstop. */
|
||||
if (vg_is_shared(vg))
|
||||
log_warn("WARNING: skipping persist stop for shared VG.");
|
||||
else if (lvs_in_vg_activated(vg))
|
||||
log_warn("WARNING: skipping persist stop for incomplete deactivation.");
|
||||
else if (!persist_stop(cmd, vg)) {
|
||||
log_error("Failed to stop persistent reservation.");
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly trigger auto-generation of system.devices:
|
||||
* - if root_dm_uuid contains vg->id, and
|
||||
@@ -1100,10 +1128,37 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (noupdate)
|
||||
cmd->ignore_device_name_mismatch = 1;
|
||||
|
||||
/* Allow LVs to be deactivated without PR started. */
|
||||
if (arg_is_set(cmd, activate_ARG) &&
|
||||
!is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY)))
|
||||
cmd->disable_pr_required = 1;
|
||||
/*
|
||||
* PR usage with activation/deactivation.
|
||||
*/
|
||||
if (arg_is_set(cmd, activate_ARG)) {
|
||||
int is_activating = is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY));
|
||||
|
||||
/* Always allow deactivation without PR being started. */
|
||||
if (!is_activating)
|
||||
cmd->disable_pr_required = 1;
|
||||
|
||||
/* Either "-ay --persist start", or "-an --persist stop". */
|
||||
if (arg_is_set(cmd, persist_ARG)) {
|
||||
const char *pr_op = arg_str_value(cmd, persist_ARG, NULL);
|
||||
if (strcmp(pr_op, "start") && strcmp(pr_op, "stop")) {
|
||||
log_error("Invalid --persist usage.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
if ((!strcmp(pr_op, "start") && !is_activating) ||
|
||||
(!strcmp(pr_op, "stop") && is_activating)) {
|
||||
log_error("Invalid --persist usage.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
/*
|
||||
* Setting disable_pr_required to bypass the
|
||||
* persist_is_started check in vg_read requires
|
||||
* persist_start in vgchange_activate.
|
||||
*/
|
||||
if (!strcmp(pr_op, "start") && is_activating)
|
||||
cmd->disable_pr_required = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the devices file includes PVs stacked on LVs, then
|
||||
|
||||
@@ -117,8 +117,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
!vg_set_max_pv(vg, vp_new.max_pv) ||
|
||||
!vg_set_alloc_policy(vg, vp_new.alloc) ||
|
||||
!vg_set_system_id(vg, vp_new.system_id) ||
|
||||
!vg_set_persist(vg, pp.setpersist_flags) ||
|
||||
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies))
|
||||
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies) ||
|
||||
!vg_set_persist(vg, pp.setpersist_flags))
|
||||
goto_bad;
|
||||
|
||||
if (arg_is_set(cmd, setautoactivation_ARG) && !arg_int_value(cmd, setautoactivation_ARG, 1))
|
||||
@@ -181,13 +181,15 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
* read without locks until the lockspace is done starting.)
|
||||
*/
|
||||
if (vg_is_shared(vg)) {
|
||||
uint64_t our_key = 0;
|
||||
|
||||
if (pp.setpersist_flags &&
|
||||
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags)) {
|
||||
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags, &our_key)) {
|
||||
log_error("Failed to start PR");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lockd_start_vg(cmd, vg, 0, NULL)) {
|
||||
if (!lockd_start_vg(cmd, vg, our_key, NULL)) {
|
||||
log_error("Failed to start locking");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
|
||||
!lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
if (pr_stop && !persist_vgremove_before(cmd, vg, &pr_devs, &pr_key))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
if (!lockd_free_vg_before(cmd, vg, 0, arg_count(cmd, yes_ARG)))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
@@ -82,9 +85,6 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
online_vgremove(vg);
|
||||
|
||||
if (pr_stop && !persist_stop_prepare(cmd, vg, &pr_devs, &pr_key))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
vg_remove_pvs(vg);
|
||||
|
||||
if (!vg_remove(vg))
|
||||
@@ -92,11 +92,8 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
lockd_free_vg_final(cmd, vg);
|
||||
|
||||
if (pr_stop) {
|
||||
if (!persist_stop_run(cmd, vg, &pr_devs, pr_key))
|
||||
log_warn("WARNING: persistent reservation not removed from devices.");
|
||||
persist_key_file_remove(cmd, vg->name);
|
||||
}
|
||||
if (pr_stop)
|
||||
persist_vgremove_after(cmd, vg, &pr_devs, pr_key);
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user