Index: LVM2.2.02.84/tools/pvremove.c
===================================================================
--- LVM2.2.02.84.orig/tools/pvremove.c	2011-02-17 15:34:05.000000000 +0800
+++ LVM2.2.02.84/tools/pvremove.c	2011-02-17 15:34:08.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] __attribute__((aligned(8)));
+
+	if (!(pv = pv_read(cmd, name, NULL, NULL, 0, 0))) {
+		return NULL;
+	}
+
+	pvuuid = dm_malloc(sizeof(char)*40);
+	if (pvuuid == NULL) {
+		return NULL;
+	}
+
+	id_write_format(&pv->id, pvuuid, 40);
+
+	dm_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.
+
+	dm_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.84/tools/pvchange.c
===================================================================
--- LVM2.2.02.84.orig/tools/pvchange.c	2011-02-17 15:34:05.000000000 +0800
+++ LVM2.2.02.84/tools/pvchange.c	2011-02-17 15:35:31.000000000 +0800
@@ -15,6 +15,103 @@
 
 #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 = dm_realloc (fpath, sizeof (char) * len);
+	  if (npath == NULL)
+	    {
+	      if (fpath != NULL)
+		dm_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)
+	    {
+	      dm_free (fpath);
+	      return NULL;
+	    }
+	  else
+	    {
+	      len = len * 2;
+	    }
+	}
+    }
+  else
+    {
+      fpath = dm_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 = dm_malloc (70);
+  if (pvuuid_link == NULL)
+    return NULL;
+  if (!(pv = pv_read (cmd, name, NULL, NULL, 0, 0)))
+    {
+      free (pvuuid_link);
+      return NULL;
+    }
+  pvuuid = dm_malloc (sizeof (char) * 40);
+  if (pvuuid == NULL)
+    {
+      dm_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);
+	  dm_free (tname);
+	}
+      else
+	{
+	  symlink (name, pvuuid_link);
+	}
+    }
+  else
+    {
+      //pvuuid_link is saved for future unlink
+      //unlink(pvuuid_link);
+    }
+  dm_free (pvuuid);
+  return pvuuid_link;
+}
+
 static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
 			    struct physical_volume *pv,
 			    void *handle __attribute__((unused)))
@@ -129,6 +226,7 @@
 			return 0;
 		log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
 		if (!is_orphan(pv)) {
+			char *oldsymlink;
 			orig_vg_name = pv_vg_name(pv);
 			orig_pe_alloc_count = pv_pe_alloc_count(pv);
 
@@ -139,11 +237,18 @@
 
 			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) dm_free(oldsymlink);
 				return 0;
 			}
+			pv_symlink_handle(cmd, pv_name, 1);
+			if (oldsymlink) {
+			  unlink(oldsymlink);
+			  dm_free(oldsymlink);
+			}
 			pv->vg_name = orig_vg_name;
 			pv->pe_alloc_count = orig_pe_alloc_count;
 
@@ -161,10 +266,20 @@
 			return 0;
 		}
 		backup(vg);
-	} else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
-		log_error("Failed to store physical volume \"%s\"",
-			  pv_name);
-		return 0;
+	} else {
+		char *oldsymlink;
+		oldsymlink = pv_symlink_handle(cmd, pv_name, 0);
+		if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
+			log_error("Failed to store physical volume \"%s\"",
+				pv_name);
+			if (oldsymlink) dm_free(oldsymlink);
+			return 0;
+		}
+		pv_symlink_handle(cmd, pv_name, 1);
+		if (oldsymlink) {
+		  unlink(oldsymlink);
+		  dm_free(oldsymlink);
+		}
 	}
 
 	log_print("Physical volume \"%s\" changed", pv_name);
Index: LVM2.2.02.84/lib/metadata/metadata.c
===================================================================
--- LVM2.2.02.84.orig/lib/metadata/metadata.c	2011-02-17 15:34:05.000000000 +0800
+++ LVM2.2.02.84/lib/metadata/metadata.c	2011-02-17 15:34:08.000000000 +0800
@@ -56,6 +56,102 @@
 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 = dm_realloc (fpath, sizeof (char) * len);
+	  if (npath == NULL)
+	    {
+	      if (fpath != NULL)
+		dm_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)
+	    {
+	      dm_free (fpath);
+	      return NULL;
+	    }
+	  else
+	    {
+	      len = len * 2;
+	    }
+	}
+    }
+  else
+    {
+      fpath = dm_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 = dm_malloc (70);
+  if (pvuuid_link == NULL)
+    return NULL;
+  if (!(pv = pv_read (cmd, name, NULL, NULL, 0, 0)))
+    {
+      free (pvuuid_link);
+      return NULL;
+    }
+  pvuuid = dm_malloc (sizeof (char) * 40);
+  if (pvuuid == NULL)
+    {
+      dm_free (pvuuid_link);
+      return NULL;
+    }
+  id_write_format (&pv->id, pvuuid, 40);
+
+  dm_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);
+	  dm_free (tname);
+	}
+      else
+	{
+	  symlink (name, pvuuid_link);
+	}
+    }
+  else
+    {
+      //pvuuid_link is saved for future unlink
+      //unlink(pvuuid_link);
+    }
+  dm_free (pvuuid);
+  return pvuuid_link;
+}
+
 static int _alignment_overrides_default(unsigned long data_alignment,
 					unsigned long default_pe_align)
 {
@@ -1456,7 +1552,8 @@
 	struct dm_list mdas;
 	struct pvcreate_params default_pp;
 	char buffer[64] __attribute__((aligned(8)));
-
+	const char* oldsymlink;
+	
 	pvcreate_params_set_defaults(&default_pp);
 	if (!pp)
 		pp = &default_pp;
@@ -1522,10 +1619,17 @@
 	log_very_verbose("Writing physical volume data to disk \"%s\"",
 			 pv_name);
 
+	oldsymlink = pv_symlink_handle(cmd, pv_name, 0);
 	if (!(pv_write(cmd, pv, &mdas, pp->labelsector))) {
 		log_error("Failed to write physical volume \"%s\"", pv_name);
+		if (oldsymlink) dm_free(oldsymlink);
 		goto error;
 	}
+	pv_symlink_handle(cmd, pv_name, 1);
+	if (oldsymlink) {
+	  unlink(oldsymlink);
+	  dm_free(oldsymlink);
+	}
 
 	log_print("Physical volume \"%s\" successfully created", pv_name);
 
