1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

pvscan: add options listlvs listvg checkcomplete

pvscan --cache <dev>
    . read only dev
    . create online file for dev

pvscan --listlvs <dev>
    . read only dev
    . list LVs using dev

pvscan --listvg <dev>
    . read only dev
    . show VG using dev

pvscan --cache --listlvs [--checkcomplete] <dev>
    . read only dev
    . create online file for dev
    . list LVs using dev
    . [check online files and report if LVs are complete]

pvscan --cache --listvg [--checkcomplete] <dev>
    . read only dev
    . create online file for dev
    . list VG using dev
    . [check online files and report if VG is complete]

The list of complete LVs is meant to be passed to lvchange -aay,
or the complete VG used with vgchange -aay.

Example of listlvs
------------------

$ lvs -a vg -olvname,devices
  LV     Devices
  lv_a   /dev/loop0(0)
  lv_ab  /dev/loop0(1),/dev/loop1(1)
  lv_abc /dev/loop0(3),/dev/loop1(3),/dev/loop2(1)
  lv_b   /dev/loop1(0)
  lv_c   /dev/loop2(0)

$ pvscan --cache --listlvs --checkcomplete /dev/loop0
  pvscan[35680] PV /dev/loop0 online, VG vg incomplete (need 2).
  LV vg/lv_a complete
  LV vg/lv_ab incomplete
  LV vg/lv_abc incomplete

$ pvscan --cache --listlvs --checkcomplete /dev/loop1
  pvscan[35681] PV /dev/loop1 online, VG vg incomplete (need 1).
  LV vg/lv_b complete
  LV vg/lv_ab complete
  LV vg/lv_abc incomplete

$ pvscan --cache --listlvs --checkcomplete /dev/loop2
  pvscan[35682] PV /dev/loop2 online, VG vg is complete.
  LV vg/lv_c complete
  LV vg/lv_abc complete

Example of listvg
-----------------

$ pvscan --cache --listvg --checkcomplete /dev/loop0
  pvscan[35684] PV /dev/loop0 online, VG vg incomplete (need 2).
  VG vg incomplete

$ pvscan --cache --listvg --checkcomplete /dev/loop1
  pvscan[35685] PV /dev/loop1 online, VG vg incomplete (need 1).
  VG vg incomplete

$ pvscan --cache --listvg --checkcomplete /dev/loop2
  pvscan[35686] PV /dev/loop2 online, VG vg is complete.
  VG vg complete
This commit is contained in:
David Teigland 2020-12-09 10:59:40 -06:00
parent 9b3458d5a9
commit 419c9b4f88
5 changed files with 250 additions and 50 deletions

View File

@ -5312,3 +5312,36 @@ struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_
return vg;
}
int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, struct device *dev,
struct dm_list *lvs_list)
{
struct pv_list *pvl;
struct lv_list *lvl, *lvl2;
struct physical_volume *pv = NULL;
dm_list_iterate_items(pvl, &vg->pvs) {
if (pvl->pv->dev == dev) {
pv = pvl->pv;
break;
}
}
if (!pv)
return_0;
dm_list_iterate_items(lvl, &vg->lvs) {
if (!lv_is_visible(lvl->lv))
continue;
if (!lv_is_on_pv(lvl->lv, pv))
continue;
if (!(lvl2 = dm_pool_zalloc(cmd->mem, sizeof(*lvl2))))
return_0;
lvl2->lv = lvl->lv;
dm_list_add(lvs_list, &lvl2->list);
}
return 1;
}

View File

@ -526,4 +526,8 @@ char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tagsl);
void set_pv_devices(struct format_instance *fid, struct volume_group *vg, int *found_md_component);
int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, struct device *dev,
struct dm_list *lvs_list);
#endif

View File

