summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WHATS_NEW4
-rw-r--r--lib/activate/activate.c1
-rw-r--r--lib/format_text/flags.c1
-rw-r--r--lib/format_text/import_vsn1.c6
-rw-r--r--lib/format_text/text_import.h3
-rw-r--r--lib/metadata/lv_alloc.h11
-rw-r--r--lib/metadata/lv_manip.c75
-rw-r--r--lib/metadata/metadata.h14
-rw-r--r--lib/metadata/mirror.c66
-rw-r--r--lib/metadata/snapshot_manip.c2
-rw-r--r--lib/mirror/mirrored.c2
-rw-r--r--lib/report/columns.h2
-rw-r--r--lib/report/report.c35
-rw-r--r--lib/striped/striped.c2
-rw-r--r--tools/commands.h23
-rw-r--r--tools/lvchange.c13
-rw-r--r--tools/lvcreate.c54
-rw-r--r--tools/lvdisplay.c3
-rw-r--r--tools/lvremove.c6
-rw-r--r--tools/lvrename.c6
-rw-r--r--tools/pvmove.c2
-rw-r--r--tools/reporter.c6
-rw-r--r--tools/toollib.c30
-rw-r--r--tools/toollib.h2
24 files changed, 325 insertions, 44 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 6ac23cf9..42fbf4e1 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 ef265d73..2ee46b92 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 2acd1706..0e7292a1 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 5da5fc6d..3202a413 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 c6b8c717..0f09c0aa 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 cb0a5a4b..ab7c83d9 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 47bd3c9f..72af7c90 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;
@@ -902,6 +917,53 @@ int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
}
/*
+ * 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.
*/
int lv_extend(struct logical_volume *lv,
@@ -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 a5914dcf..93dd1fe5 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 7bdaf2c4..9a0a8a14 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 266b3d40..a2536f50 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 3fe7992d..67f97dd7 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 ef86d34b..a7a1298d 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 c947d722..8f16e9f1 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 a6c1be90..c0042a80 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 46ac265e..6b224649 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 75251be2..036ba609 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 7bd36111..b495060b 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 c6dbfa71..2b8c8a11 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 e5069a1f..18cac809 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 34b44258..bc042acb 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 a23bd8c0..d8e18e78 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 a3e633e9..2cc172ac 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 4c7cf160..a3098ac3 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 b0536baa..b4714748 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