diff options
| author | David Teigland <teigland@redhat.com> | 2019-11-20 16:07:27 -0600 |
|---|---|---|
| committer | David Teigland <teigland@redhat.com> | 2019-12-18 15:01:02 -0600 |
| commit | 4fe0ec89933e06a278f2bacb9a86b0258a5fa919 (patch) | |
| tree | adcf864fa73ea2c3b64e9fe27598dee7b052c538 /lib/metadata/lv_manip.c | |
| parent | 2173bdb82177fc687474b72561742955cb292522 (diff) | |
| download | lvm2-dev-dct-integrity17.tar.gz | |
dm-integrity supportdev-dct-integrity17
dm-integrity stores checksums of the data written to an
LV, and returns an error if data read from the LV does
not match the previously saved checksum.
Create a linear LV with a dm-integrity layer above it:
lvcreate --type integrity --integrity String [options]
Create a raid1 LV with a dm-integrity layer over each
raid image:
lvcreate --type raid1 --integrity y [options]
Add a dm-integrity layer to an existing linear LV,
or to each image of an existing raid1 LV:
lvconvert --integrity y LV
Remove the dm-integrity layer from a linear LV, or
from the images of a raid1 LV:
lvconvert --integrity n LV
Integrity metadata:
The --integrity String specifies if the dm-integrity
metadata (checksums) should be interleaved with data
blocks, or written to a separate external LV.
--integrity external (default)
Use integrity with metadata on a separate LV.
Allows removing integrity from the LV later.
--integrity y
Same as integrity external.
--integrity n
Remove integrity (external metadata only.)
--integrity internal
Use integrity with metadata interleaved with
data on the same LV.
Only allowed with new linear LVs.
Internal integrity cannot be removed from an LV.
Around 1% of the LV size is used for integrity metadata.
Command variations:
lvcreate --type integrity -n Name -L Size VG
[Uses integrity external, the default.]
lvcreate --integrity y|external -n Name -L Size VG
[Uses type integrity, which is implied.]
lvcreate --integrity internal -n Name -L Size VG
[Uses type integrity, which is implied.]
lvcreate --type raid1 --integrity y -m Num -n Name -L Size VG
[Uses type integrity for each raid image.]
lvconvert --type integrity LV
[Converts linear LV to type integrity.]
lvconvert --integrity y|external LV
[Converts linear LV to type integrity, or each
image to type integrity in a raid1 LV.]
Options:
--integritymetadata LV
Use the specified LV for external metadata.
Allows specific device placement of metadata.
Without this option, the command creates a
hidden LV (with an _imeta suffix) to hold the
metadata. (Not usable with raid1+integrity.)
--integritysettings String
set dm-integrity parameters, e.g. to use a journal
instead of bitmap, --integritysettings "mode=J".
Example:
$ lvcreate --integrity external -n lvex -L1G vg
$ lvs -a vg
LV VG Attr LSize Origin
lvex vg gwi-a----- 1.00g [lvex_iorig]
[lvex_imeta] vg ewi-ao---- 12.00m
[lvex_iorig] vg -wi-ao---- 1.00g
$ lvcreate --integrity internal -n lvin -L1G vg
$ lvs -a vg
LV VG Attr LSize Origin
lvin vg gwi-a----- 1.00g [lvin_iorig]
[lvin_iorig] vg -wi-ao---- 1.00g
$ lvcreate --type raid1 --integrity y -m 1 -n lver -L1G vg
$ lvs -a vg
LV VG Attr LSize Origin
lver vg rwi-a-r--- 1.00g
[lver_rimage_0] vg gwi-aor--- 1.00g [lver_rimage_0_iorig]
[lver_rimage_0_imeta] vg ewi-ao---- 12.00m
[lver_rimage_0_iorig] vg -wi-ao---- 1.00g
[lver_rimage_1] vg gwi-aor--- 1.00g [lver_rimage_1_iorig]
[lver_rimage_1_imeta] vg ewi-ao---- 12.00m
[lver_rimage_1_iorig] vg -wi-ao---- 1.00g
[lver_rmeta_0] vg ewi-aor--- 4.00m
[lver_rmeta_1] vg ewi-aor--- 4.00m
Diffstat (limited to 'lib/metadata/lv_manip.c')
| -rw-r--r-- | lib/metadata/lv_manip.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b4daa5633..ae53de2de 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -134,7 +134,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[] = { @@ -190,6 +192,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, @@ -461,6 +465,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, @@ -577,6 +618,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)) @@ -1457,6 +1503,15 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete) return_0; } + if (delete && seg_is_integrity(seg)) { + /* Remove integrity origin in addition to integrity layer. */ + if (!lv_remove(seg_lv(seg, 0))) + return_0; + /* Remove integrity metadata. */ + if (seg->integrity_meta_dev && !lv_remove(seg->integrity_meta_dev)) + return_0; + } + if ((pool_lv = seg->pool_lv)) { if (!detach_pool_lv(seg)) return_0; @@ -5654,6 +5709,11 @@ int lv_resize(struct logical_volume *lv, return 0; } + if (lv_is_integrity(lv)) { + log_error("Resize not yet allowed on LVs with integrity."); + return 0; + } + if (!_lvresize_check(lv, lp)) return_0; @@ -7934,6 +7994,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, /* FIXME Eventually support raid/mirrors with -m */ if (!(create_segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED))) return_0; + + } else if (seg_is_integrity(lp)) { + if (!(create_segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED))) + return_0; + } else if (seg_is_mirrored(lp) || (seg_is_raid(lp) && !seg_is_any_raid0(lp))) { if (!(lp->region_size = adjusted_mirror_region_size(vg->cmd, vg->extent_size, @@ -8184,6 +8249,53 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, goto out; } + if (seg_is_integrity(lp) || (seg_is_raid(lp) && lp->integrity_arg)) { + log_print("Adding integrity to new LV"); + + /* + * internal integrity requires wiping the origin, before + * integrity is added, so the integrity superblock is zero. + * This is independent of wiping the final LV below. + */ + if (seg_is_integrity(lp) && lp->integrity_arg && !strcmp(lp->integrity_arg, "internal")) { + struct wipe_params wp = { .do_zero = 1, .zero_sectors = 8 }; + + log_debug("Activating to zero integrity superblock of origin %s", lv->name); + lv->status |= LV_TEMPORARY; + lv->status |= LV_NOSCAN; + + if (!activate_lv(cmd, lv)) { + log_error("Failed to activate LV for zeroing integrity superblock."); + goto revert_new_lv; + } + + lv->status &= ~LV_TEMPORARY; + lv->status &= ~LV_NOSCAN; + + if (!wipe_lv(lv, wp)) { + log_error("Failed to zero integrity superblock of new origin."); + goto revert_new_lv; + } + + if (!deactivate_lv(cmd, lv)) { + log_error("Failed to deactivate LV from zeroing integrity superblock."); + goto revert_new_lv; + } + } + + if (seg_is_raid(lp)) { + if (!lv_add_integrity_to_raid(lv, lp->integrity_arg, + &lp->integrity_settings, lp->pvh)) + goto revert_new_lv; + } else { + if (!lv_add_integrity(lv, lp->integrity_arg, lp->integrity_meta_name, + &lp->integrity_settings, lp->pvh)) + goto revert_new_lv; + } + + backup(vg); + } + /* Do not scan this LV until properly zeroed/wiped. */ if (_should_wipe_lv(lp, lv, 0)) lv->status |= LV_NOSCAN; |