@ -286,6 +286,15 @@ arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0,
"start of the disk (between 0 and 3 inclusive - see LABEL_SCAN_SECTORS\n"
"in the source). Use with care.\n")
arg(listlvs_ARG, '\0', "listlvs", 0, 0, 0,
"Print a list of LVs that use the device.\n")
arg(listvg_ARG, '\0', "listvg", 0, 0, 0,
"Print the VG that uses the device.\n")
arg(checkcomplete_ARG, '\0', "checkcomplete", 0, 0, 0,
"Check if all the devices used by VG or LV are present.\n")
arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0,
"Used to pass options for special cases to lvmlockd.\n"
"See \\fBlvmlockd\\fP(8) for more information.\n")

View File

@ -1569,11 +1569,37 @@ DESC: Display PV information.
pvscan --cache_long
OO: --ignorelockingfailure, --reportformat ReportFmt,
--activate ay, --major Number, --minor Number, --noudevsync
--major Number, --minor Number, --noudevsync
OP: PV|String ...
IO: --background
ID: pvscan_cache
DESC: Autoactivate a VG when all PVs are online.
DESC: Record that a PV is online or offline.
pvscan --cache_long --activate ay
OO: --ignorelockingfailure, --reportformat ReportFmt,
--major Number, --minor Number, --noudevsync
OP: PV|String ...
IO: --background
ID: pvscan_cache
DESC: Record that a PV is online and autoactivate VG if complete.
pvscan --cache_long --listvg PV
OO: --ignorelockingfailure, --checkcomplete
ID: pvscan_cache
DESC: Record that a PV is online and list the VG using the PV.
pvscan --cache_long --listlvs PV
OO: --ignorelockingfailure, --checkcomplete
ID: pvscan_cache
DESC: Record that a PV is online and list LVs using the PV.
pvscan --listlvs PV
ID: pvscan_cache
DESC: List LVs using the PV.
pvscan --listvg PV
ID: pvscan_cache
DESC: List the VG using the PV.
---

View File

