From 69098210beafaecd012ee431df725667e0e28687 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 3 Jun 2005 14:49:51 +0000 Subject: [PATCH] Always insert an intermediate layer for mirrors. Suppress hidden LVs from reports unless --all is given. Use square brackets for hidden LVs in reports. Centralise restrictions on LV names. --- WHATS_NEW | 4 ++ lib/activate/activate.c | 1 - lib/format_text/flags.c | 1 + lib/format_text/import_vsn1.c | 6 ++- lib/format_text/text_import.h | 3 +- lib/metadata/lv_alloc.h | 11 ++++- lib/metadata/lv_manip.c | 75 +++++++++++++++++++++++++++++++---- lib/metadata/metadata.h | 14 ++++++- lib/metadata/mirror.c | 66 +++++++++++++++++++++++++++++- lib/metadata/snapshot_manip.c | 2 +- lib/mirror/mirrored.c | 2 +- lib/report/columns.h | 2 +- lib/report/report.c | 35 ++++++++++++++++ lib/striped/striped.c | 2 +- tools/commands.h | 23 ++++++----- tools/lvchange.c | 13 +++++- tools/lvcreate.c | 54 ++++++++++++++++++++----- tools/lvdisplay.c | 3 ++ tools/lvremove.c | 6 +++ tools/lvrename.c | 6 +-- tools/pvmove.c | 2 +- tools/reporter.c | 6 +++ tools/toollib.c | 30 ++++++++++++++ tools/toollib.h | 2 + 24 files changed, 325 insertions(+), 44 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 6ac23cf9a..42fbf4e14 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,9 @@ Version 2.01.11 - ============================== + Centralise restrictions on LV names. + Always insert an intermediate layer for mirrors. + Suppress hidden LVs from reports unless --all is given. + Use square brackets for hidden LVs in reports. Allow the creation of mirrors with contiguous extents. Always perform sanity checks against metadata before committing it to disk. Split lv_extend into two steps: choosing extents + allocation to LV(s). diff --git a/lib/activate/activate.c b/lib/activate/activate.c index ef265d73f..2ee46b92f 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -534,7 +534,6 @@ int lvs_in_vg_activated(struct volume_group *vg) int lvs_in_vg_opened(struct volume_group *vg) { struct lv_list *lvl; - struct logical_volume *lv; int count = 0; if (!activation()) diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c index 2acd17068..0e7292a14 100644 --- a/lib/format_text/flags.c +++ b/lib/format_text/flags.c @@ -52,6 +52,7 @@ static struct flag _lv_flags[] = { {VISIBLE_LV, "VISIBLE"}, {PVMOVE, "PVMOVE"}, {LOCKED, "LOCKED"}, + {MIRROR_IMAGE, NULL}, {MIRROR_LOG, NULL}, {MIRRORED, NULL}, {VIRTUAL, NULL}, diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 5da5fc6d3..3202a4136 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -323,7 +323,8 @@ static int _read_segment(struct pool *mem, struct volume_group *vg, } int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct hash_table *pv_hash) + const struct config_node *cn, struct hash_table *pv_hash, + uint32_t flags) { unsigned int s; struct config_value *cv; @@ -368,7 +369,8 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn, */ seg->lv->vg->free_count -= seg->area_len; } else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) { - set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i); + set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i, + flags); } else { log_error("Couldn't find volume '%s' " "for segment '%s'.", diff --git a/lib/format_text/text_import.h b/lib/format_text/text_import.h index c6b8c717d..0f09c0aaa 100644 --- a/lib/format_text/text_import.h +++ b/lib/format_text/text_import.h @@ -20,6 +20,7 @@ struct lv_segment; struct config_node; int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct hash_table *pv_hash); + const struct config_node *cn, struct hash_table *pv_hash, + uint32_t flags); #endif diff --git a/lib/metadata/lv_alloc.h b/lib/metadata/lv_alloc.h index cb0a5a4bb..ab7c83d9d 100644 --- a/lib/metadata/lv_alloc.h +++ b/lib/metadata/lv_alloc.h @@ -35,7 +35,8 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv, int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num, struct physical_volume *pv, uint32_t pe); void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num, - struct logical_volume *lv, uint32_t le); + struct logical_volume *lv, uint32_t le, + uint32_t flags); struct alloc_handle; struct alloc_handle *allocate_extents(struct volume_group *vg, @@ -64,6 +65,14 @@ int lv_add_segment(struct alloc_handle *ah, int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv); int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status, uint32_t extents, struct segment_type *segtype); +int lv_add_mirror_segment(struct alloc_handle *ah, + struct logical_volume *lv, + struct logical_volume **sub_lvs, + uint32_t mirrors, + struct segment_type *segtype, + uint32_t status, + uint32_t region_size, + struct logical_volume *log_lv); void alloc_destroy(struct alloc_handle *ah); diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 47bd3c9fc..72af7c90e 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -74,6 +74,11 @@ struct lv_segment *alloc_lv_segment(struct pool *mem, return NULL; } + if (!segtype) { + log_error("alloc_lv_segment: Missing segtype."); + return NULL; + } + seg->segtype = segtype; seg->lv = lv; seg->le = le; @@ -142,11 +147,13 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num, * Link one LV segment to another. Assumes sizes already match. */ void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num, - struct logical_volume *lv, uint32_t le) + struct logical_volume *lv, uint32_t le, + uint32_t flags) { seg->area[area_num].type = AREA_LV; seg_lv(seg, area_num) = lv; seg_le(seg, area_num) = le; + lv->status |= flags; } /* @@ -170,12 +177,12 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction) seg->len -= reduction; seg->area_len -= area_reduction; - seg->lv->vg->free_count += area_reduction * seg->area_count; for (s = 0; s < seg->area_count; s++) { if (seg_type(seg, s) != AREA_PV) continue; release_pv_segment(seg_pvseg(seg, s), area_reduction); + seg->lv->vg->free_count += area_reduction; } return 1; @@ -271,6 +278,7 @@ struct alloc_handle { uint32_t area_count; /* Number of parallel areas */ uint32_t area_multiple; /* seg->len = area_len * area_multiple */ uint32_t log_count; /* Number of parallel 1-extent logs */ + uint32_t total_area_len; /* Total number of parallel extents */ struct alloced_area log_area; /* Extent used for log */ struct list alloced_areas[0]; /* Lists of areas in each stripe */ @@ -465,6 +473,8 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed, list_add(&ah->alloced_areas[s], &aa[s].list); } + ah->total_area_len += area_len; + for (s = 0; s < ah->area_count; s++) consume_pv_area(areas[s], area_len); @@ -831,6 +841,11 @@ int lv_add_segment(struct alloc_handle *ah, uint32_t region_size, struct logical_volume *log_lv) { + if (!segtype) { + log_error("Missing segtype in lv_add_segment()."); + return 0; + } + if (segtype_is_virtual(segtype)) { log_error("lv_add_segment cannot handle virtual segments"); return 0; @@ -901,6 +916,53 @@ int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv) return 1; } +/* + * Add a mirror segment + */ +int lv_add_mirror_segment(struct alloc_handle *ah, + struct logical_volume *lv, + struct logical_volume **sub_lvs, + uint32_t mirrors, + struct segment_type *segtype, + uint32_t status, + uint32_t region_size, + struct logical_volume *log_lv) +{ + struct lv_segment *seg; + uint32_t m; + + if (list_empty(&log_lv->segments)) { + log_error("Log LV %s is empty.", log_lv->name); + return 0; + } + + if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, + get_segtype_from_string(lv->vg->cmd, + "mirror"), + lv, lv->le_count, ah->total_area_len, 0, + 0, log_lv, mirrors, ah->total_area_len, 0, + region_size, 0))) { + log_error("Couldn't allocate new mirror segment."); + return 0; + } + + for (m = 0; m < mirrors; m++) + set_lv_segment_area_lv(seg, m, sub_lvs[m], 0, MIRROR_IMAGE); + + list_add(&lv->segments, &seg->list); + lv->le_count += ah->total_area_len; + lv->size += (uint64_t) lv->le_count *lv->vg->extent_size; + + if (lv->vg->fid->fmt->ops->lv_setup && + !lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv)) { + stack; + return 0; + } + + return 1; +} + + /* * Entry point for single-step LV allocation + extension. */ @@ -936,8 +998,8 @@ int lv_extend(struct logical_volume *lv, return r; } -static char *_generate_lv_name(struct volume_group *vg, const char *format, - char *buffer, size_t len) +char *generate_lv_name(struct volume_group *vg, const char *format, + char *buffer, size_t len) { struct lv_list *lvl; int high = -1, i; @@ -961,7 +1023,6 @@ static char *_generate_lv_name(struct volume_group *vg, const char *format, */ struct logical_volume *lv_create_empty(struct format_instance *fi, const char *name, - const char *name_format, union lvid *lvid, uint32_t status, alloc_policy_t alloc, @@ -979,8 +1040,8 @@ struct logical_volume *lv_create_empty(struct format_instance *fi, return NULL; } - if (!name && !(name = _generate_lv_name(vg, name_format, dname, - sizeof(dname)))) { + if (strstr(name, "%d") && + !(name = generate_lv_name(vg, name, dname, sizeof(dname)))) { log_error("Failed to generate unique name for the new " "logical volume"); return NULL; diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index a5914dcf7..93dd1fe5d 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -56,6 +56,7 @@ #define MIRRORED 0x00008000 /* LV - internal use only */ #define VIRTUAL 0x00010000 /* LV - internal use only */ #define MIRROR_LOG 0x00020000 /* LV */ +#define MIRROR_IMAGE 0x00040000 /* LV */ #define LVM_READ 0x00000100 /* LV VG */ #define LVM_WRITE 0x00000200 /* LV VG */ @@ -436,7 +437,6 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg, /* Manipulate LVs */ struct logical_volume *lv_create_empty(struct format_instance *fi, const char *name, - const char *name_format, union lvid *lvid, uint32_t status, alloc_policy_t alloc, @@ -534,9 +534,19 @@ int vg_add_snapshot(struct format_instance *fid, const char *name, int vg_remove_snapshot(struct logical_volume *cow); + /* * Mirroring functions */ +struct alloc_handle; +int create_mirror_layers(struct alloc_handle *ah, + uint32_t first_area, + uint32_t num_mirrors, + struct logical_volume *lv, + struct segment_type *segtype, + uint32_t status, + uint32_t region_size, + struct logical_volume *log_lv); int insert_pvmove_mirrors(struct cmd_context *cmd, struct logical_volume *lv_mirr, struct list *source_pvl, @@ -559,6 +569,8 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg, struct logical_volume *lv); uint32_t find_free_lvnum(struct logical_volume *lv); +char *generate_lv_name(struct volume_group *vg, const char *format, + char *buffer, size_t len); static inline int validate_name(const char *n) { diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c index 7bdaf2c4c..9a0a8a14d 100644 --- a/lib/metadata/mirror.c +++ b/lib/metadata/mirror.c @@ -20,6 +20,70 @@ #include "display.h" #include "activate.h" #include "lv_alloc.h" +#include "lvm-string.h" + +int create_mirror_layers(struct alloc_handle *ah, + uint32_t first_area, + uint32_t num_mirrors, + struct logical_volume *lv, + struct segment_type *segtype, + uint32_t status, + uint32_t region_size, + struct logical_volume *log_lv) +{ + uint32_t m; + struct logical_volume **img_lvs; + char *img_name; + size_t len; + + if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) { + log_error("img_lvs allocation failed. " + "Remove new LV and retry."); + return 0; + } + + len = strlen(lv->name) + 32; + if (!(img_name = alloca(len))) { + log_error("img_name allocation failed. " + "Remove new LV and retry."); + return 0; + } + + if (lvm_snprintf(img_name, len, "%s_mimage_%%d", lv->name) < 0) { + log_error("img_name allocation failed. " + "Remove new LV and retry."); + return 0; + } + + for (m = 0; m < num_mirrors; m++) { + if (!(img_lvs[m] = lv_create_empty(lv->vg->fid, img_name, + NULL, LVM_READ | LVM_WRITE, + ALLOC_INHERIT, 0, lv->vg))) {\ + log_error("Aborting. Failed to create submirror LV. " + "Remove new LV and retry."); + return 0; + } + + if (!lv_add_segment(ah, m, 1, img_lvs[m], + get_segtype_from_string(lv->vg->cmd, + "striped"), + 0, NULL, 0, 0, 0, NULL)) { + log_error("Aborting. Failed to add submirror segment " + "to %s. Remove new LV and retry.", + img_lvs[m]->name); + return 0; + } + } + + if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype, + 0, region_size, log_lv)) { + log_error("Aborting. Failed to add mirror segment. " + "Remove new LV and retry."); + return 0; + } + + return 1; +} /* * Replace any LV segments on given PV with temporary mirror. @@ -153,7 +217,7 @@ int insert_pvmove_mirrors(struct cmd_context *cmd, "temporary LV for pvmove."); return 0; } - set_lv_segment_area_lv(seg, s, lv_mirr, start_le); + set_lv_segment_area_lv(seg, s, lv_mirr, start_le, 0); extent_count += seg->area_len; diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c index 266b3d401..a2536f50f 100644 --- a/lib/metadata/snapshot_manip.c +++ b/lib/metadata/snapshot_manip.c @@ -50,7 +50,7 @@ int vg_add_snapshot(struct format_instance *fid, const char *name, return 0; } - if (!(snap = lv_create_empty(fid, name, name ? NULL : "snapshot%d", + if (!(snap = lv_create_empty(fid, name ? name : "snapshot%d", lvid, LVM_READ | LVM_WRITE | VISIBLE_LV, ALLOC_INHERIT, 1, origin->vg))) { stack; diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c index 3fe7992d1..67f97dd7d 100644 --- a/lib/mirror/mirrored.c +++ b/lib/mirror/mirrored.c @@ -129,7 +129,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn, return 0; } - return text_import_areas(seg, sn, cn, pv_hash); + return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE); } static int _text_export(const struct lv_segment *seg, struct formatter *f) diff --git a/lib/report/columns.h b/lib/report/columns.h index ef86d34bd..a7a1298d9 100644 --- a/lib/report/columns.h +++ b/lib/report/columns.h @@ -19,7 +19,7 @@ /* *INDENT-OFF* */ FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid") -FIELD(LVS, lv, STR, "LV", name, 4, string, "lv_name") +FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name") FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr") FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major") FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor") diff --git a/lib/report/report.c b/lib/report/report.c index c947d7229..8f16e9f15 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -337,6 +337,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field, repstr[0] = 'p'; else if (lv->status & MIRRORED) repstr[0] = 'm'; + else if (lv->status & MIRROR_IMAGE) + repstr[0] = 'i'; else if (lv->status & MIRROR_LOG) repstr[0] = 'l'; else if (lv->status & VIRTUAL) @@ -510,6 +512,39 @@ static int _loglv_disp(struct report_handle *rh, struct field *field, return 1; } +static int _lvname_disp(struct report_handle *rh, struct field *field, + const void *data) +{ + const struct logical_volume *lv = (const struct logical_volume *) data; + char *repstr; + size_t len; + + if (lv->status & VISIBLE_LV) { + repstr = lv->name; + return _string_disp(rh, field, &repstr); + } + + len = strlen(lv->name) + 3; + if (!(repstr = pool_zalloc(rh->mem, len))) { + log_error("pool_alloc failed"); + return 0; + } + + if (lvm_snprintf(repstr, len, "[%s]", lv->name) < 0) { + log_error("lvname snprintf failed"); + return 0; + } + + field->report_string = repstr; + + if (!(field->sort_value = pool_strdup(rh->mem, lv->name))) { + log_error("pool_strdup failed"); + return 0; + } + + return 1; +} + static int _movepv_disp(struct report_handle *rh, struct field *field, const void *data) { diff --git a/lib/striped/striped.c b/lib/striped/striped.c index a6c1be90a..c0042a801 100644 --- a/lib/striped/striped.c +++ b/lib/striped/striped.c @@ -82,7 +82,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn, seg->area_len /= seg->area_count; - return text_import_areas(seg, sn, cn, pv_hash); + return text_import_areas(seg, sn, cn, pv_hash, 0); } static int _text_export(const struct lv_segment *seg, struct formatter *f) diff --git a/tools/commands.h b/tools/commands.h index 46ac265ed..6b2246494 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -131,6 +131,7 @@ xx(lvcreate, xx(lvdisplay, "Display information about a logical volume", "lvdisplay\n" + "\t[-a|--all]\n" "\t[-c|--colon]\n" "\t[-d|--debug]\n" "\t[-h|--help]\n" @@ -145,6 +146,7 @@ xx(lvdisplay, "\n" "lvdisplay --columns|-C\n" "\t[--aligned]\n" + "\t[-a|--all]\n" "\t[-d|--debug]\n" "\t[-h|--help]\n" "\t[--ignorelockingfailure]\n" @@ -161,9 +163,10 @@ xx(lvdisplay, "\t[--version]" "\n" "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n", - aligned_ARG, colon_ARG, columns_ARG, disk_ARG, ignorelockingfailure_ARG, - maps_ARG, noheadings_ARG, nosuffix_ARG, options_ARG, sort_ARG, - partial_ARG, segments_ARG, separator_ARG, unbuffered_ARG, units_ARG) + aligned_ARG, all_ARG, colon_ARG, columns_ARG, disk_ARG, + ignorelockingfailure_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG, + options_ARG, sort_ARG, partial_ARG, segments_ARG, separator_ARG, + unbuffered_ARG, units_ARG) xx(lvextend, "Add space to a logical volume", @@ -300,6 +303,7 @@ xx(lvresize, xx(lvs, "Display information about logical volumes", "lvs" "\n" + "\t[-a|--all]\n" "\t[--aligned]\n" "\t[-d|--debug]\n" "\t[-h|--help]\n" @@ -317,9 +321,9 @@ xx(lvs, "\t[--version]" "\n" "\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n", - aligned_ARG, ignorelockingfailure_ARG, noheadings_ARG, nolocking_ARG, - nosuffix_ARG, options_ARG, partial_ARG, segments_ARG, separator_ARG, - sort_ARG, unbuffered_ARG, units_ARG) + aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG, + nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG, + separator_ARG, sort_ARG, unbuffered_ARG, units_ARG) xx(lvscan, "List all logical volumes in all volume groups", @@ -775,6 +779,7 @@ xx(vgs, "Display information about volume groups", "vgs" "\n" "\t[--aligned]\n" + "\t[-a|--all]\n" "\t[-d|--debug]\n" "\t[-h|--help]\n" "\t[--ignorelockingfailure]\n" @@ -790,9 +795,9 @@ xx(vgs, "\t[--version]\n" "\t[VolumeGroupName [VolumeGroupName...]]\n", - aligned_ARG, ignorelockingfailure_ARG, noheadings_ARG, nolocking_ARG, - nosuffix_ARG, options_ARG, partial_ARG, separator_ARG, sort_ARG, - unbuffered_ARG, units_ARG) + aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG, + nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, separator_ARG, + sort_ARG, unbuffered_ARG, units_ARG) xx(vgscan, "Search for all volume groups", diff --git a/tools/lvchange.c b/tools/lvchange.c index 75251be2c..036ba6092 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -405,12 +405,23 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } - /* FIXME Test for VISIBLE instead? */ if (lv->status & MIRROR_LOG) { log_error("Unable to change mirror log LV %s directly", lv->name); return ECMD_FAILED; } + if (lv->status & MIRROR_IMAGE) { + log_error("Unable to change mirror image LV %s directly", + lv->name); + return ECMD_FAILED; + } + + if (!(lv->status & VISIBLE_LV)) { + log_error("Unable to change internal LV %s directly", + lv->name); + return ECMD_FAILED; + } + /* access permission change */ if (arg_count(cmd, permission_ARG)) { if (!archive(lv->vg)) diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 7bd361119..b495060ba 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -137,10 +137,8 @@ static int _read_name_params(struct lvcreate_params *lp, if ((ptr = strrchr(lp->lv_name, '/'))) lp->lv_name = ptr + 1; - /* FIXME Remove this restriction eventually */ - if (!strncmp(lp->lv_name, "snapshot", 8)) { - log_error("Names starting \"snapshot\" are reserved. " - "Please choose a different LV name."); + if (!apply_lvname_restrictions(lp->lv_name)) { + stack; return 0; } @@ -469,6 +467,9 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) const char *tag; int consistent = 1; struct alloc_handle *ah = NULL; + char *log_name, lv_name_buf[128]; + const char *lv_name; + size_t len; status |= lp->permission | VISIBLE_LV; @@ -597,6 +598,16 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) if (!archive(vg)) return 0; + if (lp->lv_name) + lv_name = lp->lv_name; + else { + if (!generate_lv_name(vg, "lvol%d", lv_name_buf, sizeof(lv_name_buf))) { + log_error("Failed to generate LV name."); + return 0; + } + lv_name = &lv_name_buf[0]; + } + if (lp->mirrors > 1) { /* FIXME Adjust lp->region_size if necessary */ region_max = (1 << (ffs(lp->extents) - 1)) * vg->extent_size; @@ -609,7 +620,29 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) /* FIXME Calculate how many extents needed for the log */ - if (!(log_lv = lv_create_empty(vg->fid, NULL, "mirrorlog%d", NULL, + len = strlen(lv_name) + 32; + if (!(log_name = alloca(len))) { + log_error("log_name allocation failed. " + "Remove new LV and retry."); + return 0; + } + + if (lvm_snprintf(log_name, len, "%s_mlog", lv_name) < 0) { + log_error("log_name allocation failed. " + "Remove new LV and retry."); + return 0; + } + + if (find_lv_in_vg(vg, log_name)) { + if (lvm_snprintf(log_name, len, "%s_mlog_%%d", + lv_name) < 0) { + log_error("log_name allocation failed. " + "Remove new LV and retry."); + return 0; + } + } + + if (!(log_lv = lv_create_empty(vg->fid, log_name, NULL, VISIBLE_LV | LVM_READ | LVM_WRITE, lp->alloc, 0, vg))) { stack; @@ -662,7 +695,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) log_lv->status &= ~VISIBLE_LV; } - if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL, + if (!(lv = lv_create_empty(vg->fid, lv_name ? lv_name : "lvol%d", NULL, status, lp->alloc, 0, vg))) { stack; goto error; @@ -701,11 +734,10 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) } if (lp->mirrors > 1) { - if (!lv_add_segment(ah, 0, lp->mirrors, lv, lp->segtype, - lp->stripe_size, NULL, 0, 0, - lp->region_size, log_lv)) { - log_error("Aborting. Failed to add mirror segment. " - "Remove new LV and retry."); + if (!create_mirror_layers(ah, 0, lp->mirrors, lv, + lp->segtype, 0, + lp->region_size, log_lv)) { + stack; goto error; } diff --git a/tools/lvdisplay.c b/tools/lvdisplay.c index c6dbfa71f..2b8c8a11a 100644 --- a/tools/lvdisplay.c +++ b/tools/lvdisplay.c @@ -18,6 +18,9 @@ static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { + if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV)) + return ECMD_PROCESSED; + if (arg_count(cmd, colon_ARG)) lvdisplay_colons(lv); else { diff --git a/tools/lvremove.c b/tools/lvremove.c index e5069a1fa..18cac809c 100644 --- a/tools/lvremove.c +++ b/tools/lvremove.c @@ -34,6 +34,12 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } + if (lv->status & MIRROR_IMAGE) { + log_error("Can't remove logical volume %s used by a mirror", + lv->name); + return ECMD_FAILED; + } + if (lv->status & MIRROR_LOG) { log_error("Can't remove logical volume %s used as mirror log", lv->name); diff --git a/tools/lvrename.c b/tools/lvrename.c index 34b44258a..bc042acbd 100644 --- a/tools/lvrename.c +++ b/tools/lvrename.c @@ -83,10 +83,8 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - /* FIXME Remove this restriction eventually */ - if (!strncmp(lv_name_new, "snapshot", 8)) { - log_error("Names starting \"snapshot\" are reserved. " - "Please choose a different LV name."); + if (!apply_lvname_restrictions(lv_name_new)) { + stack; return ECMD_FAILED; } diff --git a/tools/pvmove.c b/tools/pvmove.c index a23bd8c09..d8e18e789 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -140,7 +140,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd, struct lv_list *lvl; /* FIXME Cope with non-contiguous => splitting existing segments */ - if (!(lv_mirr = lv_create_empty(vg->fid, NULL, "pvmove%d", NULL, + if (!(lv_mirr = lv_create_empty(vg->fid, "pvmove%d", NULL, LVM_READ | LVM_WRITE, ALLOC_CONTIGUOUS, 0, vg))) { log_error("Creation of temporary pvmove LV failed"); diff --git a/tools/reporter.c b/tools/reporter.c index a3e633e92..2cc172ac6 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -35,6 +35,9 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name, static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { + if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV)) + return ECMD_PROCESSED; + if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL)) return ECMD_FAILED; @@ -78,6 +81,9 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg, static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { + if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV)) + return ECMD_PROCESSED; + return process_each_segment_in_lv(cmd, lv, handle, _segs_single); } diff --git a/tools/toollib.c b/tools/toollib.c index 4c7cf160b..a3098ac32 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -1012,3 +1012,33 @@ int exec_cmd(const char *command, const char *fscmd, const char *lv_path, return 1; } + +int apply_lvname_restrictions(const char *name) +{ + if (!strncmp(name, "snapshot", 8)) { + log_error("Names starting \"snapshot\" are reserved. " + "Please choose a different LV name."); + return 0; + } + + if (!strncmp(name, "pvmove", 6)) { + log_error("Names starting \"pvmove\" are reserved. " + "Please choose a different LV name."); + return 0; + } + + if (strstr(name, "_mlog")) { + log_error("Names including \"_mlog\" are reserved. " + "Please choose a different LV name."); + return 0; + } + + if (strstr(name, "_mimage")) { + log_error("Names including \"_mimage\" are reserved. " + "Please choose a different LV name."); + return 0; + } + + return 1; +} + diff --git a/tools/toollib.h b/tools/toollib.h index b0536baac..b47147482 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -90,4 +90,6 @@ struct list *clone_pv_list(struct pool *mem, struct list *pvs); int exec_cmd(const char *command, const char *fscmd, const char *lv_path, const char *size); +int apply_lvname_restrictions(const char *name); + #endif