lvm2/lvm-pv-create-link.diff

295 lines
6.7 KiB
Diff

Index: LVM2.2.02.45/tools/pvremove.c
===================================================================
--- LVM2.2.02.45.orig/tools/pvremove.c 2009-04-27 16:35:32.000000000 +0800
+++ LVM2.2.02.45/tools/pvremove.c 2009-04-27 16:49:48.000000000 +0800
@@ -18,6 +18,30 @@
const char _really_wipe[] =
"Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+static const char* pv_remove_symlink(struct cmd_context* cmd, const char* name)
+{
+ struct physical_volume *pv;
+ char *pvuuid;
+ char pvuuid_link[70];
+
+ if (!(pv = pv_read(cmd, name, NULL, NULL, 0, 0))) {
+ return NULL;
+ }
+
+ pvuuid = malloc(sizeof(char)*40);
+ if (pvuuid == NULL) {
+ return NULL;
+ }
+
+ id_write_format(&pv->id, pvuuid, 40);
+
+ snprintf(pvuuid_link, 70, "/dev/disk/by-id/lvm2-pvuuid-%s", pvuuid);
+ unlink(pvuuid_link); //we really don't care if it successed or not.
+
+ free(pvuuid);
+ return pvuuid;
+}
+
/*
* Decide whether it is "safe" to wipe the labels on this device.
* 0 indicates we may not.
@@ -125,6 +149,8 @@
log_print("Labels on physical volume \"%s\" successfully wiped",
pv_name);
+ pv_remove_symlink(cmd, pv_name);
+
ret = ECMD_PROCESSED;
error:
Index: LVM2.2.02.45/tools/pvcreate.c
===================================================================
--- LVM2.2.02.45.orig/tools/pvcreate.c 2009-04-27 16:35:32.000000000 +0800
+++ LVM2.2.02.45/tools/pvcreate.c 2009-04-27 16:45:34.000000000 +0800
@@ -36,6 +36,89 @@
const char _really_init[] =
"Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? ";
+static const char* pv_follow_if_link (const char* path)
+{
+ int r;
+ int len = 60;
+ char *fpath = NULL;
+ char *npath = NULL;
+ struct stat st;
+
+ r = lstat(path, &st);
+ if (r == -1) return NULL; //shouldn't happen
+
+ if (S_ISLNK(st.st_mode)) {
+ while (1) {
+ npath = realloc(fpath, sizeof(char)*len);
+ if (npath == NULL) {
+ if (fpath != NULL) free(fpath);
+ return NULL;
+ }
+ fpath = npath;
+
+ memset(fpath, 0, sizeof(char)*len);
+ r = readlink(path, fpath, len);
+ if (r != -1 && fpath[len-1] == 0) break;
+ if (r == -1) {
+ free(fpath);
+ return NULL;
+ } else {
+ len = len * 2;
+ }
+ }
+ }
+ else {
+ fpath = strdup(path);
+ }
+ return fpath;
+}
+
+
+static const char* pv_symlink_handle(struct cmd_context* cmd, const char* name, int create)
+{
+ struct physical_volume *pv;
+ char *pvuuid;
+ char *pvuuid_link;
+
+ pvuuid_link = malloc(70);
+ if (pvuuid_link == NULL) return NULL;
+
+ if (!(pv = pv_read(cmd, name, NULL, NULL, 0, 0))) {
+ free(pvuuid_link);
+ return NULL;
+ }
+
+ pvuuid = malloc(sizeof(char)*40);
+ if (pvuuid == NULL) {
+ free(pvuuid_link);
+ return NULL;
+ }
+
+ id_write_format(&pv->id, pvuuid, 40);
+
+ snprintf(pvuuid_link, 70, "/dev/disk/by-id/lvm2-pvuuid-%s", pvuuid);
+
+ //we really don't care if it successed or not.
+ if (create) {
+ const char* tname = NULL;
+ int r;
+ tname = pv_follow_if_link(name);
+ if (tname != NULL) {
+ r = symlink(tname, pvuuid_link);
+ free(tname);
+ }
+ else {
+ symlink(name, pvuuid_link);
+ }
+ } else {
+ //pvuuid_link is saved for future unlink
+ //unlink(pvuuid_link);
+ }
+
+ free(pvuuid);
+ return pvuuid_link;
+}
+
/*
* See if we may pvcreate on this device.
* 0 indicates we may not.
@@ -150,6 +233,8 @@
void *pv;
struct device *dev;
struct dm_list mdas;
+ const char *oldsymlink;
+
if (pp->idp) {
if ((dev = device_from_pvid(cmd, pp->idp)) &&
@@ -213,12 +298,22 @@
log_very_verbose("Writing physical volume data to disk \"%s\"",
pv_name);
+
+ oldsymlink = pv_symlink_handle(cmd, pv_name, 0);
+
if (!(pv_write(cmd, (struct physical_volume *)pv, &mdas,
pp->labelsector))) {
log_error("Failed to write physical volume \"%s\"", pv_name);
+ if (oldsymlink) free(oldsymlink);
goto error;
}
+ pv_symlink_handle(cmd, pv_name, 1);
+ if (oldsymlink) {
+ unlink(oldsymlink);
+ free(oldsymlink);
+ }
+
log_print("Physical volume \"%s\" successfully created", pv_name);
unlock_vg(cmd, VG_ORPHANS);
Index: LVM2.2.02.45/tools/pvchange.c
===================================================================
--- LVM2.2.02.45.orig/tools/pvchange.c 2009-04-27 16:35:32.000000000 +0800
+++ LVM2.2.02.45/tools/pvchange.c 2009-04-27 16:45:18.000000000 +0800
@@ -15,6 +15,90 @@
#include "tools.h"
+static const char* pv_follow_if_link (const char* path)
+{
+ int r;
+ int len = 60;
+ char *fpath = NULL;
+ char *npath = NULL;
+ struct stat st;
+
+ r = lstat(path, &st);
+ if (r == -1) return NULL; //shouldn't happen
+
+ if (S_ISLNK(st.st_mode)) {
+ while (1) {
+ npath = realloc(fpath, sizeof(char)*len);
+ if (npath == NULL) {
+ if (fpath != NULL) free(fpath);
+ return NULL;
+ }
+ fpath = npath;
+
+ memset(fpath, 0, sizeof(char)*len);
+ r = readlink(path, fpath, len);
+ if (r != -1 && fpath[len-1] == 0) break;
+ if (r == -1) {
+ free(fpath);
+ return NULL;
+ } else {
+ len = len * 2;
+ }
+ }
+ }
+ else {
+ fpath = strdup(path);
+ }
+ return fpath;
+}
+
+static const char* pv_symlink_handle(struct cmd_context* cmd, const char* name, int create)
+{
+ struct physical_volume *pv;
+ char *pvuuid;
+ char *pvuuid_link;
+
+ pvuuid_link = malloc(70);
+ if (pvuuid_link == NULL) return NULL;
+
+
+ if (!(pv = pv_read(cmd, name, NULL, NULL, 0, 0))) {
+ free(pvuuid_link);
+ return NULL;
+ }
+
+ pvuuid = malloc(sizeof(char)*40);
+ if (pvuuid == NULL) {
+ free(pvuuid_link);
+ return NULL;
+ }
+
+ id_write_format(&pv->id, pvuuid, 40);
+
+ snprintf(pvuuid_link, 70, "/dev/disk/by-id/lvm2-pvuuid-%s", pvuuid);
+
+ //we really don't care if it successed or not.
+ if (create) {
+ const char* tname = NULL;
+ int r;
+ tname = pv_follow_if_link(name);
+ if (tname != NULL) {
+ r = symlink(tname, pvuuid_link);
+ free(tname);
+ }
+ else {
+ symlink(name, pvuuid_link);
+ }
+ } else {
+ //pvuuid_link is saved for future unlink
+ //unlink(pvuuid_link);
+ }
+
+ free(pvuuid);
+ return pvuuid_link;
+}
+
+
/* FIXME Locking. PVs in VG. */
static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
@@ -202,11 +286,23 @@
return 0;
}
backup(vg);
- } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
- unlock_vg(cmd, vg_name);
- log_error("Failed to store physical volume \"%s\"",
- pv_name);
- return 0;
+ } else {
+ const char* oldsymlink;
+ oldsymlink = pv_symlink_handle(cmd, pv_name, 0);
+
+ if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+ unlock_vg(cmd, vg_name);
+ log_error("Failed to store physical volume \"%s\"",
+ pv_name);
+ if (oldsymlink) free(oldsymlink);
+ return 0;
+ }
+ pv_symlink_handle(cmd, pv_name, 1);
+ if (oldsymlink) {
+ unlink(oldsymlink);
+ free(oldsymlink);
+ }
+
}
unlock_vg(cmd, vg_name);