File lvm-pv-create-link.diff of Package lvm2

Index: LVM2.2.02.39/tools/pvremove.c
===================================================================
--- LVM2.2.02.39.orig/tools/pvremove.c	2007-11-22 02:25:06.000000000 +0100
+++ LVM2.2.02.39/tools/pvremove.c	2008-09-10 12:13:19.000000000 +0200
@@ -18,6 +18,32 @@
 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[60];
+
+	init_partial(1);
+	if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
+		return NULL;
+	}
+	init_partial(0);
+
+	pvuuid = malloc(sizeof(char)*40);
+	if (pvuuid == NULL) {
+		return NULL;
+	}
+
+	id_write_format(&pv->id, pvuuid, 40);
+
+	snprintf(pvuuid_link, 60, "/dev/disk/by-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.
@@ -108,6 +134,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.39/tools/pvcreate.c
===================================================================
--- LVM2.2.02.39.orig/tools/pvcreate.c	2008-06-24 22:10:32.000000000 +0200
+++ LVM2.2.02.39/tools/pvcreate.c	2008-09-10 12:13:19.000000000 +0200
@@ -23,6 +23,95 @@
 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;
+	int old_partial;
+
+	pvuuid_link = malloc(60);
+	if (pvuuid_link == NULL) return NULL;
+
+	old_partial = partial_mode();
+
+    init_partial(1);
+    if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
+		free(pvuuid_link);
+		init_partial(old_partial);
+		return NULL;
+	}
+    init_partial(old_partial);
+
+    pvuuid = malloc(sizeof(char)*40);
+    if (pvuuid == NULL) {
+		free(pvuuid_link);
+		return NULL;
+	}
+
+    id_write_format(&pv->id, pvuuid, 40);
+
+    snprintf(pvuuid_link, 60, "/dev/disk/by-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.
@@ -42,6 +131,7 @@
 
 	/* Is there a pv here already? */
 	/* FIXME Use partial mode here? */
+	init_partial(1);
 	pv = pv_read(cmd, name, NULL, NULL, 0);
 
 	/*
@@ -55,6 +145,7 @@
 			return_0;
 		pv = pv_read(cmd, name, NULL, NULL, 0);
 	}
+	init_partial(0);
 
 	/* Allow partial & exported VGs to be destroyed. */
 	/* We must have -ff to overwrite a non orphan */
@@ -151,6 +242,7 @@
 	const char *restorefile;
 	uint64_t pe_start = 0;
 	uint32_t extent_count = 0, extent_size = 0;
+	const char *oldsymlink;
 
 	if (arg_count(cmd, uuidstr_ARG)) {
 		uuid = arg_str_value(cmd, uuidstr_ARG, "");
@@ -258,13 +350,23 @@
 
 	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,
 		       arg_int64_value(cmd, labelsector_ARG,
 						       DEFAULT_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.39/tools/pvchange.c
===================================================================
--- LVM2.2.02.39.orig/tools/pvchange.c	2008-02-06 16:47:28.000000000 +0100
+++ LVM2.2.02.39/tools/pvchange.c	2008-09-10 12:16:42.000000000 +0200
@@ -15,6 +15,95 @@
 
 #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;
+	int old_partial;
+
+	pvuuid_link = malloc(60);
+	if (pvuuid_link == NULL) return NULL;
+
+	old_partial = partial_mode();
+
+	init_partial(1);
+	if (!(pv = pv_read(cmd, name, NULL, NULL, 1))) {
+		free(pvuuid_link);
+		init_partial(old_partial);
+		return NULL;
+	}
+	init_partial(old_partial);
+
+	pvuuid = malloc(sizeof(char)*40);
+	if (pvuuid == NULL) {
+		free(pvuuid_link);
+		return NULL;
+	}
+
+	id_write_format(&pv->id, pvuuid, 40);
+
+	snprintf(pvuuid_link, 60, "/dev/disk/by-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,
@@ -169,16 +258,28 @@
 		}
 		log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
 		if (!is_orphan(pv)) {
+			const char* oldsymlink;
+
 			orig_vg_name = pv_vg_name(pv);
 			orig_pe_alloc_count = pv_pe_alloc_count(pv);
 			pv->vg_name = pv->fmt->orphan_vg_name;
 			pv->pe_alloc_count = 0;
+			oldsymlink = pv_symlink_handle(cmd, pv_name, 0);
+
 			if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
 				log_error("pv_write with new uuid failed "
 					  "for %s.", pv_name);
+				if (oldsymlink) free(oldsymlink);
 				unlock_vg(cmd, vg_name);
 				return 0;
 			}
+
+			pv_symlink_handle(cmd, pv_name, 1);
+			if (oldsymlink) {
+				unlink(oldsymlink);
+				free(oldsymlink);
+			}
+
 			pv->vg_name = orig_vg_name;
 			pv->pe_alloc_count = orig_pe_alloc_count;
 		}
@@ -193,11 +294,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);
openSUSE Build Service is sponsored by