1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

Calculate mirror log size instead of hardcoding 1 extent size.

It fails for 1k PE now.

Patch adds log_region_size into allocation habdle struct
and use it in _alloc_parallel_area() for proper log size calculation
instead of hardcoded 1 extent - which can fail.

Reproducer for incorrect log size calculation:
        DEV=/dev/sd[bcd]

        pvcreate $DEV
        vgcreate -s 1k vg_test $DEV
        lvcreate -m1 -L 12M -n mirr vg_test

https://bugzilla.redhat.com/show_bug.cgi?id=477040

The log size calculation is mostly copied from kernel code.
This commit is contained in:
Milan Broz 2008-12-19 15:24:52 +00:00
parent 0c8bdaf33c
commit 6d1b3b5385
5 changed files with 49 additions and 10 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.44 - Version 2.02.44 -
==================================== ====================================
Calculate mirror log size instead of using 1 extent.
Check if requested major/minor pair is already used. Check if requested major/minor pair is already used.
Fix incorrect return value in help function. Fix incorrect return value in help function.
Fix vgrename using UUID in case there are VGs with the same name. Fix vgrename using UUID in case there are VGs with the same name.

View File

@ -47,7 +47,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
const struct segment_type *segtype, const struct segment_type *segtype,
uint32_t stripes, uint32_t stripes,
uint32_t mirrors, uint32_t log_count, uint32_t mirrors, uint32_t log_count,
uint32_t extents, uint32_t log_region_size, uint32_t extents,
struct dm_list *allocatable_pvs, struct dm_list *allocatable_pvs,
alloc_policy_t alloc, alloc_policy_t alloc,
struct dm_list *parallel_areas); struct dm_list *parallel_areas);

View File

@ -516,6 +516,7 @@ struct alloc_handle {
uint32_t area_count; /* Number of parallel areas */ uint32_t area_count; /* Number of parallel areas */
uint32_t area_multiple; /* seg->len = area_len * area_multiple */ uint32_t area_multiple; /* seg->len = area_len * area_multiple */
uint32_t log_count; /* Number of parallel 1-extent logs */ uint32_t log_count; /* Number of parallel 1-extent logs */
uint32_t log_region_size; /* region size for log device */
uint32_t total_area_len; /* Total number of parallel extents */ uint32_t total_area_len; /* Total number of parallel extents */
struct dm_list *parallel_areas; /* PVs to avoid */ struct dm_list *parallel_areas; /* PVs to avoid */
@ -543,6 +544,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
uint32_t mirrors, uint32_t mirrors,
uint32_t stripes, uint32_t stripes,
uint32_t log_count, uint32_t log_count,
uint32_t log_region_size,
struct dm_list *parallel_areas) struct dm_list *parallel_areas)
{ {
struct alloc_handle *ah; struct alloc_handle *ah;
@ -582,6 +584,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
ah->area_count = area_count; ah->area_count = area_count;
ah->log_count = log_count; ah->log_count = log_count;
ah->log_region_size = log_region_size;
ah->alloc = alloc; ah->alloc = alloc;
ah->area_multiple = calc_area_multiple(segtype, area_count); ah->area_multiple = calc_area_multiple(segtype, area_count);
@ -703,6 +706,28 @@ static int _setup_alloced_segments(struct logical_volume *lv,
return 1; return 1;
} }
/*
* Returns log device size in extents, algorithm from kernel code
*/
#define BYTE_SHIFT 3
static uint32_t mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint32_t area_len)
{
size_t area_size, bitset_size, log_size, region_count;
area_size = area_len * pe_size;
region_count = dm_div_up(area_size, region_size);
/* Work out how many "unsigned long"s we need to hold the bitset. */
bitset_size = dm_round_up(region_count, sizeof(uint32_t) << BYTE_SHIFT);
bitset_size >>= BYTE_SHIFT;
/* Log device holds both header and bitset. */
log_size = dm_round_up((MIRROR_LOG_OFFSET << SECTOR_SHIFT) + bitset_size, 1 << SECTOR_SHIFT);
log_size >>= SECTOR_SHIFT;
return dm_div_up(log_size, pe_size);
}
/* /*
* This function takes a list of pv_areas and adds them to allocated_areas. * This function takes a list of pv_areas and adds them to allocated_areas.
* If the complete area is not needed then it gets split. * If the complete area is not needed then it gets split.
@ -745,7 +770,9 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
if (log_area) { if (log_area) {
ah->log_area.pv = log_area->map->pv; ah->log_area.pv = log_area->map->pv;
ah->log_area.pe = log_area->start; ah->log_area.pe = log_area->start;
ah->log_area.len = MIRROR_LOG_SIZE; /* FIXME Calculate & check this */ ah->log_area.len = mirror_log_extents(ah->log_region_size,
pv_pe_size(log_area->map->pv),
area_len);
consume_pv_area(log_area, ah->log_area.len); consume_pv_area(log_area, ah->log_area.len);
} }
@ -817,7 +844,7 @@ static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
/* FIXME only_single_area_segments used as workaround to skip log LV - needs new param? */ /* FIXME only_single_area_segments used as workaround to skip log LV - needs new param? */
if (!only_single_area_segments && seg_is_mirrored(seg) && seg->log_lv) { if (!only_single_area_segments && seg_is_mirrored(seg) && seg->log_lv) {
if (!(r = _for_each_pv(cmd, seg->log_lv, 0, MIRROR_LOG_SIZE, if (!(r = _for_each_pv(cmd, seg->log_lv, 0, seg->log_lv->le_count?:1,
NULL, 0, 0, 0, only_single_area_segments, NULL, 0, 0, 0, only_single_area_segments,
fn, data))) fn, data)))
stack; stack;
@ -1256,7 +1283,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
const struct segment_type *segtype, const struct segment_type *segtype,
uint32_t stripes, uint32_t stripes,
uint32_t mirrors, uint32_t log_count, uint32_t mirrors, uint32_t log_count,
uint32_t extents, uint32_t log_region_size, uint32_t extents,
struct dm_list *allocatable_pvs, struct dm_list *allocatable_pvs,
alloc_policy_t alloc, alloc_policy_t alloc,
struct dm_list *parallel_areas) struct dm_list *parallel_areas)
@ -1282,7 +1309,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
alloc = vg->alloc; alloc = vg->alloc;
if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc, mirrors, if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc, mirrors,
stripes, log_count, parallel_areas))) stripes, log_count, log_region_size, parallel_areas)))
return_NULL; return_NULL;
if (!segtype_is_virtual(segtype) && if (!segtype_is_virtual(segtype) &&
@ -1577,7 +1604,7 @@ int lv_extend(struct logical_volume *lv,
if (segtype_is_virtual(segtype)) if (segtype_is_virtual(segtype))
return lv_add_virtual_segment(lv, status, extents, segtype); return lv_add_virtual_segment(lv, status, extents, segtype);
if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0, if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0, 0,
extents, allocatable_pvs, alloc, NULL))) extents, allocatable_pvs, alloc, NULL)))
return_0; return_0;

