1
0
mirror of git://sourceware.org/git/lvm2.git synced 2026-02-11 12:32:46 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
39f781ca21 Add dm-integrity support
Create a linear LV with a dm-integrity layer added
above it.  The dm-integrity layer stores checksums
of the data written to the LV, and returns an error
if data read from the LV does not match the previously
saved checksum.

lvcreate --type integrity --integrity String [options]

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)
  Store integrity metadata on a separate LV.
  Allows removing integrity from the LV later.

  --integrity internal
  Store integrity metadata interleaved with data
  on the same LV.  Around 1% of the LV size will
  be used for integrity metadata.

  --integrity y
  Enable default integrity settings (external).

Command variations:

lvcreate --type integrity -n Name -L Size VG

  [--integrity external is the default]

lvcreate --integrity external -n Name -L Size VG

  [--integrity external implies --type integrity]

lvcreate --integrity y -n Name -L Size VG

  [--integrity y uses default/external, and implies
   --type integrity]

lvcreate --integrity internal -n Name -L Size VG

  [--integrity internal implies --type integrity]

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.

  --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 -wi-a-----  1.00g [lvex_iorig]
  [lvex_imeta] vg -wi-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 -wi-a----- 1.00g [lvin_iorig]
  [lvin_iorig] vg -wi-ao---- 1.00g

Zeroing:

After a new integrity LV is created, zeroes are written to
the entire LV to initialize integrity metadata (checksums).
Without this initialization, the LV will return read errors
for any unwritten (and uninitialized) data.

A large LV may take a long time to zero.  The -Zn option can
be used to disable the whole-LV zeroing, or the lvcreate
command can be canceled while zeroing the new LV.  In either
case, the user may write to the entire LV to initialize the
integrity metadata themselves.

TODO:

- add command to remove intregrity from an LV (only for external),
  i.e. lvconvert --integrity none LV

- let integrity be used by raid images
2019-12-03 15:44:11 -06:00
3 changed files with 39 additions and 9 deletions

View File

@@ -62,6 +62,7 @@ int lv_create_integrity_metadata(struct cmd_context *cmd,
.vg_name = vg->name,
.zero = 0,
.wipe_signatures = 0,
.suppress_zero_warn = 1,
};
if (dm_snprintf(metaname, NAME_LEN, "%s_imeta", lp->lv_name) < 0) {
@@ -79,8 +80,8 @@ int lv_create_integrity_metadata(struct cmd_context *cmd,
meta_sectors = meta_bytes / 512;
lp_meta.extents = meta_sectors / vg->extent_size;
log_print("Creating integrity metadata LV %s with %u extents, %s",
metaname, lp_meta.extents, display_size(cmd, meta_sectors));
log_print("Creating integrity metadata LV %s with size %s.",
metaname, display_size(cmd, meta_sectors));
dm_list_init(&lp_meta.tags);
@@ -261,7 +262,7 @@ int lv_add_integrity(struct logical_volume *lv, const char *arg,
memset(&wipe, 0, sizeof(wipe));
wipe.do_zero = 1;
wipe.zero_sectors = 1;
wipe.zero_sectors = 8;
if (!wipe_lv(meta_lv, wipe)) {
log_error("Failed to zero LV for integrity metadata %s", display_lvname(meta_lv));
@@ -302,6 +303,11 @@ int lv_add_integrity(struct logical_volume *lv, const char *arg,
ret = 1;
}
if (!seg->integrity_data_sectors) {
log_error("LV size too small to include metadata.");
ret = 0;
}
lv->status |= LV_UNCOMMITTED;
if (!deactivate_lv(cmd, lv)) {

View File

@@ -28,6 +28,7 @@
#include "lib/datastruct/str_list.h"
#include "lib/config/defaults.h"
#include "lib/misc/lvm-exec.h"
#include "lib/misc/lvm-signal.h"
#include "lib/mm/memlock.h"
#include "lib/locking/lvmlockd.h"
#include "lib/label/label.h"
@@ -7451,8 +7452,8 @@ int zero_lv_name(struct cmd_context *cmd, const char *vg_name, const char *lv_na
zero_bytes = lv_size_bytes;
log_print("Zeroing %s %s ...", name, display_size(cmd, zero_bytes/512));
log_print("Cancel command to zero device manually.");
log_print("Zeroing %s %s... (cancel command to zero manually)",
name, display_size(cmd, zero_bytes/512));
if ((extra_bytes = (zero_bytes % ONE_MB_IN_BYTES)))
zero_bytes -= extra_bytes;
@@ -7463,12 +7464,21 @@ int zero_lv_name(struct cmd_context *cmd, const char *vg_name, const char *lv_na
* cover remaining dev size.
*/
sigint_allow();
for (i = 0; i < (zero_bytes / ONE_MB_IN_BYTES); i++) {
off = i * ONE_MB_IN_BYTES;
if (!dev_write_zeros(dev, off, (size_t)ONE_MB_IN_BYTES))
log_error("Failed to zero LV at offset %llu.", (unsigned long long)off);
if (off && !(off % (1024 * ONE_MB_IN_BYTES)))
log_print("Zeroed %s ...", display_size(cmd, off/512));
log_print("Zeroed %s...", display_size(cmd, off/512));
if (sigint_caught()) {
log_print("Zeroing canceled.");
goto out;
}
}
if (extra_bytes) {
@@ -7478,6 +7488,11 @@ int zero_lv_name(struct cmd_context *cmd, const char *vg_name, const char *lv_na
off = i * ONE_MB_IN_BYTES + j * BCACHE_BLOCK_SIZE_IN_BYTES;
if (!dev_write_zeros(dev, off, (size_t)BCACHE_BLOCK_SIZE_IN_BYTES))
log_error("Failed to zero LV at offset %llu.", (unsigned long long)off);
if (sigint_caught()) {
log_print("Zeroing canceled.");
goto out;
}
}
}
@@ -7489,6 +7504,8 @@ int zero_lv_name(struct cmd_context *cmd, const char *vg_name, const char *lv_na
if ((extra_bytes = lv_size_bytes - (i * ONE_MB_IN_BYTES + j * BCACHE_BLOCK_SIZE_IN_BYTES)))
log_warn("WARNING: last %llu bytes not zeroed.", (unsigned long long)extra_bytes);
out:
sigint_restore();
label_scan_invalidate(dev);
return 1;
}
@@ -8422,7 +8439,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
backup(vg);
/* Activate for zeroing */
/*
* Activate for zeroing
* TODO: activate in zero_lv_name() if zeroing is enabled.
*/
if (!activate_lv(cmd, lv)) {
log_error("Failed to activate LV to zero integrity.");
goto out;

View File

@@ -1809,8 +1809,12 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
* 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)
zero_lv_name(cmd, lp.vg_name, lp.lv_name, lp.post_zero_bytes);
if (lp.post_zero_bytes) {
if (!lp.zero)
log_warn("WARNING: not zeroing LV, integrity read errors may occur.");
else
zero_lv_name(cmd, lp.vg_name, lp.lv_name, lp.post_zero_bytes);
}
return ret;
}