mirror of
git://sourceware.org/git/lvm2.git
synced 2026-02-10 08:32:46 +03:00
Compare commits
1 Commits
dev-dct-in
...
dev-dct-in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b3f34b39a |
@@ -105,6 +105,7 @@ static const struct flag _lv_flags[] = {
|
||||
{LV_VDO_POOL_DATA, NULL, 0},
|
||||
{WRITECACHE, NULL, 0},
|
||||
{INTEGRITY, NULL, 0},
|
||||
{INTEGRITY_METADATA, NULL, 0},
|
||||
{LV_PENDING_DELETE, NULL, 0}, /* FIXME Display like COMPATIBLE_FLAG */
|
||||
{LV_REMOVED, NULL, 0},
|
||||
{LV_UNCOMMITTED, NULL, 0},
|
||||
|
||||
@@ -156,6 +156,9 @@ static int _integrity_text_import(struct lv_segment *seg,
|
||||
seg->integrity_meta_dev = meta_lv;
|
||||
seg->lv->status |= INTEGRITY;
|
||||
|
||||
if (meta_lv)
|
||||
meta_lv->status |= INTEGRITY_METADATA;
|
||||
|
||||
if (meta_lv && !add_seg_to_segs_using_this_lv(meta_lv, seg))
|
||||
return_0;
|
||||
|
||||
|
||||
@@ -29,6 +29,19 @@
|
||||
|
||||
#define ONE_MB_IN_BYTES 1048576
|
||||
|
||||
int lv_is_integrity_origin(const struct logical_volume *lv)
|
||||
{
|
||||
struct seg_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
|
||||
if (!sl->seg || !sl->seg->lv || !sl->seg->origin)
|
||||
continue;
|
||||
if (lv_is_integrity(sl->seg->lv) && (sl->seg->origin == lv))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Every 500M of data needs 4M of metadata.
|
||||
* (From trial and error testing.)
|
||||
@@ -147,6 +160,49 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lv_remove_integrity(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
struct logical_volume *origin;
|
||||
struct logical_volume *meta_lv;
|
||||
|
||||
if (!seg_is_integrity(seg)) {
|
||||
log_error("LV %s segment is not integrity.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(meta_lv = seg->integrity_meta_dev)) {
|
||||
log_error("LV %s segment has no integrity metadata device.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(origin = seg_lv(seg, 0))) {
|
||||
log_error("LV %s integrity segment has no origin", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!remove_seg_from_segs_using_this_lv(seg->integrity_meta_dev, seg))
|
||||
return_0;
|
||||
|
||||
lv_set_visible(seg->integrity_meta_dev);
|
||||
|
||||
lv->status &= ~INTEGRITY;
|
||||
meta_lv->status &= ~INTEGRITY_METADATA;
|
||||
|
||||
seg->integrity_meta_dev = NULL;
|
||||
|
||||
if (!remove_layer_from_lv(lv, origin))
|
||||
return_0;
|
||||
|
||||
if (!lv_remove(origin))
|
||||
return_0;
|
||||
|
||||
if (!lv_remove(meta_lv))
|
||||
log_warn("WARNING: failed to remove integrity metadata LV.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_add_integrity(struct logical_volume *lv, const char *arg,
|
||||
struct logical_volume *meta_lv_created,
|
||||
const char *meta_name,
|
||||
@@ -274,6 +330,7 @@ int lv_add_integrity(struct logical_volume *lv, const char *arg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
meta_lv->status |= INTEGRITY_METADATA;
|
||||
seg->integrity_data_sectors = lv_size_sectors;
|
||||
seg->integrity_meta_dev = meta_lv;
|
||||
lv_set_hidden(meta_lv);
|
||||
|
||||
@@ -1202,10 +1202,13 @@ char *lv_attr_dup_with_info_and_seg_status(struct dm_pool *mem, const struct lv_
|
||||
repstr[0] = (lv_is_merging_origin(lv)) ? 'O' : 'o';
|
||||
else if (lv_is_pool_metadata(lv) ||
|
||||
lv_is_pool_metadata_spare(lv) ||
|
||||
lv_is_raid_metadata(lv))
|
||||
lv_is_raid_metadata(lv) ||
|
||||
lv_is_integrity_metadata(lv))
|
||||
repstr[0] = 'e';
|
||||
else if (lv_is_cache_type(lv) || lv_is_writecache(lv))
|
||||
repstr[0] = 'C';
|
||||
else if (lv_is_integrity(lv))
|
||||
repstr[0] = 'g';
|
||||
else if (lv_is_raid(lv))
|
||||
repstr[0] = (lv_is_not_synced(lv)) ? 'R' : 'r';
|
||||
else if (lv_is_mirror(lv))
|
||||
|
||||
@@ -137,7 +137,9 @@ enum {
|
||||
LV_TYPE_SANLOCK,
|
||||
LV_TYPE_CACHEVOL,
|
||||
LV_TYPE_WRITECACHE,
|
||||
LV_TYPE_WRITECACHEORIGIN
|
||||
LV_TYPE_WRITECACHEORIGIN,
|
||||
LV_TYPE_INTEGRITY,
|
||||
LV_TYPE_INTEGRITYORIGIN
|
||||
};
|
||||
|
||||
static const char *_lv_type_names[] = {
|
||||
@@ -193,6 +195,8 @@ static const char *_lv_type_names[] = {
|
||||
[LV_TYPE_CACHEVOL] = "cachevol",
|
||||
[LV_TYPE_WRITECACHE] = "writecache",
|
||||
[LV_TYPE_WRITECACHEORIGIN] = "writecacheorigin",
|
||||
[LV_TYPE_INTEGRITY] = "integrity",
|
||||
[LV_TYPE_INTEGRITYORIGIN] = "integrityorigin",
|
||||
};
|
||||
|
||||
static int _lv_layout_and_role_mirror(struct dm_pool *mem,
|
||||
@@ -464,6 +468,43 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lv_layout_and_role_integrity(struct dm_pool *mem,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_list *layout,
|
||||
struct dm_list *role,
|
||||
int *public_lv)
|
||||
{
|
||||
int top_level = 0;
|
||||
|
||||
/* non-top-level LVs */
|
||||
if (lv_is_integrity_metadata(lv)) {
|
||||
if (!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_INTEGRITY]) ||
|
||||
!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_METADATA]))
|
||||
goto_bad;
|
||||
} else if (lv_is_integrity_origin(lv)) {
|
||||
if (!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_INTEGRITY]) ||
|
||||
!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_ORIGIN]) ||
|
||||
!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_INTEGRITYORIGIN]))
|
||||
goto_bad;
|
||||
} else
|
||||
top_level = 1;
|
||||
|
||||
if (!top_level) {
|
||||
*public_lv = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* top-level LVs */
|
||||
if (lv_is_integrity(lv)) {
|
||||
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_INTEGRITY]))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lv_layout_and_role_thick_origin_snapshot(struct dm_pool *mem,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_list *layout,
|
||||
@@ -580,6 +621,11 @@ int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
!_lv_layout_and_role_cache(mem, lv, *layout, *role, &public_lv))
|
||||
goto_bad;
|
||||
|
||||
/* Integrity related */
|
||||
if ((lv_is_integrity(lv) || lv_is_integrity_origin(lv) || lv_is_integrity_metadata(lv)) &&
|
||||
!_lv_layout_and_role_integrity(mem, lv, *layout, *role, &public_lv))
|
||||
goto_bad;
|
||||
|
||||
/* VDO and related */
|
||||
if (lv_is_vdo_type(lv) &&
|
||||
!_lv_layout_and_role_vdo(mem, lv, *layout, *role, &public_lv))
|
||||
@@ -8440,12 +8486,23 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
backup(vg);
|
||||
|
||||
/*
|
||||
* Activate for zeroing
|
||||
* TODO: activate in zero_lv_name() if zeroing is enabled.
|
||||
* The standard option combination should be -Zy -ay, in which
|
||||
* case we activate here, and zero at the end of the command.
|
||||
* The invalid combination -Zy -an has been prevented earlier.
|
||||
* The combination -Zn -an involves no zeroing or activation.
|
||||
* For combination -Zn -ay we activate here.
|
||||
*/
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate LV to zero integrity.");
|
||||
goto out;
|
||||
if (lp->zero) {
|
||||
/* Activate for zeroing at the end of lvcreate. */
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate LV %s.", display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
} else if (!lp->zero && is_change_activating(lp->activate)) {
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Failed to activate LV %s.", display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8455,7 +8512,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
* problems (if the user doesn't want to wait, or wants
|
||||
* to do the zeroing themselves.)
|
||||
*/
|
||||
lp->post_zero_bytes = first_seg(lv)->integrity_data_sectors * 512;
|
||||
lp->integrity_bytes_to_zero = first_seg(lv)->integrity_data_sectors * 512;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
|
||||
//#define POSTORDER_FLAG UINT64_C(0x0000000002000000) /* Not real flags, reserved for
|
||||
//#define POSTORDER_OPEN_FLAG UINT64_C(0x0000000004000000) temporary use inside vg_read_internal. */
|
||||
#define INTEGRITY_METADATA UINT64_C(0x0000000004000000) /* LV - Internal use only */
|
||||
#define LV_UNCOMMITTED UINT64_C(0x0000000002000000)
|
||||
#define VIRTUAL_ORIGIN UINT64_C(0x0000000008000000) /* LV - internal use only */
|
||||
|
||||
@@ -263,7 +264,8 @@
|
||||
#define lv_is_pool_metadata_spare(lv) (((lv)->status & POOL_METADATA_SPARE) ? 1 : 0)
|
||||
#define lv_is_lockd_sanlock_lv(lv) (((lv)->status & LOCKD_SANLOCK_LV) ? 1 : 0)
|
||||
#define lv_is_writecache(lv) (((lv)->status & WRITECACHE) ? 1 : 0)
|
||||
#define lv_is_integrity(lv) (((lv)->status & INTEGRITY) ? 1 : 0)
|
||||
#define lv_is_integrity(lv) (((lv)->status & INTEGRITY) ? 1 : 0)
|
||||
#define lv_is_integrity_metadata(lv) (((lv)->status & INTEGRITY_METADATA) ? 1 : 0)
|
||||
|
||||
#define lv_is_vdo(lv) (((lv)->status & LV_VDO) ? 1 : 0)
|
||||
#define lv_is_vdo_pool(lv) (((lv)->status & LV_VDO_POOL) ? 1 : 0)
|
||||
@@ -275,9 +277,11 @@
|
||||
/* Recognize component LV (matching lib/misc/lvm-string.c _lvname_has_reserved_component_string()) */
|
||||
#define lv_is_component(lv) (lv_is_cache_origin(lv) || \
|
||||
lv_is_writecache_origin(lv) || \
|
||||
lv_is_integrity_origin(lv) || \
|
||||
((lv)->status & (\
|
||||
CACHE_POOL_DATA |\
|
||||
CACHE_POOL_METADATA |\
|
||||
INTEGRITY_METADATA |\
|
||||
LV_CACHE_VOL |\
|
||||
LV_VDO_POOL_DATA |\
|
||||
MIRROR_IMAGE |\
|
||||
@@ -998,12 +1002,12 @@ struct lvcreate_params {
|
||||
int approx_alloc; /* all */
|
||||
alloc_policy_t alloc; /* all */
|
||||
struct dm_vdo_target_params vdo_params; /* vdo */
|
||||
uint64_t post_zero_bytes; /* write zeros to LV after it's created */
|
||||
|
||||
const char *integrity_arg;
|
||||
const char *integrity_meta_name; /* external LV is user-specified */
|
||||
struct logical_volume *integrity_meta_lv; /* external LV we create */
|
||||
struct integrity_settings integrity_settings;
|
||||
uint64_t integrity_bytes_to_zero; /* zeros the final LV after it's created */
|
||||
|
||||
struct dm_list tags; /* all */
|
||||
|
||||
@@ -1099,6 +1103,8 @@ int lv_is_cache_origin(const struct logical_volume *lv);
|
||||
int lv_is_writecache_origin(const struct logical_volume *lv);
|
||||
int lv_is_writecache_cachevol(const struct logical_volume *lv);
|
||||
|
||||
int lv_is_integrity_origin(const struct logical_volume *lv);
|
||||
|
||||
int lv_is_merging_cow(const struct logical_volume *cow);
|
||||
uint32_t cow_max_extents(const struct logical_volume *origin, uint32_t chunk_size);
|
||||
int cow_has_min_chunks(const struct volume_group *vg, uint32_t cow_extents, uint32_t chunk_size);
|
||||
@@ -1404,6 +1410,7 @@ int lv_add_integrity(struct logical_volume *lv, const char *arg,
|
||||
int lv_create_integrity_metadata(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct lvcreate_params *lp);
|
||||
int lv_remove_integrity(struct logical_volume *lv);
|
||||
|
||||
int zero_lv_name(struct cmd_context *cmd, const char *vg_name, const char *lv_name, uint64_t zero_bytes);
|
||||
|
||||
|
||||
@@ -757,6 +757,14 @@ FLAGS: SECONDARY_SYNTAX
|
||||
|
||||
---
|
||||
|
||||
lvconvert --integrity String LV
|
||||
OO: OO_LVCONVERT
|
||||
OP: PV ...
|
||||
ID: lvconvert_integrity
|
||||
DESC: Remove integrity from an LV.
|
||||
|
||||
---
|
||||
|
||||
# --extents is not specified; it's an automatic alternative for --size
|
||||
|
||||
OO_LVCREATE: --addtag Tag, --alloc Alloc, --autobackup Bool, --activate Active,
|
||||
|
||||
@@ -5730,6 +5730,75 @@ int lvconvert_to_cache_with_cachevol_cmd(struct cmd_context *cmd, int argc, char
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _lvconvert_integrity_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
struct volume_group *vg = lv->vg;
|
||||
struct lv_segment *seg;
|
||||
const char *arg = arg_str_value(cmd, integrity_ARG, NULL);
|
||||
|
||||
if (strcmp(arg, "none") && strcmp(arg, "n")) {
|
||||
log_error("Integrity can only be removed from an existing LV (see --integrity none).");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!lv_is_integrity(lv)) {
|
||||
log_error("LV does not have integrity.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
seg = first_seg(lv);
|
||||
|
||||
if (!seg->integrity_meta_dev) {
|
||||
log_error("Internal integrity cannot be removed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
/* TODO: lift this restriction */
|
||||
if (lv_info(cmd, lv, 1, NULL, 0, 0)) {
|
||||
log_error("LV must be inactive to remove integrity.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (!lv_remove_integrity(lv))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
backup(vg);
|
||||
|
||||
log_print_unless_silent("Logical volume %s has removed integrity.", display_lvname(lv));
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
int lvconvert_integrity_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct processing_handle *handle;
|
||||
struct lvconvert_result lr = { 0 };
|
||||
int ret;
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &lr;
|
||||
|
||||
cmd->cname->flags &= ~GET_VGNAME_FROM_OPTIONS;
|
||||
|
||||
ret = process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle, NULL,
|
||||
&_lvconvert_integrity_single);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* All lvconvert command defs have their own function,
|
||||
* so the generic function name is unused.
|
||||
|
||||
@@ -1582,6 +1582,13 @@ static int _check_zero_parameters(struct cmd_context *cmd, struct lvcreate_param
|
||||
if (seg_is_thin(lp))
|
||||
return 1;
|
||||
|
||||
if (seg_is_integrity(lp)) {
|
||||
if (lp->zero && !is_change_activating(lp->activate)) {
|
||||
log_error("Zeroing integrity is not compatible with inactive creation (-an).");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is some problem, buffer will not be empty */
|
||||
if (dm_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
|
||||
lp->origin_name ? "origin " : "",
|
||||
@@ -1801,19 +1808,11 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
_destroy_lvcreate_params(&lp);
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
/*
|
||||
* FIXME: make this interruptible. If the user cancels the zeroing,
|
||||
* they can either use the LV without it being zeroed, or can finish
|
||||
* zeroing it themselves, e.g. with dd.
|
||||
*
|
||||
* FIXME: if the user asked for the lv to be created in inactive
|
||||
* (-an) then deactivate the LV after zeroing.
|
||||
*/
|
||||
if (lp.post_zero_bytes) {
|
||||
if (lp.integrity_bytes_to_zero) {
|
||||
if (!lp.zero)
|
||||
log_warn("WARNING: not zeroing LV, integrity read errors may occur.");
|
||||
log_warn("WARNING: not zeroing integrity LV, read errors are possible.");
|
||||
else
|
||||
zero_lv_name(cmd, lp.vg_name, lp.lv_name, lp.post_zero_bytes);
|
||||
zero_lv_name(cmd, lp.vg_name, lp.lv_name, lp.integrity_bytes_to_zero);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -149,6 +149,9 @@ static const struct command_function _command_functions[CMD_COUNT] = {
|
||||
{ lvconvert_to_vdopool_CMD, lvconvert_to_vdopool_cmd },
|
||||
{ lvconvert_to_vdopool_param_CMD, lvconvert_to_vdopool_param_cmd },
|
||||
|
||||
/* lvconvert for integrity */
|
||||
{ lvconvert_integrity_CMD, lvconvert_integrity_cmd },
|
||||
|
||||
{ pvscan_display_CMD, pvscan_display_cmd },
|
||||
{ pvscan_cache_CMD, pvscan_cache_cmd },
|
||||
};
|
||||
|
||||
@@ -275,6 +275,8 @@ int lvconvert_merge_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
int lvconvert_to_vdopool_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
int lvconvert_to_vdopool_param_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
int lvconvert_integrity_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
int pvscan_display_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user