View File

@ -34,7 +34,18 @@
//#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1) //#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
//#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */ //#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
//#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */ //#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */
#define MIRROR_LOG_SIZE 1 /* Extents */ #define MIRROR_LOG_OFFSET 2 /* sectors */
/*
* Ceiling(n / sz)
*/
#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
/*
* Ceiling(n / size) * size
*/
#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
/* Various flags */ /* Various flags */
/* Note that the bits no longer necessarily correspond to LVM1 disk format */ /* Note that the bits no longer necessarily correspond to LVM1 disk format */

View File

@ -1171,7 +1171,7 @@ int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
lv->le_count, lv->le_count,
region_size); region_size);
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0, if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0, 0,
lv->le_count, allocatable_pvs, alloc, lv->le_count, allocatable_pvs, alloc,
parallel_areas))) { parallel_areas))) {
log_error("Unable to allocate mirror extents for %s.", lv->name); log_error("Unable to allocate mirror extents for %s.", lv->name);
@ -1388,7 +1388,7 @@ int add_mirror_log(struct cmd_context *cmd, struct logical_volume *lv,
/* allocate destination extents */ /* allocate destination extents */
ah = allocate_extents(lv->vg, NULL, segtype, ah = allocate_extents(lv->vg, NULL, segtype,
0, 0, log_count, 0, 0, 0, log_count, region_size, 0,
allocatable_pvs, alloc, parallel_areas); allocatable_pvs, alloc, parallel_areas);
if (!ah) { if (!ah) {
log_error("Unable to allocate extents for mirror log."); log_error("Unable to allocate extents for mirror log.");
@ -1443,7 +1443,7 @@ int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
return_0; return_0;
ah = allocate_extents(lv->vg, NULL, segtype, ah = allocate_extents(lv->vg, NULL, segtype,
stripes, mirrors, log_count, lv->le_count, stripes, mirrors, log_count, region_size, lv->le_count,
allocatable_pvs, alloc, parallel_areas); allocatable_pvs, alloc, parallel_areas);
if (!ah) { if (!ah) {
log_error("Unable to allocate extents for mirror(s)."); log_error("Unable to allocate extents for mirror(s).");