1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-09 18:03:17 +03:00

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.
This commit is contained in:
David Teigland 2021-11-08 16:02:48 -06:00
parent 024ce50f06
commit 73b4602f21
6 changed files with 182 additions and 69 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
continue;
}
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;
}
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
goto_bad;

View File

@ -223,7 +223,7 @@ static void _online_pvid_file_remove_devno(int major, int minor)
file_minor = 0;
memset(file_vgname, 0, sizeof(file_vgname));
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
online_pvid_file_read(path, &file_major, &file_minor, file_vgname, NULL);
if ((file_major == major) && (file_minor == minor)) {
log_debug("Unlink pv online %s", path);
@ -509,6 +509,7 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
{
char path[PATH_MAX];
char file_vgname[NAME_LEN];
char file_devname[NAME_LEN];
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char uuidstr[64] __attribute__((aligned(8)));
struct pv_list *pvl;
@ -538,8 +539,9 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
file_major = 0;
file_minor = 0;
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_vgname[0] && strcmp(vgname, file_vgname)) {
log_error_pvscan(cmd, "Wrong VG found for %d:%d PVID %s: %s vs %s",
@ -549,13 +551,8 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
devno = MKDEV(file_major, file_minor);
if (!setup_devno_in_dev_cache(cmd, devno)) {
log_error_pvscan(cmd, "No device set up for %d:%d PVID %s", file_major, file_minor, pvid);
goto bad;
}
if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
log_error_pvscan(cmd, "No device found for %d:%d PVID %s", file_major, file_minor, pvid);
if (!(dev = setup_dev_in_dev_cache(cmd, devno, file_devname[0] ? file_devname : NULL))) {
log_error_pvscan(cmd, "No device set up for online PV %d:%d %s PVID %s", file_major, file_minor, file_devname, pvid);
goto bad;
}
@ -888,16 +885,12 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
/* in common usage, no dev will be found for a devno */
dm_list_iterate_items(arg, pvscan_args) {
if (arg->devname) {
if (!setup_devname_in_dev_cache(cmd, arg->devname))
log_error_pvscan(cmd, "No device set up for name arg %s", arg->devname);
arg->dev = dev_cache_get(cmd, arg->devname, NULL);
} else if (arg->devno) {
if (!setup_devno_in_dev_cache(cmd, arg->devno))
log_error_pvscan(cmd, "No device set up for devno arg %d", (int)arg->devno);
arg->dev = dev_cache_get_by_devt(cmd, arg->devno, NULL, NULL);
} else
if (!arg->devname && !arg->devno)
return_0;
if (!(arg->dev = setup_dev_in_dev_cache(cmd, arg->devno, arg->devname))) {
log_error_pvscan(cmd, "No device set up for arg %s %d:%d",
arg->devname ?: "", (int)MAJOR(arg->devno), (int)MINOR(arg->devno));
}
}
dm_list_iterate_items(arg, pvscan_args) {
@ -917,6 +910,7 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
{
char path[PATH_MAX];
char file_vgname[NAME_LEN];
char file_devname[NAME_LEN];
char pvid[ID_LEN+1] = { 0 };
struct pv_list *pvl;
struct device *dev;
@ -944,9 +938,10 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
major = 0;
minor = 0;
file_vgname[0] = '\0';
memset(file_vgname, 0, sizeof(file_vgname));
memset(file_devname, 0, sizeof(file_devname));
online_pvid_file_read(path, &major, &minor, file_vgname);
online_pvid_file_read(path, &major, &minor, file_vgname, file_devname);
if (file_vgname[0] && strcmp(vg->name, file_vgname)) {
log_warn("WARNING: VG %s PV %s wrong vgname in online file %s",
@ -957,9 +952,9 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
devno = MKDEV(major, minor);
if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
log_print_pvscan(cmd, "VG %s PV %s no device found for %d:%d",
vg->name, pvid, major, minor);
if (!(dev = setup_dev_in_dev_cache(cmd, devno, file_devname[0] ? file_devname : NULL))) {
log_print_pvscan(cmd, "VG %s PV %s no device found for online PV %d:%d %s",
vg->name, pvid, major, minor, file_devname);
pvl->pv->status |= MISSING_PV;
continue;
}