* [PATCH 2 of 10] LVM: make log_area a list
@ 2009-10-08 21:18 ` Jonathan Brassow
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Brassow @ 2009-10-08 21:18 UTC (permalink / raw)
To: dm-devel; +Cc: lvm-devel
Patch name: lvm-make-log_area-a-list.patch
The 'alloc_handle' structure only has space for one log_area.
We change that to a list to allow an arbitrary number of
log areas.
RFC: Jonathan Brassow <jbrassow@redhat.com>
Index: LVM2/lib/metadata/lv_manip.c
===================================================================
--- LVM2.orig/lib/metadata/lv_manip.c
+++ LVM2/lib/metadata/lv_manip.c
@@ -515,7 +515,7 @@ struct alloc_handle {
struct dm_list *parallel_areas; /* PVs to avoid */
- struct alloced_area log_area; /* Extent used for log */
+ struct dm_list log_areas; /* Extents used for logs */
struct dm_list alloced_areas[0]; /* Lists of areas in each stripe */
};
@@ -582,6 +582,7 @@ static struct alloc_handle *_alloc_init(
ah->alloc = alloc;
ah->area_multiple = calc_area_multiple(segtype, area_count);
+ dm_list_init(&ah->log_areas);
for (s = 0; s < ah->area_count; s++)
dm_list_init(&ah->alloced_areas[s]);
@@ -763,10 +764,11 @@ static int _alloc_parallel_area(struct a
consume_pv_area(areas[s], area_len);
if (log_area) {
- ah->log_area.pv = log_area->map->pv;
- ah->log_area.pe = log_area->start;
- ah->log_area.len = log_len;
- consume_pv_area(log_area, ah->log_area.len);
+ aa[s].pv = log_area->map->pv;
+ aa[s].pe = log_area->start;
+ aa[s].len = log_len;
+ dm_list_add(&ah->log_areas, &aa[s].list);
+ consume_pv_area(log_area, log_len);
}
*ix += area_len * ah->area_multiple;
@@ -983,6 +985,7 @@ static int _find_parallel_space(struct a
struct lv_segment *prev_lvseg,
uint32_t *allocated, uint32_t needed)
{
+ int skip = 0;
struct pv_map *pvm;
struct pv_area *pva;
struct pv_list *pvl;
@@ -999,6 +1002,7 @@ static int _find_parallel_space(struct a
uint32_t log_len;
struct pv_area *log_area;
unsigned log_needs_allocating;
+ struct alloced_area *aa;
/* Is there enough total space? */
free_pes = pv_maps_size(pvms);
@@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
continue; /* Next PV */
if (alloc != ALLOC_ANYWHERE) {
- /* Don't allocate onto the log pv */
- if (ah->log_count &&
- pvm->pv == ah->log_area.pv)
- continue; /* Next PV */
+ /* Don't allocate onto the log pvs */
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (pvm->pv == aa->pv)
+ skip = 1;
+ if (skip) {
+ skip = 0;
+ continue;
+ }
/* Avoid PVs used by existing parallel areas */
if (parallel_pvs)
@@ -1125,8 +1133,9 @@ static int _find_parallel_space(struct a
if ((contiguous || cling) && (preferred_count < ix_offset))
break;
- log_needs_allocating = (ah->log_count && !ah->log_area.len) ?
- 1 : 0;
+ log_needs_allocating = 0;
+ if (ah->log_count && dm_list_empty(&ah->log_areas))
+ log_needs_allocating = 1;
if (ix + ix_offset < ah->area_count +
(log_needs_allocating ? ah->log_count : 0))
@@ -1199,6 +1208,7 @@ static int _allocate(struct alloc_handle
struct dm_list *pvms;
uint32_t areas_size;
alloc_policy_t alloc;
+ struct alloced_area *aa;
if (allocated >= new_extents && !ah->log_count) {
log_error("_allocate called with no work to do!");
@@ -1264,12 +1274,13 @@ static int _allocate(struct alloc_handle
goto out;
}
- if (ah->log_count && !ah->log_area.len) {
- log_error("Insufficient extents for log allocation "
- "for logical volume %s.",
- lv ? lv->name : "");
- goto out;
- }
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (ah->log_count && !aa->len) {
+ log_error("Insufficient extents for log allocation "
+ "for logical volume %s.",
+ lv ? lv->name : "");
+ goto out;
+ }
r = 1;
@@ -1545,10 +1556,21 @@ int lv_add_mirror_lvs(struct logical_vol
/*
* Turn an empty LV into a mirror log.
+ *
+ * Only for the addition of the first, linear log.
*/
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
{
struct lv_segment *seg;
+ struct alloced_area *log_area;
+
+ dm_list_iterate_items(log_area, &ah->log_areas)
+ break;
+
+ if (!log_area)
+ return 0;
+
+ dm_list_del(&log_area->list);
if (dm_list_size(&log_lv->segments)) {
log_error("Log segments can only be added to an empty LV");
@@ -1558,19 +1580,21 @@ int lv_add_log_segment(struct alloc_hand
if (!(seg = alloc_lv_segment(log_lv->vg->cmd->mem,
get_segtype_from_string(log_lv->vg->cmd,
"striped"),
- log_lv, 0, ah->log_area.len, MIRROR_LOG,
- 0, NULL, 1, ah->log_area.len, 0, 0, 0))) {
+ log_lv, 0, log_area->len, MIRROR_LOG,
+ 0, NULL, 1, log_area->len, 0, 0, 0))) {
log_error("Couldn't allocate new mirror log segment.");
return 0;
}
- if (!set_lv_segment_area_pv(seg, 0, ah->log_area.pv, ah->log_area.pe))
+ if (!set_lv_segment_area_pv(seg, 0, log_area->pv, log_area->pe))
return_0;
dm_list_add(&log_lv->segments, &seg->list);
- log_lv->le_count += ah->log_area.len;
+ log_lv->le_count += log_area->len;
log_lv->size += (uint64_t) log_lv->le_count * log_lv->vg->extent_size;
+ dm_pool_free(ah->mem, log_area);
+
if (log_lv->vg->fid->fmt->ops->lv_setup &&
!log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv))
return_0;
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 10] LVM: make log_area a list
@ 2009-10-08 21:18 ` Jonathan Brassow
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Brassow @ 2009-10-08 21:18 UTC (permalink / raw)
To: lvm-devel
Patch name: lvm-make-log_area-a-list.patch
The 'alloc_handle' structure only has space for one log_area.
We change that to a list to allow an arbitrary number of
log areas.
RFC: Jonathan Brassow <jbrassow@redhat.com>
Index: LVM2/lib/metadata/lv_manip.c
===================================================================
--- LVM2.orig/lib/metadata/lv_manip.c
+++ LVM2/lib/metadata/lv_manip.c
@@ -515,7 +515,7 @@ struct alloc_handle {
struct dm_list *parallel_areas; /* PVs to avoid */
- struct alloced_area log_area; /* Extent used for log */
+ struct dm_list log_areas; /* Extents used for logs */
struct dm_list alloced_areas[0]; /* Lists of areas in each stripe */
};
@@ -582,6 +582,7 @@ static struct alloc_handle *_alloc_init(
ah->alloc = alloc;
ah->area_multiple = calc_area_multiple(segtype, area_count);
+ dm_list_init(&ah->log_areas);
for (s = 0; s < ah->area_count; s++)
dm_list_init(&ah->alloced_areas[s]);
@@ -763,10 +764,11 @@ static int _alloc_parallel_area(struct a
consume_pv_area(areas[s], area_len);
if (log_area) {
- ah->log_area.pv = log_area->map->pv;
- ah->log_area.pe = log_area->start;
- ah->log_area.len = log_len;
- consume_pv_area(log_area, ah->log_area.len);
+ aa[s].pv = log_area->map->pv;
+ aa[s].pe = log_area->start;
+ aa[s].len = log_len;
+ dm_list_add(&ah->log_areas, &aa[s].list);
+ consume_pv_area(log_area, log_len);
}
*ix += area_len * ah->area_multiple;
@@ -983,6 +985,7 @@ static int _find_parallel_space(struct a
struct lv_segment *prev_lvseg,
uint32_t *allocated, uint32_t needed)
{
+ int skip = 0;
struct pv_map *pvm;
struct pv_area *pva;
struct pv_list *pvl;
@@ -999,6 +1002,7 @@ static int _find_parallel_space(struct a
uint32_t log_len;
struct pv_area *log_area;
unsigned log_needs_allocating;
+ struct alloced_area *aa;
/* Is there enough total space? */
free_pes = pv_maps_size(pvms);
@@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
continue; /* Next PV */
if (alloc != ALLOC_ANYWHERE) {
- /* Don't allocate onto the log pv */
- if (ah->log_count &&
- pvm->pv == ah->log_area.pv)
- continue; /* Next PV */
+ /* Don't allocate onto the log pvs */
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (pvm->pv == aa->pv)
+ skip = 1;
+ if (skip) {
+ skip = 0;
+ continue;
+ }
/* Avoid PVs used by existing parallel areas */
if (parallel_pvs)
@@ -1125,8 +1133,9 @@ static int _find_parallel_space(struct a
if ((contiguous || cling) && (preferred_count < ix_offset))
break;
- log_needs_allocating = (ah->log_count && !ah->log_area.len) ?
- 1 : 0;
+ log_needs_allocating = 0;
+ if (ah->log_count && dm_list_empty(&ah->log_areas))
+ log_needs_allocating = 1;
if (ix + ix_offset < ah->area_count +
(log_needs_allocating ? ah->log_count : 0))
@@ -1199,6 +1208,7 @@ static int _allocate(struct alloc_handle
struct dm_list *pvms;
uint32_t areas_size;
alloc_policy_t alloc;
+ struct alloced_area *aa;
if (allocated >= new_extents && !ah->log_count) {
log_error("_allocate called with no work to do!");
@@ -1264,12 +1274,13 @@ static int _allocate(struct alloc_handle
goto out;
}
- if (ah->log_count && !ah->log_area.len) {
- log_error("Insufficient extents for log allocation "
- "for logical volume %s.",
- lv ? lv->name : "");
- goto out;
- }
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (ah->log_count && !aa->len) {
+ log_error("Insufficient extents for log allocation "
+ "for logical volume %s.",
+ lv ? lv->name : "");
+ goto out;
+ }
r = 1;
@@ -1545,10 +1556,21 @@ int lv_add_mirror_lvs(struct logical_vol
/*
* Turn an empty LV into a mirror log.
+ *
+ * Only for the addition of the first, linear log.
*/
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
{
struct lv_segment *seg;
+ struct alloced_area *log_area;
+
+ dm_list_iterate_items(log_area, &ah->log_areas)
+ break;
+
+ if (!log_area)
+ return 0;
+
+ dm_list_del(&log_area->list);
if (dm_list_size(&log_lv->segments)) {
log_error("Log segments can only be added to an empty LV");
@@ -1558,19 +1580,21 @@ int lv_add_log_segment(struct alloc_hand
if (!(seg = alloc_lv_segment(log_lv->vg->cmd->mem,
get_segtype_from_string(log_lv->vg->cmd,
"striped"),
- log_lv, 0, ah->log_area.len, MIRROR_LOG,
- 0, NULL, 1, ah->log_area.len, 0, 0, 0))) {
+ log_lv, 0, log_area->len, MIRROR_LOG,
+ 0, NULL, 1, log_area->len, 0, 0, 0))) {
log_error("Couldn't allocate new mirror log segment.");
return 0;
}
- if (!set_lv_segment_area_pv(seg, 0, ah->log_area.pv, ah->log_area.pe))
+ if (!set_lv_segment_area_pv(seg, 0, log_area->pv, log_area->pe))
return_0;
dm_list_add(&log_lv->segments, &seg->list);
- log_lv->le_count += ah->log_area.len;
+ log_lv->le_count += log_area->len;
log_lv->size += (uint64_t) log_lv->le_count * log_lv->vg->extent_size;
+ dm_pool_free(ah->mem, log_area);
+
if (log_lv->vg->fid->fmt->ops->lv_setup &&
!log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv))
return_0;
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2 of 10] LVM: make log_area a list
2009-10-08 21:18 ` Jonathan Brassow
@ 2009-10-13 1:48 ` malahal
-1 siblings, 0 replies; 11+ messages in thread
From: malahal @ 2009-10-13 1:48 UTC (permalink / raw)
To: dm-devel, lvm-devel
Jonathan Brassow [jbrassow@redhat.com] wrote:
> Patch name: lvm-make-log_area-a-list.patch
>
> The 'alloc_handle' structure only has space for one log_area.
> We change that to a list to allow an arbitrary number of
> log areas.
>
> RFC: Jonathan Brassow <jbrassow@redhat.com>
>
> @@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
> continue; /* Next PV */
>
> if (alloc != ALLOC_ANYWHERE) {
> - /* Don't allocate onto the log pv */
> - if (ah->log_count &&
> - pvm->pv == ah->log_area.pv)
> - continue; /* Next PV */
> + /* Don't allocate onto the log pvs */
> + dm_list_iterate_items(aa, &ah->log_areas)
> + if (pvm->pv == aa->pv)
> + skip = 1;
You can 'break' soon after setting skip.
> @@ -1199,6 +1208,7 @@ static int _allocate(struct alloc_handle
> struct dm_list *pvms;
> uint32_t areas_size;
> alloc_policy_t alloc;
> + struct alloced_area *aa;
>
> if (allocated >= new_extents && !ah->log_count) {
> log_error("_allocate called with no work to do!");
> @@ -1264,12 +1274,13 @@ static int _allocate(struct alloc_handle
> goto out;
> }
>
> - if (ah->log_count && !ah->log_area.len) {
> - log_error("Insufficient extents for log allocation "
> - "for logical volume %s.",
> - lv ? lv->name : "");
> - goto out;
> - }
> + dm_list_iterate_items(aa, &ah->log_areas)
> + if (ah->log_count && !aa->len) {
ah->log_count can be checked outside of the list iterate.
> + log_error("Insufficient extents for log allocation "
> + "for logical volume %s.",
> + lv ? lv->name : "");
> + goto out;
> + }
> int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
> {
> struct lv_segment *seg;
> + struct alloced_area *log_area;
> +
> + dm_list_iterate_items(log_area, &ah->log_areas)
> + break;
Using the list iterator to get the first element looks odd!
Should we use dm_list_first and dm_list_item? Or just have
dm_list_first_item()???
--
lvm-devel mailing list
lvm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/lvm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2 of 10] LVM: make log_area a list
@ 2009-10-13 1:48 ` malahal
0 siblings, 0 replies; 11+ messages in thread
From: malahal @ 2009-10-13 1:48 UTC (permalink / raw)
To: lvm-devel
Jonathan Brassow [jbrassow at redhat.com] wrote:
> Patch name: lvm-make-log_area-a-list.patch
>
> The 'alloc_handle' structure only has space for one log_area.
> We change that to a list to allow an arbitrary number of
> log areas.
>
> RFC: Jonathan Brassow <jbrassow@redhat.com>
>
> @@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
> continue; /* Next PV */
>
> if (alloc != ALLOC_ANYWHERE) {
> - /* Don't allocate onto the log pv */
> - if (ah->log_count &&
> - pvm->pv == ah->log_area.pv)
> - continue; /* Next PV */
> + /* Don't allocate onto the log pvs */
> + dm_list_iterate_items(aa, &ah->log_areas)
> + if (pvm->pv == aa->pv)
> + skip = 1;
You can 'break' soon after setting skip.
> @@ -1199,6 +1208,7 @@ static int _allocate(struct alloc_handle
> struct dm_list *pvms;
> uint32_t areas_size;
> alloc_policy_t alloc;
> + struct alloced_area *aa;
>
> if (allocated >= new_extents && !ah->log_count) {
> log_error("_allocate called with no work to do!");
> @@ -1264,12 +1274,13 @@ static int _allocate(struct alloc_handle
> goto out;
> }
>
> - if (ah->log_count && !ah->log_area.len) {
> - log_error("Insufficient extents for log allocation "
> - "for logical volume %s.",
> - lv ? lv->name : "");
> - goto out;
> - }
> + dm_list_iterate_items(aa, &ah->log_areas)
> + if (ah->log_count && !aa->len) {
ah->log_count can be checked outside of the list iterate.
> + log_error("Insufficient extents for log allocation "
> + "for logical volume %s.",
> + lv ? lv->name : "");
> + goto out;
> + }
> int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
> {
> struct lv_segment *seg;
> + struct alloced_area *log_area;
> +
> + dm_list_iterate_items(log_area, &ah->log_areas)
> + break;
Using the list iterator to get the first element looks odd!
Should we use dm_list_first and dm_list_item? Or just have
dm_list_first_item()???
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2 of 10] LVM: make log_area a list
2009-10-13 1:48 ` malahal
(?)
@ 2009-10-13 21:28 ` Jonathan Brassow
2009-10-14 17:16 ` malahal
-1 siblings, 1 reply; 11+ messages in thread
From: Jonathan Brassow @ 2009-10-13 21:28 UTC (permalink / raw)
To: lvm-devel
On Oct 12, 2009, at 8:48 PM, malahal at us.ibm.com wrote:
> Jonathan Brassow [jbrassow at redhat.com] wrote:
>> Patch name: lvm-make-log_area-a-list.patch
>>
>> The 'alloc_handle' structure only has space for one log_area.
>> We change that to a list to allow an arbitrary number of
>> log areas.
>>
>> RFC: Jonathan Brassow <jbrassow@redhat.com>
>>
>> @@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
>> continue; /* Next PV */
>>
>> if (alloc != ALLOC_ANYWHERE) {
>> - /* Don't allocate onto the log pv */
>> - if (ah->log_count &&
>> - pvm->pv == ah->log_area.pv)
>> - continue; /* Next PV */
>> + /* Don't allocate onto the log pvs */
>> + dm_list_iterate_items(aa, &ah->log_areas)
>> + if (pvm->pv == aa->pv)
>> + skip = 1;
>
> You can 'break' soon after
> setting skip.
If I use 'break' won't that break out of the 'dm_list_iterate_items'
and not the enclosing loop - giving an incorrect result?
>
>> @@ -1199,6 +1208,7 @@ static int _allocate(struct alloc_handle
>> struct dm_list *pvms;
>> uint32_t areas_size;
>> alloc_policy_t alloc;
>> + struct alloced_area *aa;
>>
>> if (allocated >= new_extents && !ah->log_count) {
>> log_error("_allocate called with no work to do!");
>> @@ -1264,12 +1274,13 @@ static int _allocate(struct alloc_handle
>> goto out;
>> }
>>
>> - if (ah->log_count && !ah->log_area.len) {
>> - log_error("Insufficient extents for log allocation "
>> - "for logical volume %s.",
>> - lv ? lv->name : "");
>> - goto out;
>> - }
>> + dm_list_iterate_items(aa, &ah->log_areas)
>> + if (ah->log_count && !aa->len) {
>
> ah->log_count can be checked outside of the list iterate.
I thought the code looked ugly with three levels of indentation; but
yes, I think that could save some cycles. (I've changed it in my
local patch.)
>
>> + log_error("Insufficient extents for log allocation "
>> + "for logical volume %s.",
>> + lv ? lv->name : "");
>> + goto out;
>> + }
>> int lv_add_log_segment(struct alloc_handle *ah, struct
>> logical_volume *log_lv)
>> {
>> struct lv_segment *seg;
>> + struct alloced_area *log_area;
>> +
>> + dm_list_iterate_items(log_area, &ah->log_areas)
>> + break;
>
> Using the list iterator to get the first element looks odd!
> Should we use dm_list_first and dm_list_item? Or just have
> dm_list_first_item()???
I thought the same thing. :) Perhaps I should introduce another
patch adding that macro...
brassow
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2 of 10] LVM: make log_area a list
2009-10-13 21:28 ` Jonathan Brassow
@ 2009-10-14 17:16 ` malahal
2009-10-14 18:58 ` Jonathan Brassow
0 siblings, 1 reply; 11+ messages in thread
From: malahal @ 2009-10-14 17:16 UTC (permalink / raw)
To: lvm-devel
Jonathan Brassow [jbrassow at redhat.com] wrote:
>
> On Oct 12, 2009, at 8:48 PM, malahal at us.ibm.com wrote:
>
>> Jonathan Brassow [jbrassow at redhat.com] wrote:
>>> Patch name: lvm-make-log_area-a-list.patch
>>>
>>> The 'alloc_handle' structure only has space for one log_area.
>>> We change that to a list to allow an arbitrary number of
>>> log areas.
>>>
>>> RFC: Jonathan Brassow <jbrassow@redhat.com>
>>>
>>> @@ -1061,10 +1065,14 @@ static int _find_parallel_space(struct a
>>> continue; /* Next PV */
>>>
>>> if (alloc != ALLOC_ANYWHERE) {
>>> - /* Don't allocate onto the log pv */
>>> - if (ah->log_count &&
>>> - pvm->pv == ah->log_area.pv)
>>> - continue; /* Next PV */
>>> + /* Don't allocate onto the log pvs */
>>> + dm_list_iterate_items(aa, &ah->log_areas)
>>> + if (pvm->pv == aa->pv)
>>> + skip = 1;
>>
>> You can 'break' soon after setting
>> skip.
>
> If I use 'break' won't that break out of the 'dm_list_iterate_items' and
> not the enclosing loop - giving an incorrect result?
IIRC, there are two dm_list_iterate_items loops. You can 'break' from the
inner loop after setting 'skip=1' and the next statement will check that
skip is set and execute 'continue' for the outer loop.
My understanding is that the current code executes the inner loop to
completion every time.
Thanks, Malahal.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2 of 10] LVM: make log_area a list
2009-10-14 17:16 ` malahal
@ 2009-10-14 18:58 ` Jonathan Brassow
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Brassow @ 2009-10-14 18:58 UTC (permalink / raw)
To: lvm-devel
On Oct 14, 2009, at 12:16 PM, malahal at us.ibm.com wrote:
> My understanding is that the current code executes the inner loop to
> completion every time.
I see what you are saying. Ok, fixed in my local patch.
brassow
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 10] LVM: make log_area a list
2009-10-08 21:18 ` Jonathan Brassow
(?)
(?)
@ 2009-10-15 22:47 ` Alasdair G Kergon
-1 siblings, 0 replies; 11+ messages in thread
From: Alasdair G Kergon @ 2009-10-15 22:47 UTC (permalink / raw)
To: lvm-devel
On Thu, Oct 08, 2009 at 04:18:36PM -0500, Jon Brassow wrote:
> + int skip = 0;
> + dm_list_iterate_items(aa, &ah->log_areas)
> + if (pvm->pv == aa->pv)
> + skip = 1;
> + if (skip) {
> + skip = 0;
> + continue;
> + }
If 'skip' is just to break out of nested loops, please use something
like 'goto next_pv' instead.
Alasdair
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 10] LVM: make log_area a list
2009-10-08 21:18 ` Jonathan Brassow
` (2 preceding siblings ...)
(?)
@ 2009-10-15 23:18 ` Alasdair G Kergon
2009-10-21 20:25 ` Jonathan Brassow
-1 siblings, 1 reply; 11+ messages in thread
From: Alasdair G Kergon @ 2009-10-15 23:18 UTC (permalink / raw)
To: lvm-devel
On Thu, Oct 08, 2009 at 04:18:36PM -0500, Jon Brassow wrote:
> - struct alloced_area log_area; /* Extent used for log */
> + struct dm_list log_areas; /* Extents used for logs */
> struct dm_list alloced_areas[0]; /* Lists of areas in each stripe */
Rather than storing the log areas differently (in a list) from the other areas
(in an array), I'd prefer them all to be stored the same way.
I.e. In a simple contiguous 2-leg mirror plus mirrored log, you'd get
leg1 as first item on alloced_areas[0] list,
leg2 as first item on alloced_areas[1] list,
log leg1 as first item on log_areas list,
log leg2 as second item on log_areas list.
I'd prefer to see:
leg1 as first item on alloced_areas[0] list,
leg2 as first item on alloced_areas[1] list,
log leg1 as first item on log_areas[0] list,
log leg2 as first item on log_areas[1] list.
and of course log_areas[0] can be the same as alloced_areas[2].
This should be both simpler (logs are less of a special case and
like any other area may include more than 1 segment) and more general
(we're asking to allocate several parallel areas, with different lengths
but sorted largest first and with different allocation constraints
applying to some of them).
Alasdair
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 10] LVM: make log_area a list
2009-10-15 23:18 ` Alasdair G Kergon
@ 2009-10-21 20:25 ` Jonathan Brassow
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Brassow @ 2009-10-21 20:25 UTC (permalink / raw)
To: lvm-devel
agk,
I've been thinking about this... What I'd really like to see done is a
two phase allocation for mirrors. The first phase would be for the
legs and the second phase would be for the log(s). If we cleaned
things up in this way, there would be no need for the log_area(s) at
all. This would involve changing the code around a bit more, but
would give us an easier path to adhering to various allocation
policies. Also, it would make function behave more like their
original intent, rather than having these extra bolt-on items that
seem to bloat functions every time we add a new feature. If you are
keen on this approach, would you settle for the posted patch for now?
In (weak) defense of the patch as it's written, please note that the
'areas' field is an /array/ of 'dm_list' type. Each element in the
array is for a specific leg. The elements are lists presumably to
handle multiple segments per leg. Logs, on the other hand, are never
more than one segment, so I don't need something as complicated as an
array of lists. Either an array or a list would be fine. I thought it
would be easier to use the list vs. the array. Note also that
_find_parallel_areas cycles through the log PVs to avoid them if
possible... which complicates putting them together with the 'areas'
array of lists.
If you still want me to attempt doing it as you describe, then I
will. Otherwise, I'd rather avoid doing this intermediate step and
move straight to a two phase allocation.
Your thoughts?
brassow
On Oct 15, 2009, at 6:18 PM, Alasdair G Kergon wrote:
> On Thu, Oct 08, 2009 at 04:18:36PM -0500, Jon Brassow wrote:
>> - struct alloced_area log_area; /* Extent used for log */
>> + struct dm_list log_areas; /* Extents used for logs */
>> struct dm_list alloced_areas[0]; /* Lists of areas in each stripe */
>
> Rather than storing the log areas differently (in a list) from the
> other areas
> (in an array), I'd prefer them all to be stored the same way.
>
> I.e. In a simple contiguous 2-leg mirror plus mirrored log, you'd get
> leg1 as first item on alloced_areas[0] list,
> leg2 as first item on alloced_areas[1] list,
> log leg1 as first item on log_areas list,
> log leg2 as second item on log_areas list.
>
> I'd prefer to see:
> leg1 as first item on alloced_areas[0] list,
> leg2 as first item on alloced_areas[1] list,
> log leg1 as first item on log_areas[0] list,
> log leg2 as first item on log_areas[1] list.
> and of course log_areas[0] can be the same as alloced_areas[2].
>
> This should be both simpler (logs are less of a special case and
> like any other area may include more than 1 segment) and more general
> (we're asking to allocate several parallel areas, with different
> lengths
> but sorted largest first and with different allocation constraints
> applying to some of them).
>
> Alasdair
>
> --
> lvm-devel mailing list
> lvm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/lvm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 10] LVM: make log_area a list
@ 2010-01-20 2:21 Jonathan Brassow
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Brassow @ 2010-01-20 2:21 UTC (permalink / raw)
To: lvm-devel
Patch name: lvm-make-log_area-a-list.patch
The 'alloc_handle' structure only has space for one log_area.
We change that to a list to allow an arbitrary number of
log areas.
RFC: Jonathan Brassow <jbrassow@redhat.com>
Index: LVM2/lib/metadata/lv_manip.c
===================================================================
--- LVM2.orig/lib/metadata/lv_manip.c
+++ LVM2/lib/metadata/lv_manip.c
@@ -515,7 +515,7 @@ struct alloc_handle {
struct dm_list *parallel_areas; /* PVs to avoid */
- struct alloced_area log_area; /* Extent used for log */
+ struct dm_list log_areas; /* Extents used for logs */
struct dm_list alloced_areas[0]; /* Lists of areas in each stripe */
};
@@ -582,6 +582,7 @@ static struct alloc_handle *_alloc_init(
ah->alloc = alloc;
ah->area_multiple = calc_area_multiple(segtype, area_count);
+ dm_list_init(&ah->log_areas);
for (s = 0; s < ah->area_count; s++)
dm_list_init(&ah->alloced_areas[s]);
@@ -763,10 +764,11 @@ static int _alloc_parallel_area(struct a
consume_pv_area(areas[s], area_len);
if (log_area) {
- ah->log_area.pv = log_area->map->pv;
- ah->log_area.pe = log_area->start;
- ah->log_area.len = log_len;
- consume_pv_area(log_area, ah->log_area.len);
+ aa[s].pv = log_area->map->pv;
+ aa[s].pe = log_area->start;
+ aa[s].len = log_len;
+ dm_list_add(&ah->log_areas, &aa[s].list);
+ consume_pv_area(log_area, log_len);
}
*ix += area_len * ah->area_multiple;
@@ -999,6 +1001,7 @@ static int _find_parallel_space(struct a
uint32_t log_len;
struct pv_area *log_area;
unsigned log_needs_allocating;
+ struct alloced_area *aa;
/* Is there enough total space? */
free_pes = pv_maps_size(pvms);
@@ -1061,10 +1064,10 @@ static int _find_parallel_space(struct a
continue; /* Next PV */
if (alloc != ALLOC_ANYWHERE) {
- /* Don't allocate onto the log pv */
- if (ah->log_count &&
- pvm->pv == ah->log_area.pv)
- continue; /* Next PV */
+ /* Don't allocate onto the log pvs */
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (pvm->pv == aa->pv)
+ goto next_pv;
/* Avoid PVs used by existing parallel areas */
if (parallel_pvs)
@@ -1123,8 +1126,9 @@ static int _find_parallel_space(struct a
if ((contiguous || cling) && (preferred_count < ix_offset))
break;
- log_needs_allocating = (ah->log_count && !ah->log_area.len) ?
- 1 : 0;
+ log_needs_allocating = 0;
+ if (ah->log_count && dm_list_empty(&ah->log_areas))
+ log_needs_allocating = 1;
if (ix + ix_offset < ah->area_count +
(log_needs_allocating ? ah->log_count : 0))
@@ -1197,6 +1201,7 @@ static int _allocate(struct alloc_handle
struct dm_list *pvms;
uint32_t areas_size;
alloc_policy_t alloc;
+ struct alloced_area *aa;
if (allocated >= new_extents && !ah->log_count) {
log_error("_allocate called with no work to do!");
@@ -1262,11 +1267,14 @@ static int _allocate(struct alloc_handle
goto out;
}
- if (ah->log_count && !ah->log_area.len) {
- log_error("Insufficient extents for log allocation "
- "for logical volume %s.",
- lv ? lv->name : "");
- goto out;
+ if (ah->log_count) {
+ dm_list_iterate_items(aa, &ah->log_areas)
+ if (!aa->len) {
+ log_error("Insufficient extents for log "
+ "allocation for logical volume %s.",
+ lv ? lv->name : "");
+ goto out;
+ }
}
r = 1;
@@ -1543,10 +1551,23 @@ int lv_add_mirror_lvs(struct logical_vol
/*
* Turn an empty LV into a mirror log.
+ *
+ * Only for the addition of the first, linear log.
*/
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv)
{
+ struct dm_list *l;
struct lv_segment *seg;
+ struct alloced_area *log_area, no_area;
+
+ l = dm_list_first(&ah->log_areas);
+ if (l) {
+ log_area = dm_list_item(l, struct alloced_area);
+ dm_list_del(&log_area->list);
+ } else {
+ log_area = &no_area;
+ memset(log_area, 0, sizeof(struct alloced_area));
+ }
if (dm_list_size(&log_lv->segments)) {
log_error("Log segments can only be added to an empty LV");
@@ -1556,19 +1577,22 @@ int lv_add_log_segment(struct alloc_hand
if (!(seg = alloc_lv_segment(log_lv->vg->cmd->mem,
get_segtype_from_string(log_lv->vg->cmd,
"striped"),
- log_lv, 0, ah->log_area.len, MIRROR_LOG,
- 0, NULL, 1, ah->log_area.len, 0, 0, 0))) {
+ log_lv, 0, log_area->len, MIRROR_LOG,
+ 0, NULL, 1, log_area->len, 0, 0, 0))) {
log_error("Couldn't allocate new mirror log segment.");
return 0;
}
- if (!set_lv_segment_area_pv(seg, 0, ah->log_area.pv, ah->log_area.pe))
+ if (!set_lv_segment_area_pv(seg, 0, log_area->pv, log_area->pe))
return_0;
dm_list_add(&log_lv->segments, &seg->list);
- log_lv->le_count += ah->log_area.len;
+ log_lv->le_count += log_area->len;
log_lv->size += (uint64_t) log_lv->le_count * log_lv->vg->extent_size;
+ if (log_area != &no_area)
+ dm_pool_free(ah->mem, log_area);
+
if (log_lv->vg->fid->fmt->ops->lv_setup &&
!log_lv->vg->fid->fmt->ops->lv_setup(log_lv->vg->fid, log_lv))
return_0;
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2010-01-20 2:21 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-08 21:18 [PATCH 2 of 10] LVM: make log_area a list Jonathan Brassow
2009-10-08 21:18 ` Jonathan Brassow
2009-10-13 1:48 ` malahal
2009-10-13 1:48 ` malahal
2009-10-13 21:28 ` Jonathan Brassow
2009-10-14 17:16 ` malahal
2009-10-14 18:58 ` Jonathan Brassow
2009-10-15 22:47 ` Alasdair G Kergon
2009-10-15 23:18 ` Alasdair G Kergon
2009-10-21 20:25 ` Jonathan Brassow
-- strict thread matches above, loose matches on Subject: below --
2010-01-20 2:21 Jonathan Brassow
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.