lvm2/0038-devices-fix-dev_name-assumptions.patch

271 lines
9.3 KiB
Diff

From 591b5f006fca7e06bfbf0d5512da3ae5b0f6bbdd Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
Date: Tue, 22 Feb 2022 15:03:11 -0600
Subject: [PATCH 38/54] devices: fix dev_name assumptions
dev_name(dev) returns "[unknown]" if there are no names
on dev->aliases. It's meant mainly for log messages.
Many places assume a valid path name is returned, and
use it directly. A caller that wants to use the path
from dev_name() must first check if the dev has any
paths with dm_list_empty(&dev->aliases).
---
lib/activate/dev_manager.c | 9 ++++++++-
lib/device/dev-type.c | 3 +++
lib/device/device_id.c | 13 +++++++++++--
lib/label/hints.c | 2 ++
lib/label/label.c | 16 +++++++++++++++-
lib/locking/lvmlockd.c | 4 ++++
lib/metadata/mirror.c | 17 +++++++++++++----
lib/metadata/pv_list.c | 5 +++++
lib/metadata/vg.c | 5 +++++
test/shell/losetup-partscan.sh | 2 ++
10 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index a73a556b2..284254d68 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -2875,6 +2875,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
/* FIXME Avoid repeating identical stat in dm_tree_node_add_target_area */
for (s = start_area; s < areas; s++) {
+
+ /* FIXME: dev_name() does not return NULL! It needs to check if dm_list_empty(&dev->aliases)
+ but this knot of logic is too complex to pull apart without careful deconstruction. */
+
if ((seg_type(seg, s) == AREA_PV &&
(!seg_pvseg(seg, s) || !seg_pv(seg, s) || !seg_dev(seg, s) ||
!(name = dev_name(seg_dev(seg, s))) || !*name ||
@@ -2893,7 +2897,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
return_0;
num_error_areas++;
} else if (seg_type(seg, s) == AREA_PV) {
- if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL,
+ struct device *dev = seg_dev(seg, s);
+ name = dm_list_empty(&dev->aliases) ? NULL : dev_name(dev);
+
+ if (!dm_tree_node_add_target_area(node, name, NULL,
(seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s)))))
return_0;
num_existing_areas++;
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 0e77a009d..c67a86fa3 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -966,6 +966,9 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam
/* TODO: Should we check for valid dev - _dev_is_valid(dev)? */
+ if (dm_list_empty(&dev->aliases))
+ goto_out;
+
if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) {
log_error("Failed to create a new blkid probe for device %s.", dev_name(dev));
goto out;
diff --git a/lib/device/device_id.c b/lib/device/device_id.c
index bcb2e6bcf..82db6e4a5 100644
--- a/lib/device/device_id.c
+++ b/lib/device/device_id.c
@@ -347,6 +347,8 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
}
else if (idtype == DEV_ID_TYPE_DEVNAME) {
+ if (dm_list_empty(&dev->aliases))
+ goto_bad;
if (!(idname = strdup(dev_name(dev))))
goto_bad;
return idname;
@@ -940,6 +942,10 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid_
if (!dev_get_partition_number(dev, &part))
return_0;
+ /* Ensure valid dev_name(dev) below. */
+ if (dm_list_empty(&dev->aliases))
+ return_0;
+
/*
* When enable_devices_file=0 and pending_devices_file=1 we let
* pvcreate/vgcreate add new du's to cmd->use_devices. These du's may
@@ -1820,6 +1826,9 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
if (dev->flags & DEV_SCAN_NOT_READ)
continue;
+ if (dm_list_empty(&dev->aliases))
+ continue;
+
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
log_warn("Devices file %s is excluded by filter: %s.",
dev_name(dev), dev_filtered_reason(dev));
@@ -2197,14 +2206,14 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
dm_list_iterate_items(dil, &search_pvids) {
char *dup_devname1, *dup_devname2, *dup_devname3;
- if (!dil->dev) {
+ if (!dil->dev || dm_list_empty(&dil->dev->aliases)) {
not_found++;
continue;
}
- found++;
dev = dil->dev;
devname = dev_name(dev);
+ found++;
if (!(du = get_du_for_pvid(cmd, dil->pvid))) {
/* shouldn't happen */
diff --git a/lib/label/hints.c b/lib/label/hints.c
index 95d5d77b8..2a7b3dca7 100644
--- a/lib/label/hints.c
+++ b/lib/label/hints.c
@@ -498,6 +498,8 @@ int validate_hints(struct cmd_context *cmd, struct dm_list *hints)
if (!(iter = dev_iter_create(NULL, 0)))
return 0;
while ((dev = dev_iter_get(cmd, iter))) {
+ if (dm_list_empty(&dev->aliases))
+ continue;
if (!(hint = _find_hint_name(hints, dev_name(dev))))
continue;
diff --git a/lib/label/label.c b/lib/label/label.c
index ffe925254..cf707f7a3 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1565,10 +1565,24 @@ int label_scan_open_rw(struct device *dev)
int label_scan_reopen_rw(struct device *dev)
{
+ const char *name;
int flags = 0;
int prev_fd = dev->bcache_fd;
int fd;
+ if (dm_list_empty(&dev->aliases)) {
+ log_error("Cannot reopen rw device %d:%d with no valid paths di %d fd %d.",
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
+ return 0;
+ }
+
+ name = dev_name(dev);
+ if (!name || name[0] != '/') {
+ log_error("Cannot reopen rw device %d:%d with no valid name di %d fd %d.",
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev->bcache_di, dev->bcache_fd);
+ return 0;
+ }
+
if (!(dev->flags & DEV_IN_BCACHE)) {
if ((dev->bcache_fd != -1) || (dev->bcache_di != -1)) {
/* shouldn't happen */
@@ -1598,7 +1612,7 @@ int label_scan_reopen_rw(struct device *dev)
flags |= O_NOATIME;
flags |= O_RDWR;
- fd = open(dev_name(dev), flags, 0777);
+ fd = open(name, flags, 0777);
if (fd < 0) {
log_error("Failed to open rw %s errno %d di %d fd %d.",
dev_name(dev), errno, dev->bcache_di, dev->bcache_fd);
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index b598df3d6..60c80f1b1 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -272,6 +272,8 @@ static void _lockd_retrive_vg_pv_list(struct volume_group *vg,
i = 0;
dm_list_iterate_items(pvl, &vg->pvs) {
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
+ continue;
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
if (!lock_pvs->path[i]) {
log_error("Fail to allocate PV path for VG %s", vg->name);
@@ -341,6 +343,8 @@ static void _lockd_retrive_lv_pv_list(struct volume_group *vg,
dm_list_iterate_items(pvl, &vg->pvs) {
if (lv_is_on_pv(lv, pvl->pv)) {
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases))
+ continue;
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
if (!lock_pvs->path[i]) {
log_error("Fail to allocate PV path for LV %s/%s",
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index e2bf191a1..46da57948 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -1231,14 +1231,23 @@ int remove_mirrors_from_segments(struct logical_volume *lv,
const char *get_pvmove_pvname_from_lv_mirr(const struct logical_volume *lv_mirr)
{
struct lv_segment *seg;
+ struct device *dev;
dm_list_iterate_items(seg, &lv_mirr->segments) {
if (!seg_is_mirrored(seg))
continue;
- if (seg_type(seg, 0) == AREA_PV)
- return dev_name(seg_dev(seg, 0));
- if (seg_type(seg, 0) == AREA_LV)
- return dev_name(seg_dev(first_seg(seg_lv(seg, 0)), 0));
+ if (seg_type(seg, 0) == AREA_PV) {
+ dev = seg_dev(seg, 0);
+ if (!dev || dm_list_empty(&dev->aliases))
+ return NULL;
+ return dev_name(dev);
+ }
+ if (seg_type(seg, 0) == AREA_LV) {
+ dev = seg_dev(first_seg(seg_lv(seg, 0)), 0);
+ if (!dev || dm_list_empty(&dev->aliases))
+ return NULL;
+ return dev_name(dev);
+ }
}
return NULL;
diff --git a/lib/metadata/pv_list.c b/lib/metadata/pv_list.c
index 813e8e525..fc3667db0 100644
--- a/lib/metadata/pv_list.c
+++ b/lib/metadata/pv_list.c
@@ -152,6 +152,11 @@ static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
struct pv_list *new_pvl = NULL, *pvl2;
struct dm_list *pe_ranges;
+ if (!pvl->pv->dev || dm_list_empty(&pvl->pv->dev->aliases)) {
+ log_error("Failed to create PV entry for missing device.");
+ return 0;
+ }
+
pvname = pv_dev_name(pvl->pv);
if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) {
log_warn("WARNING: Physical volume %s not allocatable.", pvname);
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index 85482552a..adc954bab 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -679,6 +679,11 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
return r;
}
+ if (!pv->dev || dm_list_empty(&pv->dev->aliases)) {
+ log_error("No device found for PV.");
+ return r;
+ }
+
log_debug("vgreduce_single VG %s PV %s", vg->name, pv_dev_name(pv));
if (pv_pe_alloc_count(pv)) {
diff --git a/test/shell/losetup-partscan.sh b/test/shell/losetup-partscan.sh
index 99f552ad1..670568945 100644
--- a/test/shell/losetup-partscan.sh
+++ b/test/shell/losetup-partscan.sh
@@ -33,6 +33,8 @@ aux udev_wait
ls -la "${LOOP}"*
test -e "${LOOP}p1"
+aux lvmconf 'devices/scan = "/dev"'
+
aux extend_filter "a|$LOOP|"
aux extend_devices "$LOOP"
--
2.34.3