summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-11-08 16:02:48 -0600
committerDavid Teigland <teigland@redhat.com>2021-11-09 11:26:26 -0600
commit73b4602f219767850a2834c6b15bdb5e6d636870 (patch)
tree381641be2d22bd66908b8735009977382b16acf1 /lib
parent024ce50f06feff2dae53dce83398911bef071a6e (diff)
downloadlvm2-73b4602f219767850a2834c6b15bdb5e6d636870.tar.gz
pvs_online: include devname in pvid files
Include the device name in the /run/lvm/pvs_online/pvid files. Commands using the pvid file can use the devname to more quickly find the correct device, vs finding the device using the major:minor number. If the devname in the pvid file is missing or incorrect, fall back to using the devno.
Diffstat (limited to 'lib')
-rw-r--r--lib/device/dev-cache.c50
-rw-r--r--lib/device/dev-cache.h1
-rw-r--r--lib/device/online.c138
-rw-r--r--lib/device/online.h3
-rw-r--r--lib/label/label.c18
5 files changed, 164 insertions, 46 deletions
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 525dae31e..b5f355484 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -2241,3 +2241,53 @@ int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno)
return setup_devname_in_dev_cache(cmd, devname);
}
+struct device *setup_dev_in_dev_cache(struct cmd_context *cmd, dev_t devno, const char *devname)
+{
+ struct device *dev;
+ struct stat buf;
+ int major = (int)MAJOR(devno);
+ int minor = (int)MINOR(devno);
+
+ if (devname) {
+ if (stat(devname, &buf) < 0) {
+ log_error("Cannot access device %s for %d:%d.", devname, major, minor);
+ if (!(devname = _get_devname_from_devno(cmd, devno))) {
+ log_error("No device name found from %d:%d.", major, minor);
+ return_NULL;
+ }
+ if (stat(devname, &buf) < 0) {
+ log_error("Cannot access device %s from %d:%d.", devname, major, minor);
+ return_NULL;
+ }
+ }
+ } else {
+ if (!(devname = _get_devname_from_devno(cmd, devno))) {
+ log_error("No device name found from %d:%d.", major, minor);
+ return_NULL;
+ }
+ if (stat(devname, &buf) < 0) {
+ log_error("Cannot access device %s from %d:%d.", devname, major, minor);
+ return_NULL;
+ }
+ }
+
+ if (!S_ISBLK(buf.st_mode)) {
+ log_error("Invaild device type %s.", devname);
+ return_NULL;
+ }
+
+ if (devno && (buf.st_rdev != devno)) {
+ log_warn("Found %s devno %d:%d expected %d:%d.", devname,
+ (int)MAJOR(buf.st_rdev), (int)MINOR(buf.st_rdev), major, minor);
+ }
+
+ if (!_insert_dev(devname, buf.st_rdev))
+ return_NULL;
+
+ if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname))) {
+ log_error("Device lookup failed for %d:%d %s", major, minor, devname);
+ return_NULL;
+ }
+
+ return dev;
+}
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 175c0a3e3..449bfeb75 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -82,5 +82,6 @@ int setup_device(struct cmd_context *cmd, const char *devname);
int setup_devices_for_online_autoactivation(struct cmd_context *cmd);
int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname);
int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno);
+struct device *setup_dev_in_dev_cache(struct cmd_context *cmd, dev_t devno, const char *devname);
#endif
diff --git a/lib/device/online.c b/lib/device/online.c
index 58696871e..c67f45001 100644
--- a/lib/device/online.c
+++ b/lib/device/online.c
@@ -21,35 +21,50 @@
#include <dirent.h>
-static char *_vgname_in_pvid_file_buf(char *buf)
+/*
+ * file contains:
+ * <major>:<minor>\n
+ * vg:<vgname>\n
+ * dev:<devname>\n\0
+ *
+ * It's possible that vg and dev may not exist.
+ */
+
+static int _copy_pvid_file_field(const char *field, char *buf, int bufsize, char *out, int outsize)
{
- char *p, *n;
+ char *p;
+ int i = 0;
+
+ if (!(p = strstr(buf, field)))
+ return 0;
- /*
- * file contains:
- * <major>:<minor>\n
- * vg:<vgname>\n\0
- */
+ p += strlen(field);
- if (!(p = strchr(buf, '\n')))
- return NULL;
+ while (1) {
+ if (*p == '\n')
+ break;
+ if (*p == '\0')
+ break;
- p++; /* skip \n */
+ if (p >= (buf + bufsize))
+ return 0;
+ if (i >= outsize-1)
+ return 0;
- if (*p && !strncmp(p, "vg:", 3)) {
- if ((n = strchr(p, '\n')))
- *n = '\0';
- return p + 3;
+ out[i] = *p;
+
+ i++;
+ p++;
}
- return NULL;
+
+ return i ? 1 : 0;
}
#define MAX_PVID_FILE_SIZE 512
-int online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
+int online_pvid_file_read(char *path, int *major, int *minor, char *vgname, char *devname)
{
char buf[MAX_PVID_FILE_SIZE] = { 0 };
- char *name;
int fd, rv;
fd = open(path, O_RDONLY);
@@ -72,12 +87,47 @@ int online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
return 0;
}
- /* vgname points to an offset in buf */
- if ((name = _vgname_in_pvid_file_buf(buf)))
- strncpy(vgname, name, NAME_LEN);
- else
- log_debug("No vgname in %s", path);
+ if (vgname) {
+ if (!strstr(buf, "vg:")) {
+ log_debug("No vgname in %s", path);
+ vgname[0] = '\0';
+ goto copy_dev;
+ }
+
+ if (!_copy_pvid_file_field("vg:", buf, MAX_PVID_FILE_SIZE, vgname, NAME_LEN)) {
+ log_warn("Ignoring invalid vg field in %s", path);
+ vgname[0] = '\0';
+ goto copy_dev;
+ }
+
+ if (!validate_name(vgname)) {
+ log_warn("Ignoring invalid vgname in %s (%s)", path, vgname);
+ vgname[0] = '\0';
+ goto copy_dev;
+ }
+ }
+
+ copy_dev:
+ if (devname) {
+ if (!strstr(buf, "dev:")) {
+ log_debug("No devname in %s", path);
+ devname[0] = '\0';
+ goto out;
+ }
+
+ if (!_copy_pvid_file_field("dev:", buf, MAX_PVID_FILE_SIZE, devname, NAME_LEN)) {
+ log_warn("Ignoring invalid devname field in %s", path);
+ devname[0] = '\0';
+ goto out;
+ }
+ if (strncmp(devname, "/dev/", 5)) {
+ log_warn("Ignoring invalid devname in %s (%s)", path, devname);
+ devname[0] = '\0';
+ goto out;
+ }
+ }
+ out:
return 1;
}
@@ -95,6 +145,7 @@ int get_pvs_online(struct dm_list *pvs_online, const char *vgname)
{
char path[PATH_MAX];
char file_vgname[NAME_LEN];
+ char file_devname[NAME_LEN];
DIR *dir;
struct dirent *de;
struct pv_online *po;
@@ -116,8 +167,9 @@ int get_pvs_online(struct dm_list *pvs_online, const char *vgname)
file_major = 0;
file_minor = 0;
memset(file_vgname, 0, sizeof(file_vgname));
+ memset(file_devname, 0, sizeof(file_devname));
- if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname))
+ if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname, file_devname))
continue;
if (vgname && strcmp(file_vgname, vgname))
@@ -130,15 +182,18 @@ int get_pvs_online(struct dm_list *pvs_online, const char *vgname)
if (file_major || file_minor)
po->devno = MKDEV(file_major, file_minor);
if (file_vgname[0])
- strncpy(po->vgname, file_vgname, NAME_LEN-1);
+ strncpy(po->vgname, file_vgname, NAME_LEN);
+ if (file_devname[0])
+ strncpy(po->devname, file_devname, NAME_LEN);
+ log_debug("Found PV online %s for VG %s %s", path, vgname, file_devname);
dm_list_add(pvs_online, &po->list);
}
if (closedir(dir))
log_sys_debug("closedir", PVS_ONLINE_DIR);
- log_debug("PVs online found %d for %s", dm_list_size(pvs_online), vgname ?: "all");
+ log_debug("Found PVs online %d for %s", dm_list_size(pvs_online), vgname ?: "all");
return 1;
}
@@ -195,6 +250,9 @@ int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const c
char path[PATH_MAX];
char buf[MAX_PVID_FILE_SIZE] = { 0 };
char file_vgname[NAME_LEN];
+ char file_devname[NAME_LEN];
+ char devname[NAME_LEN];
+ int devnamelen;
int file_major = 0, file_minor = 0;
int major, minor;
int fd;
@@ -202,6 +260,7 @@ int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const c
int len;
int len1 = 0;
int len2 = 0;
+ int len3 = 0;
major = (int)MAJOR(dev->dev);
minor = (int)MINOR(dev->dev);
@@ -218,13 +277,22 @@ int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const c
if (vgname) {
if ((len2 = dm_snprintf(buf + len1, sizeof(buf) - len1, "vg:%s\n", vgname)) < 0) {
- log_print_pvscan(cmd, "Incomplete online file for %s %d:%d vg %s.", dev_name(dev), major, minor, vgname);
+ log_print("Incomplete online file for %s %d:%d vg %s.", dev_name(dev), major, minor, vgname);
/* can still continue without vgname */
len2 = 0;
}
}
- len = len1 + len2;
+ devnamelen = dm_snprintf(devname, sizeof(devname), "%s", dev_name(dev));
+ if ((devnamelen > 5) && (devnamelen < NAME_LEN-1)) {
+ if ((len3 = dm_snprintf(buf + len1 + len2, sizeof(buf) - len1 - len2, "dev:%s\n", devname)) < 0) {
+ log_print("Incomplete devname in online file for %s.", dev_name(dev));
+ /* can continue without devname */
+ len3 = 0;
+ }
+ }
+
+ len = len1 + len2 + len3;
log_debug("Create pv online: %s %d:%d %s", path, major, minor, dev_name(dev));
@@ -269,8 +337,9 @@ check_duplicate:
*/
memset(file_vgname, 0, sizeof(file_vgname));
+ memset(file_devname, 0, sizeof(file_devname));
- online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
+ online_pvid_file_read(path, &file_major, &file_minor, file_vgname, file_devname);
if ((file_major == major) && (file_minor == minor)) {
log_debug("Existing online file for %d:%d", major, minor);
@@ -280,8 +349,8 @@ check_duplicate:
/* Don't know how vgname might not match, but it's not good so fail. */
if ((file_major != major) || (file_minor != minor))
- log_error_pvscan(cmd, "PV %s is duplicate for PVID %s on %d:%d and %d:%d.",
- dev_name(dev), dev->pvid, major, minor, file_major, file_minor);
+ log_error_pvscan(cmd, "PV %s %d:%d is duplicate for PVID %s on %d:%d %s.",
+ dev_name(dev), major, minor, dev->pvid, file_major, file_minor, file_devname);
if (file_vgname[0] && vgname && strcmp(file_vgname, vgname))
log_error_pvscan(cmd, "PV %s has unexpected VG %s vs %s.",
@@ -319,6 +388,7 @@ int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname)
char line[64];
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char file_vgname[NAME_LEN];
+ char file_devname[NAME_LEN];
struct pv_online *po;
int file_major = 0, file_minor = 0;
FILE *fp;
@@ -340,8 +410,9 @@ int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname)
file_major = 0;
file_minor = 0;
memset(file_vgname, 0, sizeof(file_vgname));
+ memset(file_devname, 0, sizeof(file_devname));
- if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname))
+ if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname, file_devname))
goto_bad;
if (vgname && strcmp(file_vgname, vgname))
@@ -355,11 +426,14 @@ int get_pvs_lookup(struct dm_list *pvs_online, const char *vgname)
po->devno = MKDEV(file_major, file_minor);
if (file_vgname[0])
strncpy(po->vgname, file_vgname, NAME_LEN-1);
+ if (file_devname[0])
+ strncpy(po->devname, file_devname, NAME_LEN-1);
+ log_debug("Found PV online lookup %s for VG %s on %s", path, vgname, file_devname);
dm_list_add(pvs_online, &po->list);
}
- log_debug("PVs online lookup found %d for %s", dm_list_size(pvs_online), vgname);
+ log_debug("Found PVs online lookup %d for %s", dm_list_size(pvs_online), vgname);
fclose(fp);
return 1;
diff --git a/lib/device/online.h b/lib/device/online.h
index 25a176854..850b03db8 100644
--- a/lib/device/online.h
+++ b/lib/device/online.h
@@ -21,6 +21,7 @@ struct pv_online {
dev_t devno;
char pvid[ID_LEN + 1];
char vgname[NAME_LEN];
+ char devname[NAME_LEN];
};
/*
@@ -44,7 +45,7 @@ do \
log_error("pvscan[%d] " fmt, getpid(), ##args); \
while (0)
-int online_pvid_file_read(char *path, int *major, int *minor, char *vgname);
+int online_pvid_file_read(char *path, int *major, int *minor, char *vgname, char *devname);
int online_vg_file_create(struct cmd_context *cmd, const char *vgname);
void online_vg_file_remove(const char *vgname);
int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname);
diff --git a/lib/label/label.c b/lib/label/label.c
index 9875b5f02..324cfd034 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -1073,26 +1073,18 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
}
/*
- * For each po devno add a struct dev to dev-cache. This is a faster
+ * For each po add a struct dev to dev-cache. This is a faster
* alternative to the usual dev_cache_scan() which looks at all
* devices. If this optimization fails, then fall back to the usual
* dev_cache_scan().
*/
dm_list_iterate_items(po, &pvs_online) {
- if (!setup_devno_in_dev_cache(cmd, po->devno)) {
- log_debug("No device set up for quick mapping of %d:%d PVID %s",
- (int)MAJOR(po->devno), (int)MINOR(po->devno), po->pvid);
+ if (!(po->dev = setup_dev_in_dev_cache(cmd, po->devno, po->devname[0] ? po->devname : NULL))) {
+ log_debug("No device found for quick mapping of online PV %d:%d %s PVID %s",
+ (int)MAJOR(po->devno), (int)MINOR(po->devno), po->devname, po->pvid);
try_dev_scan = 1;
- break;
- }
-
- if (!(po->dev = dev_cache_get_by_devt(cmd, po->devno, NULL, NULL))) {
- log_debug("No device found for quick mapping of %d:%d PVID %s",
- (int)MAJOR(po->devno), (int)MINOR(po->devno), po->pvid);
- try_dev_scan = 1;
- break;
+ continue;
}
-
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
goto_bad;