/* Convert a non-canonical LV path like /dev/mapper/vg-lv or /dev/dm-0 * to a canonical one. * * This is harder than it should be. A LV device like /dev/VG/LV is * really a symlink to a device-mapper device like /dev/dm-0. However * at the device-mapper (kernel) level, nothing is really known about * LVM (a userspace concept). Therefore we use a convoluted method to * determine this, by listing out known LVs and checking whether the * rdev (major/minor) of the device we are passed matches any of them. * * Note use of 'stat' instead of 'lstat' so that symlinks are fully * resolved. * * Returns: * 1 = conversion was successful, path is an LV * '*ret' is set to the updated path if 'ret' is non-NULL. * 0 = path is not an LV * -1 = error, reply_with_* has been called * */ int lv_canonical (const char *device, char **ret) { struct stat stat1, stat2; int r = stat (device, &stat1); if (r == -1) { reply_with_perror ("stat: %s", device); return -1; } char **lvs = do_lvs (); if (lvs == NULL) return -1; size_t i; for (i = 0; lvs[i] != NULL; ++i) { r = stat (lvs[i], &stat2); if (r == -1) { reply_with_perror ("stat: %s", lvs[i]); free_strings (lvs); return -1; } if (stat1.st_rdev == stat2.st_rdev) { /* found it */ if (ret) { *ret = strdup (lvs[i]); if (*ret == NULL) { reply_with_perror ("strdup"); free_strings (lvs); return -1; } } free_strings (lvs); return 1; } } /* not found */ free_strings (lvs); return 0; }
/* Super-dangerous command used for testing. It removes all * LVs, VGs and PVs permanently. */ int do_lvm_remove_all (void) { size_t i; int r; { /* Remove LVs. */ CLEANUP_FREE_STRING_LIST char **xs = do_lvs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { CLEANUP_FREE char *err = NULL; /* Deactivate the LV first. On Ubuntu, lvremove '-f' option * does not remove active LVs reliably. */ (void) command (NULL, NULL, str_lvm, "lvchange", "-an", xs[i], NULL); udev_settle (); r = command (NULL, &err, str_lvm, "lvremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("lvremove: %s: %s", xs[i], err); return -1; } } } { /* Remove VGs. */ CLEANUP_FREE_STRING_LIST char **xs = do_vgs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { CLEANUP_FREE char *err = NULL; /* Deactivate the VG first, see note above. */ (void) command (NULL, NULL, str_lvm, "vgchange", "-an", xs[i], NULL); udev_settle (); r = command (NULL, &err, str_lvm, "vgremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("vgremove: %s: %s", xs[i], err); return -1; } } } { /* Remove PVs. */ CLEANUP_FREE_STRING_LIST char **xs = do_pvs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { CLEANUP_FREE char *err = NULL; r = command (NULL, &err, str_lvm, "pvremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("pvremove: %s: %s", xs[i], err); return -1; } } } udev_settle (); /* There, that was easy, sorry about your data. */ return 0; }
/* Super-dangerous command used for testing. It removes all * LVs, VGs and PVs permanently. */ int do_lvm_remove_all (void) { char **xs; int i, r; char *err; /* Remove LVs. */ xs = do_lvs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { /* Deactivate the LV first. On Ubuntu, lvremove '-f' option * does not remove active LVs reliably. */ (void) command (NULL, NULL, "lvm", "lvchange", "-an", xs[i], NULL); udev_settle (); r = command (NULL, &err, "lvm", "lvremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("lvremove: %s: %s", xs[i], err); free (err); free_strings (xs); return -1; } free (err); } free_strings (xs); /* Remove VGs. */ xs = do_vgs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { /* Deactivate the VG first, see note above. */ (void) command (NULL, NULL, "lvm", "vgchange", "-an", xs[i], NULL); udev_settle (); r = command (NULL, &err, "lvm", "vgremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("vgremove: %s: %s", xs[i], err); free (err); free_strings (xs); return -1; } free (err); } free_strings (xs); /* Remove PVs. */ xs = do_pvs (); if (xs == NULL) return -1; for (i = 0; xs[i] != NULL; ++i) { r = command (NULL, &err, "lvm", "pvremove", "-f", xs[i], NULL); if (r == -1) { reply_with_error ("pvremove: %s: %s", xs[i], err); free (err); free_strings (xs); return -1; } free (err); } free_strings (xs); udev_settle (); /* There, that was easy, sorry about your data. */ return 0; }