Blob Blame History Raw
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