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-11 16:10:31.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[70]; + + 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, 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. @@ -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-11 16:11:04.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(70); + 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, 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. @@ -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-11 16:11:27.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(70); + 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, 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, @@ -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);