1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

integrity: add new option raidintegrityjournalsize

to specify the integrity journal size
This commit is contained in:
David Teigland 2024-08-05 13:20:58 -05:00
parent 07576f7e51
commit 920a1d2229
6 changed files with 55 additions and 9 deletions

View File

@ -50,7 +50,8 @@ int lv_is_integrity_origin(const struct logical_volume *lv)
* plus some initial space for journals.
* (again from trial and error testing.)
*/
static uint64_t _lv_size_bytes_to_integrity_meta_bytes(uint64_t lv_size_bytes)
static uint64_t _lv_size_bytes_to_integrity_meta_bytes(uint64_t lv_size_bytes, uint32_t journal_sectors,
uint32_t extent_size)
{
uint64_t meta_bytes;
uint64_t initial_bytes;
@ -58,8 +59,16 @@ static uint64_t _lv_size_bytes_to_integrity_meta_bytes(uint64_t lv_size_bytes)
/* Every 500M of data needs 4M of metadata. */
meta_bytes = ((lv_size_bytes / (500 * ONE_MB_IN_BYTES)) + 1) * (4 * ONE_MB_IN_BYTES);
if (journal_sectors) {
/* for calculating the metadata LV size for the specified
journal size, round the specified journal size up to the
nearest extent. extent_size is in sectors. */
initial_bytes = dm_round_up(journal_sectors, extent_size) * 512;
goto out;
}
/*
* initial space used for journals
* initial space used for journals (when journal size is not specified):
* lv_size <= 512M -> 4M
* lv_size <= 1G -> 8M
* lv_size <= 4G -> 32M
@ -73,7 +82,10 @@ static uint64_t _lv_size_bytes_to_integrity_meta_bytes(uint64_t lv_size_bytes)
initial_bytes = 32 * ONE_MB_IN_BYTES;
else if (lv_size_bytes > (4ULL * ONE_GB_IN_BYTES))
initial_bytes = 64 * ONE_MB_IN_BYTES;
out:
log_debug("integrity_meta_bytes %llu from lv_size_bytes %llu meta_bytes %llu initial_bytes %llu journal_sectors %u",
(unsigned long long)(meta_bytes+initial_bytes), (unsigned long long)lv_size_bytes,
(unsigned long long)meta_bytes, (unsigned long long)initial_bytes, journal_sectors);
return meta_bytes + initial_bytes;
}
@ -84,6 +96,7 @@ static uint64_t _lv_size_bytes_to_integrity_meta_bytes(uint64_t lv_size_bytes)
static int _lv_create_integrity_metadata(struct cmd_context *cmd,
struct volume_group *vg,
struct lvcreate_params *lp,
struct integrity_settings *settings,
struct logical_volume **meta_lv)
{
char metaname[NAME_LEN] = { 0 };
@ -115,7 +128,7 @@ static int _lv_create_integrity_metadata(struct cmd_context *cmd,
lp_meta.pvh = lp->pvh;
lv_size_bytes = (uint64_t)lp->extents * (uint64_t)vg->extent_size * 512;
meta_bytes = _lv_size_bytes_to_integrity_meta_bytes(lv_size_bytes);
meta_bytes = _lv_size_bytes_to_integrity_meta_bytes(lv_size_bytes, settings->journal_sectors, vg->extent_size);
meta_sectors = meta_bytes / 512;
lp_meta.extents = meta_sectors / vg->extent_size;
@ -181,13 +194,18 @@ int lv_extend_integrity_in_raid(struct logical_volume *lv, struct dm_list *pvh)
}
lv_size_bytes = lv_iorig->size * 512;
meta_bytes = _lv_size_bytes_to_integrity_meta_bytes(lv_size_bytes);
meta_bytes = _lv_size_bytes_to_integrity_meta_bytes(lv_size_bytes, 0, 0);
meta_sectors = meta_bytes / 512;
meta_extents = meta_sectors / vg->extent_size;
prev_meta_sectors = lv_imeta->size;
prev_meta_extents = prev_meta_sectors / vg->extent_size;
/*
* FIXME: allow --raidintegrityjournalsize to be used with
* lvextend to override the default journal size calculation.
*/
if (meta_extents <= prev_meta_extents) {
log_debug("extend not needed for imeta LV %s", lv_imeta->name);
continue;
@ -322,6 +340,18 @@ int integrity_mode_set(const char *mode, struct integrity_settings *settings)
return 1;
}
int integrity_journal_set(int num_sectors, struct integrity_settings *settings)
{
int size_mb = num_sectors / 2048;
if (size_mb < 4 || size_mb > 1024) {
log_error("Invalid raid integrity journal size %d MiB (use 4-1024 MiB).", size_mb);
return 0;
}
settings->journal_sectors = num_sectors;
settings->journal_sectors_set = 1;
return 1;
}
static int _set_integrity_block_size(struct cmd_context *cmd, struct logical_volume *lv, int is_active,
struct integrity_settings *settings,
int lbs_4k, int lbs_512, int pbs_4k, int pbs_512)
@ -597,7 +627,7 @@ int lv_add_integrity_to_raid(struct logical_volume *lv, struct integrity_setting
lp.pvh = use_pvh;
lp.extents = lv_image->size / vg->extent_size;
if (!_lv_create_integrity_metadata(cmd, vg, &lp, &meta_lv))
if (!_lv_create_integrity_metadata(cmd, vg, &lp, settings, &meta_lv))
goto_bad;
revert_meta_lvs++;

View File

@ -1508,6 +1508,7 @@ int lv_raid_has_integrity(struct logical_volume *lv);
int lv_extend_integrity_in_raid(struct logical_volume *lv, struct dm_list *pvh);
int lv_get_raid_integrity_settings(struct logical_volume *lv, struct integrity_settings **isettings);
int integrity_mode_set(const char *mode, struct integrity_settings *settings);
int integrity_journal_set(int size_mb, struct integrity_settings *settings);
int lv_integrity_mismatches(struct cmd_context *cmd, const struct logical_volume *lv, uint64_t *mismatches);
int lv_raid_integrity_total_mismatches(struct cmd_context *cmd, const struct logical_volume *lv, uint64_t *mismatches);

View File

@ -670,6 +670,9 @@ arg(raidintegritymode_ARG, '\0', "raidintegritymode", string_VAL, 0, 0,
"bitmap mode can in theory achieve full write throughput of the device,\n"
"but would not benefit from the potential scattered write optimization.\n")
arg(raidintegrityjournalsize_ARG, '\0', "raidintegrityjournalsize", sizemb_VAL, 0, 0,
"The size of integrity journal.\n")
arg(readonly_ARG, '\0', "readonly", 0, 0, 0,
"Prevent the command from making changes, including activation and\n"
"metadata updates.\n")

View File

@ -843,7 +843,7 @@ FLAGS: SECONDARY_SYNTAX
---
lvconvert --raidintegrity Bool LV_raid
OO: --raidintegritymode String, --raidintegrityblocksize Number, OO_LVCONVERT
OO: --raidintegritymode String, --raidintegrityblocksize Number, --raidintegrityjournalsize SizeMB, OO_LVCONVERT
OP: PV ...
ID: lvconvert_integrity
DESC: Add or remove data integrity checksums to raid images.
@ -869,7 +869,7 @@ OO_LVCREATE_VDO: --compression Bool, --deduplication Bool, --vdosettings String
OO_LVCREATE_THINPOOL: --discards Discards, --errorwhenfull Bool, --pooldatavdo Bool, OO_LVCREATE_VDO, OO_LVCREATE_POOL
OO_LVCREATE_RAID: --regionsize RegionSize, --minrecoveryrate SizeKB, --maxrecoveryrate SizeKB,
--raidintegrity Bool, --raidintegritymode String, --raidintegrityblocksize Number
--raidintegrity Bool, --raidintegritymode String, --raidintegrityblocksize Number, --raidintegrityjournalsize SizeMB
---

View File

@ -6522,6 +6522,9 @@ static int _lvconvert_integrity_single(struct cmd_context *cmd,
if (!integrity_mode_set(arg_str_value(cmd, raidintegritymode_ARG, NULL), &settings))
return_ECMD_FAILED;
if (!integrity_journal_set(arg_int_value(cmd, raidintegrityjournalsize_ARG, 0), &settings))
return_ECMD_FAILED;
if (arg_is_set(cmd, raidintegrityblocksize_ARG))
settings.block_size = arg_int_value(cmd, raidintegrityblocksize_ARG, 0);

View File

@ -609,12 +609,20 @@ static int _read_raid_params(struct cmd_context *cmd,
if (arg_int_value(cmd, raidintegrity_ARG, 0)) {
lp->raidintegrity = 1;
log_debug("raid integrity enabled blocksize %d journalsize %d mode %s",
arg_int_value(cmd, raidintegrityblocksize_ARG, 0),
arg_int_value(cmd, raidintegrityjournalsize_ARG, 0),
arg_str_value(cmd, raidintegritymode_ARG, NULL) ?: "none");
if (arg_is_set(cmd, raidintegrityblocksize_ARG))
lp->integrity_settings.block_size = arg_int_value(cmd, raidintegrityblocksize_ARG, 0);
if (arg_is_set(cmd, raidintegritymode_ARG)) {
if (!integrity_mode_set(arg_str_value(cmd, raidintegritymode_ARG, NULL), &lp->integrity_settings))
return_0;
}
if (arg_is_set(cmd, raidintegrityjournalsize_ARG)) {
if (!integrity_journal_set(arg_int_value(cmd, raidintegrityjournalsize_ARG, 0), &lp->integrity_settings))
return_0;
}
}
return 1;
@ -936,7 +944,8 @@ static int _lvcreate_params(struct cmd_context *cmd,
raidminrecoveryrate_ARG, \
raidintegrity_ARG, \
raidintegritymode_ARG, \
raidintegrityblocksize_ARG
raidintegrityblocksize_ARG, \
raidintegrityjournalsize_ARG
#define SIZE_ARGS \
extents_ARG,\