mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
thin: add pool metadata spare lv support
Add support for pool's metadata spare volume.
This commit is contained in:
parent
08df7ba844
commit
460d0254eb
@ -1,5 +1,6 @@
|
||||
Version 2.02.99 -
|
||||
===================================
|
||||
Add support for poolmetadataspare LV, that will be used for pool recovery.
|
||||
Improve activation order when creating thin pools in non-clustered VG.
|
||||
List thin-pool and thin modules for thin volumes.
|
||||
Correct thin creation error paths.
|
||||
|
@ -61,6 +61,7 @@ static const struct flag _lv_flags[] = {
|
||||
{LV_REBUILD, "REBUILD", STATUS_FLAG},
|
||||
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
||||
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
||||
{POOL_METADATA_SPARE, NULL, 0},
|
||||
{RAID, NULL, 0},
|
||||
{RAID_META, NULL, 0},
|
||||
{RAID_IMAGE, NULL, 0},
|
||||
|
@ -617,6 +617,18 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
|
||||
if (timestamp && !lv_set_creation(lv, hostname, timestamp))
|
||||
return_0;
|
||||
|
||||
if (!lv_is_visible(lv) && strstr(lv->name, "_pmspare")) {
|
||||
if (vg->pool_metadata_spare_lv) {
|
||||
log_error("Couldn't use another pool metadata spare "
|
||||
"logical volume %s/%s.", vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
log_debug_metadata("Logical volume %s is pool metadata spare.",
|
||||
lv->name);
|
||||
lv->status |= POOL_METADATA_SPARE;
|
||||
vg->pool_metadata_spare_lv = lv;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -97,10 +97,11 @@
|
||||
#define THIN_POOL UINT64_C(0x0000002000000000) /* LV */
|
||||
#define THIN_POOL_DATA UINT64_C(0x0000004000000000) /* LV */
|
||||
#define THIN_POOL_METADATA UINT64_C(0x0000008000000000) /* LV */
|
||||
#define POOL_METADATA_SPARE UINT64_C(0x0000010000000000) /* LV internal */
|
||||
|
||||
#define LV_WRITEMOSTLY UINT64_C(0x0000010000000000) /* LV (RAID1) */
|
||||
#define LV_WRITEMOSTLY UINT64_C(0x0000020000000000) /* LV (RAID1) */
|
||||
|
||||
#define LV_ACTIVATION_SKIP UINT64_C(0x0000020000000000) /* LV */
|
||||
#define LV_ACTIVATION_SKIP UINT64_C(0x0000040000000000) /* LV */
|
||||
|
||||
/* Format features flags */
|
||||
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
|
||||
@ -160,6 +161,7 @@
|
||||
#define lv_is_raid_type(lv) (((lv)->status & (RAID | RAID_IMAGE | RAID_META)) ? 1 : 0)
|
||||
|
||||
#define lv_is_virtual(lv) (((lv)->status & VIRTUAL) ? 1 : 0)
|
||||
#define lv_is_pool_metadata_spare(lv) (((lv)->status & POOL_METADATA_SPARE) ? 1 : 0)
|
||||
|
||||
/* Ordered list - see lv_manip.c */
|
||||
typedef enum {
|
||||
@ -665,6 +667,8 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
|
||||
uint32_t stripes, uint32_t stripe_size,
|
||||
uint64_t size, alloc_policy_t alloc,
|
||||
struct dm_list *pvh);
|
||||
int vg_set_pool_metadata_spare(struct logical_volume *lv);
|
||||
int vg_remove_pool_metadata_spare(struct volume_group *vg);
|
||||
|
||||
int attach_thin_external_origin(struct lv_segment *seg,
|
||||
struct logical_volume *external_lv);
|
||||
|
@ -2293,6 +2293,7 @@ int vg_validate(struct volume_group *vg)
|
||||
unsigned hidden_lv_count = 0, lv_count = 0, lv_visible_count = 0;
|
||||
unsigned pv_count = 0;
|
||||
unsigned num_snapshots = 0;
|
||||
unsigned spare_count = 0;
|
||||
struct validate_hash vhash = { NULL };
|
||||
|
||||
if (vg->alloc == ALLOC_CLING_BY_TAGS) {
|
||||
@ -2472,6 +2473,19 @@ int vg_validate(struct volume_group *vg)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (lv_is_pool_metadata_spare(lvl->lv)) {
|
||||
if (++spare_count > 1) {
|
||||
log_error(INTERNAL_ERROR "LV %s is %u. pool metadata spare (>1).",
|
||||
lvl->lv->name, spare_count);
|
||||
r = 0;
|
||||
}
|
||||
if (vg->pool_metadata_spare_lv != lvl->lv) {
|
||||
log_error(INTERNAL_ERROR "LV %s is not vg pool metadata spare.",
|
||||
lvl->lv->name);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_lv_segments(lvl->lv, 1)) {
|
||||
log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
|
||||
lvl->lv->name);
|
||||
@ -2524,6 +2538,13 @@ int vg_validate(struct volume_group *vg)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (vg->pool_metadata_spare_lv &&
|
||||
!lv_is_pool_metadata_spare(vg->pool_metadata_spare_lv)) {
|
||||
log_error(INTERNAL_ERROR "VG references non pool metadata spare LV %s.",
|
||||
vg->pool_metadata_spare_lv->name);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (vg_max_lv_reached(vg))
|
||||
stack;
|
||||
out:
|
||||
|
@ -727,3 +727,75 @@ struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
|
||||
|
||||
return metadata_lv;
|
||||
}
|
||||
|
||||
int vg_set_pool_metadata_spare(struct logical_volume *lv)
|
||||
{
|
||||
char new_name[NAME_LEN];
|
||||
struct volume_group *vg = lv->vg;
|
||||
|
||||
if (vg->pool_metadata_spare_lv) {
|
||||
if (vg->pool_metadata_spare_lv == lv)
|
||||
return 1;
|
||||
if (!vg_remove_pool_metadata_spare(vg))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(new_name, sizeof(new_name), "%s_pmspare", lv->name) < 0) {
|
||||
log_error("Can't create pool metadata spare. Name of pool LV "
|
||||
"%s is too long.", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_rename_update(vg->cmd, lv, new_name, 0))
|
||||
return_0;
|
||||
|
||||
lv_set_hidden(lv);
|
||||
lv->status |= POOL_METADATA_SPARE;
|
||||
vg->pool_metadata_spare_lv = lv;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vg_remove_pool_metadata_spare(struct volume_group *vg)
|
||||
{
|
||||
char new_name[NAME_LEN];
|
||||
char *c;
|
||||
|
||||
struct logical_volume *lv = vg->pool_metadata_spare_lv;
|
||||
|
||||
if (!(lv->status & POOL_METADATA_SPARE)) {
|
||||
log_error(INTERNAL_ERROR "LV %s is not pool metadata spare.",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vg->pool_metadata_spare_lv = NULL;
|
||||
lv->status &= ~POOL_METADATA_SPARE;
|
||||
lv_set_visible(lv);
|
||||
|
||||
/* Cut off suffix _pmspare */
|
||||
(void) dm_strncpy(new_name, lv->name, sizeof(new_name));
|
||||
if (!(c = strchr(new_name, '_'))) {
|
||||
log_error(INTERNAL_ERROR "LV %s has no suffix for pool metadata spare.",
|
||||
new_name);
|
||||
return 0;
|
||||
}
|
||||
*c = 0;
|
||||
|
||||
/* If the name is in use, generate new lvol%d */
|
||||
if (find_lv_in_vg(vg, new_name) &&
|
||||
!generate_lv_name(vg, "lvol%d", new_name, sizeof(new_name))) {
|
||||
log_error("Failed to generate unique name for "
|
||||
"pool metadata spare logical volume.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print_unless_silent("Renaming existing pool metadata spare "
|
||||
"logical volume \"%s/%s\" to \"%s/%s\".",
|
||||
vg->name, lv->name, vg->name, new_name);
|
||||
|
||||
if (!lv_rename_update(vg->cmd, lv, new_name, 0))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -20,6 +20,7 @@ struct dm_pool;
|
||||
struct format_instance;
|
||||
struct dm_list;
|
||||
struct id;
|
||||
struct logical_volume;
|
||||
|
||||
typedef enum {
|
||||
ALLOC_INVALID,
|
||||
@ -121,6 +122,7 @@ struct volume_group {
|
||||
uint32_t mda_copies; /* target number of mdas for this VG */
|
||||
|
||||
struct dm_hash_table *hostnames; /* map of creation hostnames */
|
||||
struct logical_volume *pool_metadata_spare_lv; /* one per VG */
|
||||
};
|
||||
|
||||
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
|
||||
|
@ -105,6 +105,7 @@ int apply_lvname_restrictions(const char *name)
|
||||
static const char * const _reserved_strings[] = {
|
||||
"_mlog",
|
||||
"_mimage",
|
||||
"_pmspare",
|
||||
"_rimage",
|
||||
"_rmeta",
|
||||
"_vorigin",
|
||||
|
@ -74,6 +74,7 @@ arg(originname_ARG, '\0', "originname", string_arg, 0)
|
||||
arg(poll_ARG, '\0', "poll", yes_no_arg, 0)
|
||||
arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0)
|
||||
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0)
|
||||
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", yes_no_arg, 0)
|
||||
arg(discards_ARG, '\0', "discards", discards_arg, 0)
|
||||
arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE)
|
||||
arg(stripes_long_ARG, '\0', "stripes", int_arg, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user