diff options
author | David Teigland <teigland@redhat.com> | 2021-11-08 16:02:48 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2021-11-09 11:26:26 -0600 |
commit | 73b4602f219767850a2834c6b15bdb5e6d636870 (patch) | |
tree | 381641be2d22bd66908b8735009977382b16acf1 /lib | |
parent | 024ce50f06feff2dae53dce83398911bef071a6e (diff) | |
download | lvm2-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.c | 50 | ||||
-rw-r--r-- | lib/device/dev-cache.h | 1 | ||||
-rw-r--r-- | lib/device/online.c | 138 | ||||
-rw-r--r-- | lib/device/online.h | 3 | ||||
-rw-r--r-- | lib/label/label.c | 18 |
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; |