diff options
author | Alasdair Kergon <agk@redhat.com> | 2008-04-08 12:49:21 +0000 |
---|---|---|
committer | Alasdair Kergon <agk@redhat.com> | 2008-04-08 12:49:21 +0000 |
commit | 6eb44b50913ae83449fef735dd9f356de2cb710a (patch) | |
tree | 4344136298268095e8e8c729c43fceb8f28a7440 | |
parent | ad607a23f16ceda1824ed12462ccc557c85085e5 (diff) | |
download | lvm2-6eb44b50913ae83449fef735dd9f356de2cb710a.tar.gz lvm2-6eb44b50913ae83449fef735dd9f356de2cb710a.tar.xz lvm2-6eb44b50913ae83449fef735dd9f356de2cb710a.zip |
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
Add (empty) orphan VGs to lvmcache during initialisation.
Fix orphan VG name used for format_pool.
-rw-r--r-- | WHATS_NEW | 3 | ||||
-rw-r--r-- | lib/cache/lvmcache.c | 118 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 3 | ||||
-rw-r--r-- | lib/commands/toolcontext.c | 21 | ||||
-rw-r--r-- | lib/commands/toolcontext.h | 1 | ||||
-rw-r--r-- | lib/format_pool/format_pool.c | 4 | ||||
-rw-r--r-- | lib/format_pool/format_pool.h | 3 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 17 | ||||
-rw-r--r-- | tools/lvmcmdline.c | 2 | ||||
-rw-r--r-- | tools/pvcreate.c | 2 | ||||
-rw-r--r-- | tools/pvscan.c | 2 | ||||
-rw-r--r-- | tools/vgreduce.c | 29 | ||||
-rw-r--r-- | tools/vgrename.c | 2 | ||||
-rw-r--r-- | tools/vgscan.c | 2 |
14 files changed, 151 insertions, 58 deletions
@@ -1,5 +1,8 @@ Version 2.02.34 - =================================== + Fix vgreduce to use vg_split_mdas to check sufficient mdas remain. + Add (empty) orphan VGs to lvmcache during initialisation. + Fix orphan VG name used for format_pool. Create a fid for internal orphan VGs. Update lvmcache VG lock state for all locking types now. Fix output if overriding command_names on cmdline. diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 04b62138..4790056b 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -536,34 +536,38 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid) return NULL; } -static int _drop_vginfo(struct lvmcache_info *info) +/* + * vginfo must be info->vginfo unless info is NULL + */ +static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo) { - if (!list_empty(&info->list)) { + if (info && !list_empty(&info->list)) { list_del(&info->list); list_init(&info->list); } - if (info->vginfo && list_empty(&info->vginfo->infos)) { - dm_hash_remove(_vgname_hash, info->vginfo->vgname); - if (info->vginfo->next) { - if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) { + if (vginfo && !is_orphan_vg(vginfo->vgname) && list_empty(&vginfo->infos)) { + dm_hash_remove(_vgname_hash, vginfo->vgname); + if (vginfo->next) { + if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) { log_error("vg hash re-insertion failed: %s", - info->vginfo->vgname); + vginfo->vgname); return 0; } } - if (info->vginfo->vgname) - dm_free(info->vginfo->vgname); - if (info->vginfo->creation_host) - dm_free(info->vginfo->creation_host); - if (*info->vginfo->vgid) - dm_hash_remove(_vgid_hash, info->vginfo->vgid); - list_del(&info->vginfo->list); + if (vginfo->vgname) + dm_free(vginfo->vgname); + if (vginfo->creation_host) + dm_free(vginfo->creation_host); + if (*vginfo->vgid) + dm_hash_remove(_vgid_hash, vginfo->vgid); + list_del(&vginfo->list); dm_free(info->vginfo); } - info->vginfo = NULL; + if (info) + info->vginfo = NULL; return 1; } @@ -574,7 +578,7 @@ void lvmcache_del(struct lvmcache_info *info) if (info->dev->pvid[0] && _pvid_hash) dm_hash_remove(_pvid_hash, info->dev->pvid); - _drop_vginfo(info); + _drop_vginfo(info, info->vginfo); info->label->labeller->ops->destroy_label(info->label->labeller, info->label); @@ -599,31 +603,36 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid) return 1; } -static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid) +/* + * vginfo must be info->vginfo unless info is NULL (orphans) + */ +static int _lvmcache_update_vgid(struct lvmcache_info *info, + struct lvmcache_vginfo *vginfo, + const char *vgid) { - if (!vgid || !info->vginfo || - !strncmp(info->vginfo->vgid, vgid, ID_LEN)) + if (!vgid || !vginfo || + !strncmp(vginfo->vgid, vgid, ID_LEN)) return 1; - if (info->vginfo && *info->vginfo->vgid) - dm_hash_remove(_vgid_hash, info->vginfo->vgid); + if (vginfo && *vginfo->vgid) + dm_hash_remove(_vgid_hash, vginfo->vgid); if (!vgid) { - log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev)); + log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname); return 1; } - strncpy(info->vginfo->vgid, vgid, ID_LEN); - info->vginfo->vgid[ID_LEN] = '\0'; - if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) { + strncpy(vginfo->vgid, vgid, ID_LEN); + vginfo->vgid[ID_LEN] = '\0'; + if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) { log_error("_lvmcache_update: vgid hash insertion failed: %s", - info->vginfo->vgid); + vginfo->vgid); return 0; } - if (!is_orphan_vg(info->vginfo->vgname)) + if (!is_orphan_vg(vginfo->vgname)) log_debug("lvmcache: %s: setting %s VGID to %s", - dev_name(info->dev), info->vginfo->vgname, - info->vginfo->vgid); + dev_name(info->dev), vginfo->vgname, + vginfo->vgid); return 1; } @@ -714,16 +723,18 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid, static int _lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname, const char *vgid, - uint32_t vgstatus, const char *creation_host) + uint32_t vgstatus, const char *creation_host, + const struct format_type *fmt) { struct lvmcache_vginfo *vginfo, *primary_vginfo; // struct lvmcache_vginfo *old_vginfo, *next; - if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname))) + if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname))) return 1; /* Remove existing vginfo entry */ - _drop_vginfo(info); + if (info) + _drop_vginfo(info, info->vginfo); /* Get existing vginfo or create new one */ if (!(vginfo = vginfo_from_vgname(vgname, vgid))) { @@ -791,18 +802,25 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info, ***/ } - info->vginfo = vginfo; - list_add(&vginfo->infos, &info->list); + if (info) { + info->vginfo = vginfo; + list_add(&vginfo->infos, &info->list); + } else if (!_lvmcache_update_vgid(info, vginfo, vgid)) /* Orphans */ + return_0; _update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname)); /* FIXME Check consistency of list! */ - vginfo->fmt = info->fmt; - - log_debug("lvmcache: %s: now in VG %s%s%s%s", dev_name(info->dev), - vgname, vginfo->vgid[0] ? " (" : "", - vginfo->vgid[0] ? vginfo->vgid : "", - vginfo->vgid[0] ? ")" : ""); + vginfo->fmt = fmt; + + if (info) + log_debug("lvmcache: %s: now in VG %s%s%s%s", + dev_name(info->dev), + vgname, vginfo->vgid[0] ? " (" : "", + vginfo->vgid[0] ? vginfo->vgid : "", + vginfo->vgid[0] ? ")" : ""); + else + log_debug("lvmcache: initialised VG %s", vgname); return 1; } @@ -842,6 +860,16 @@ static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstat return 1; } +int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt) +{ + if (!_lock_hash && !lvmcache_init()) { + log_error("Internal cache initialisation failed"); + return 0; + } + + return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt); +} + int lvmcache_update_vgname_and_id(struct lvmcache_info *info, const char *vgname, const char *vgid, uint32_t vgstatus, const char *creation_host) @@ -852,9 +880,10 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, vgname = info->fmt->orphan_vg_name; vgid = vgname; } + if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus, - creation_host) || - !_lvmcache_update_vgid(info, vgid) || + creation_host, info->fmt) || + !_lvmcache_update_vgid(info, info->vginfo, vgid) || !_lvmcache_update_vgstatus(info, vgstatus, creation_host)) return_0; @@ -1036,7 +1065,7 @@ static void _lvmcache_destroy_lockname(struct dm_hash_node *n) dm_hash_get_key(_lock_hash, n)); } -void lvmcache_destroy(void) +void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans) { struct dm_hash_node *n; log_verbose("Wiping internal VG cache"); @@ -1069,4 +1098,7 @@ void lvmcache_destroy(void) } list_init(&_vginfos); + + if (retain_orphans) + init_lvmcache_orphans(cmd); } diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 7a61b9b1..0a36b4d7 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -63,7 +63,7 @@ struct lvmcache_info { }; int lvmcache_init(void); -void lvmcache_destroy(void); +void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans); /* Set full_scan to 1 to reread every filtered device label or * 2 to rescan /dev for new devices */ @@ -74,6 +74,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, struct device *dev, const char *vgname, const char *vgid, uint32_t vgstatus); +int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt); void lvmcache_del(struct lvmcache_info *info); /* Update things */ diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 280ea133..aa064726 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -721,6 +721,17 @@ static int _init_formats(struct cmd_context *cmd) return 0; } +int init_lvmcache_orphans(struct cmd_context *cmd) +{ + struct format_type *fmt; + + list_iterate_items(fmt, &cmd->formats) + if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt)) + return_0; + + return 1; +} + static int _init_segtypes(struct cmd_context *cmd) { struct segment_type *segtype; @@ -981,6 +992,9 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, if (!_init_formats(cmd)) goto error; + if (!init_lvmcache_orphans(cmd)) + goto error; + if (!_init_segtypes(cmd)) goto error; @@ -1044,7 +1058,7 @@ int refresh_toolcontext(struct cmd_context *cmd) */ activation_release(); - lvmcache_destroy(); + lvmcache_destroy(cmd, 0); label_exit(); _destroy_segtypes(&cmd->segtypes); _destroy_formats(&cmd->formats); @@ -1086,6 +1100,9 @@ int refresh_toolcontext(struct cmd_context *cmd) if (!_init_formats(cmd)) return 0; + if (!init_lvmcache_orphans(cmd)) + return 0; + if (!_init_segtypes(cmd)) return 0; @@ -1107,7 +1124,7 @@ void destroy_toolcontext(struct cmd_context *cmd) archive_exit(cmd); backup_exit(cmd); - lvmcache_destroy(); + lvmcache_destroy(cmd, 0); label_exit(); _destroy_segtypes(&cmd->segtypes); _destroy_formats(&cmd->formats); diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index d3f061ae..f2992034 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -95,5 +95,6 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, void destroy_toolcontext(struct cmd_context *cmd); int refresh_toolcontext(struct cmd_context *cmd); int config_files_changed(struct cmd_context *cmd); +int init_lvmcache_orphans(struct cmd_context *cmd); #endif diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c index 9cd8f5d4..9482bf96 100644 --- a/lib/format_pool/format_pool.c +++ b/lib/format_pool/format_pool.c @@ -24,8 +24,6 @@ #include "format_pool.h" #include "pool_label.h" -#define FMT_POOL_NAME "pool" - /* Must be called after pvs are imported */ static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem, int *sps) @@ -316,7 +314,7 @@ struct format_type *init_format(struct cmd_context *cmd) fmt->ops = &_format_pool_ops; fmt->name = FMT_POOL_NAME; fmt->alias = NULL; - fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_POOL_NAME); + fmt->orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME; fmt->features = 0; fmt->private = NULL; diff --git a/lib/format_pool/format_pool.h b/lib/format_pool/format_pool.h index 3325c681..0d4b9735 100644 --- a/lib/format_pool/format_pool.h +++ b/lib/format_pool/format_pool.h @@ -18,6 +18,9 @@ #include "metadata.h" +#define FMT_POOL_NAME "pool" +#define FMT_POOL_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_POOL_NAME) + #ifdef POOL_INTERNAL struct format_type *init_pool_format(struct cmd_context *cmd); #endif diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 2f37157a..cecbcbd2 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -692,6 +692,10 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)), return 1; } +/* + * Separate metadata areas after splitting a VG. + * Also accepts orphan VG as destination (for vgreduce). + */ int vg_split_mdas(struct cmd_context *cmd __attribute((unused)), struct volume_group *vg_from, struct volume_group *vg_to) { @@ -708,11 +712,16 @@ int vg_split_mdas(struct cmd_context *cmd __attribute((unused)), continue; } - if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) - list_move(&mda->list, mdas_to); + if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) { + if (is_orphan_vg(vg_to->name)) + list_del(&mda->list); + else + list_move(&mda->list, mdas_to); + } } - if (list_empty(mdas_from) || list_empty(mdas_to)) + if (list_empty(mdas_from) || + (!is_orphan_vg(vg_to->name) && list_empty(mdas_to))) return common_mda; return 1; @@ -1366,6 +1375,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd, struct volume_group *vg; struct physical_volume *pv; + lvmcache_label_scan(cmd, 0); + if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL))) return_NULL; diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 95dbae03..bb3fdaec 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -938,7 +938,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) out: if (test_mode()) { log_verbose("Test mode: Wiping internal cache"); - lvmcache_destroy(); + lvmcache_destroy(cmd, 1); } if (cmd->cft_override) { diff --git a/tools/pvcreate.c b/tools/pvcreate.c index 1a5baef0..5661e2ee 100644 --- a/tools/pvcreate.c +++ b/tools/pvcreate.c @@ -81,7 +81,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name) unlock_vg(cmd, VG_ORPHANS); persistent_filter_wipe(cmd->filter); - lvmcache_destroy(); + lvmcache_destroy(cmd, 1); init_md_filtering(0); if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { diff --git a/tools/pvscan.c b/tools/pvscan.c index bbe606c1..519720fc 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -130,7 +130,7 @@ int pvscan(struct cmd_context *cmd, int argc __attribute((unused)), } persistent_filter_wipe(cmd->filter); - lvmcache_destroy(); + lvmcache_destroy(cmd, 1); log_verbose("Walking through all physical volumes"); if (!(pvslist = get_pvs(cmd))) { diff --git a/tools/vgreduce.c b/tools/vgreduce.c index ccda5d96..5e613824 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -353,6 +353,8 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, void *handle __attribute((unused))) { struct pv_list *pvl; + struct volume_group *orphan_vg; + int consistent = 1; const char *name = pv_dev_name(pv); if (pv_pe_alloc_count(pv)) { @@ -366,10 +368,17 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, return ECMD_FAILED; } + if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE | LCK_NONBLOCK)) { + log_error("Can't get lock for orphan PVs"); + return ECMD_FAILED; + } + pvl = find_pv_in_vg(vg, name); - if (!archive(vg)) + if (!archive(vg)) { + unlock_vg(cmd, VG_ORPHANS); return ECMD_FAILED; + } log_verbose("Removing \"%s\" from volume group \"%s\"", name, vg->name); @@ -381,6 +390,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, if (!dev_get_size(pv_dev(pv), &pv->size)) { log_error("%s: Couldn't get size.", pv_dev_name(pv)); + unlock_vg(cmd, VG_ORPHANS); return ECMD_FAILED; } @@ -388,9 +398,24 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, vg->free_count -= pv_pe_count(pv) - pv_pe_alloc_count(pv); vg->extent_count -= pv_pe_count(pv); + if(!(orphan_vg = vg_read(cmd, vg->fid->fmt->orphan_vg_name, NULL, &consistent)) || + !consistent) { + log_error("Unable to read existing orphan PVs"); + unlock_vg(cmd, VG_ORPHANS); + return ECMD_FAILED; + } + + if (!vg_split_mdas(cmd, vg, orphan_vg) || !vg->pv_count) { + log_error("Cannot remove final metadata area on \"%s\" from \"%s\"", + name, vg->name); + unlock_vg(cmd, VG_ORPHANS); + return ECMD_FAILED; + } + if (!vg_write(vg) || !vg_commit(vg)) { log_error("Removal of physical volume \"%s\" from " "\"%s\" failed", name, vg->name); + unlock_vg(cmd, VG_ORPHANS); return ECMD_FAILED; } @@ -398,9 +423,11 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg, log_error("Failed to clear metadata from physical " "volume \"%s\" " "after removal from \"%s\"", name, vg->name); + unlock_vg(cmd, VG_ORPHANS); return ECMD_FAILED; } + unlock_vg(cmd, VG_ORPHANS); backup(vg); log_print("Removed \"%s\" from volume group \"%s\"", name, vg->name); diff --git a/tools/vgrename.c b/tools/vgrename.c index 6cdfaf2a..03acbee0 100644 --- a/tools/vgrename.c +++ b/tools/vgrename.c @@ -151,7 +151,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path, /* FIXME lvmcache corruption - vginfo duplicated instead of renamed */ persistent_filter_wipe(cmd->filter); - lvmcache_destroy(); + lvmcache_destroy(cmd, 1); return 1; diff --git a/tools/vgscan.c b/tools/vgscan.c index e444e8d0..3a0258c2 100644 --- a/tools/vgscan.c +++ b/tools/vgscan.c @@ -57,7 +57,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv) } persistent_filter_wipe(cmd->filter); - lvmcache_destroy(); + lvmcache_destroy(cmd, 1); log_print("Reading all physical volumes. This may take a while..."); |