@ -1175,6 +1175,64 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
return 1;
}
static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group *vg)
{
char path[PATH_MAX];
char file_vgname[NAME_LEN];
char pvid[ID_LEN+1] = { 0 };
struct pv_list *pvl;
struct device *dev;
int major, minor;
dev_t devno;
dm_list_iterate_items(pvl, &vg->pvs) {
memcpy(&pvid, &pvl->pv->id.uuid, ID_LEN);
if (pvl->pv->status & MISSING_PV) {
log_debug("set_pv_devices_online vg %s pv %s missing flag already set",
vg->name, pvid);
continue;
}
if (!_online_pvid_file_exists(pvid)) {
log_debug("set_pv_devices_online vg %s pv %s no online file",
vg->name, pvid);
pvl->pv->status |= MISSING_PV;
continue;
}
memset(path, 0, sizeof(path));
snprintf(path, sizeof(path), "%s/%s", _pvs_online_dir, pvid);
major = 0;
minor = 0;
file_vgname[0] = '\0';
_online_pvid_file_read(path, &major, &minor, file_vgname);
if (file_vgname[0] && strcmp(vg->name, file_vgname)) {
log_warn("WARNING: VG %s PV %s wrong vgname in online file %s",
vg->name, pvid, file_vgname);
pvl->pv->status |= MISSING_PV;
continue;
}
devno = MKDEV(major, minor);
if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
log_print("WARNING: VG %s PV %s no device found for %d:%d",
vg->name, pvid, major, minor);
pvl->pv->status |= MISSING_PV;
continue;
}
log_debug("set_pv_devices_online vg %s pv %s is online %s",
vg->name, pvid, dev_name(dev));
pvl->pv->dev = dev;
}
}
static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvscan_devs,
int *pv_count, struct dm_list *complete_vgnames)
{
@ -1188,7 +1246,11 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
struct volume_group *vg;
const char *vgname;
uint32_t ext_version, ext_flags;
int do_cache = arg_is_set(cmd, cache_long_ARG);
int do_activate = arg_is_set(cmd, activate_ARG);
int list_lvs = arg_is_set(cmd, listlvs_ARG);
int list_vg = arg_is_set(cmd, listvg_ARG);
int check_complete = arg_is_set(cmd, checkcomplete_ARG);
int pvs_online;
int pvs_offline;
int pvs_unknown;
@ -1243,8 +1305,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
goto online;
}
set_pv_devices(fid, vg, NULL);
#if 0
/*
* Skip devs that are md components (set_pv_devices can do new
* md check), are shared, or foreign.
@ -1255,6 +1316,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
release_vg(vg);
continue;
}
#endif
if (vg_is_shared(vg)) {
log_print("pvscan[%d] PV %s ignore shared VG.", getpid(), dev_name(dev));
@ -1286,8 +1348,9 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
/*
* Create file named for pvid to record this PV is online.
* The command creates/checks online files only when --cache is used.
*/
if (!_online_pvid_file_create(dev, vg ? vg->name : NULL)) {
if (do_cache && !_online_pvid_file_create(dev, vg ? vg->name : NULL)) {
log_error("pvscan[%d] PV %s failed to create online file.", getpid(), dev_name(dev));
release_vg(vg);
ret = 0;
@ -1295,9 +1358,9 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
}
/*
* When not activating we don't need to know about vg completeness.
* A plain pvscan --cache <dev> just creates the online file.
*/
if (!do_activate) {
if (!do_activate && !list_lvs && !list_vg) {
log_print("pvscan[%d] PV %s online.", getpid(), dev_name(dev));
release_vg(vg);
continue;
@ -1306,8 +1369,10 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
/*
* Check if all the PVs for this VG are online. If the arrival
* of this dev completes the VG, then save the vgname in
* complete_vgnames so it will be activated.
* complete_vgnames (activation phase will want to know which
* VGs to activate.)
*/
if (do_activate || check_complete) {
pvs_online = 0;
pvs_offline = 0;
pvs_unknown = 0;
@ -1359,8 +1424,71 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
stack;
vg_complete = 1;
}
}
if (!saved_vg && vg && vg_complete && !do_all && (dm_list_size(pvscan_devs) == 1))
if (!vgname && vg)
vgname = vg->name;
if (list_lvs) {
struct dm_list lvs_list;
struct lv_list *lvl;
dm_list_init(&lvs_list);
/*
* For each vg->pvs entry, get the dev based on the online file
* for the pvid and set pv->dev or pv->status MISSING_PV.
*/
_set_pv_devices_online(cmd, vg);
/*
* lvs_list are LVs that use dev.
*/
if (!get_visible_lvs_using_pv(cmd, vg, dev, &lvs_list))
log_warn("WARNING: failed to find LVs using %s.", dev_name(dev));
if (!check_complete) {
dm_list_iterate_items(lvl, &lvs_list)
log_print("LV %s", display_lvname(lvl->lv));
} else if (vg_complete) {
/*
* A shortcut; the vg complete implies all lvs are complete.
*/
dm_list_iterate_items(lvl, &lvs_list)
log_print("LV %s complete", display_lvname(lvl->lv));
} else {
/*
* For each LV in VG, check if all devs are present.
* Sets the PARTIAL flag on LVs that are not complete.
*/
if (!vg_mark_partial_lvs(vg, 1))
log_print("Failed to check partial lvs.");
dm_list_iterate_items(lvl, &lvs_list) {
if (!lv_is_partial(lvl->lv))
log_print("LV %s complete", display_lvname(lvl->lv));
else
log_print("LV %s incomplete", display_lvname(lvl->lv));
}
}
}
if (list_vg) {
if (!vgname)
log_print("VG unknown");
else if (!check_complete)
log_print("VG %s", vgname);
else if (vg_complete)
log_print("VG %s complete", vgname);
else
log_print("VG %s incomplete", vgname);
}
/*
* When "pvscan --cache -aay <dev>" completes the vg, save the
* struct vg to use for quick activation function.
*/
if (do_activate && !saved_vg && vg && vg_complete && !do_all && (dm_list_size(pvscan_devs) == 1))
saved_vg = vg;
else
release_vg(vg);