From: agk@sourceware.org <agk@sourceware.org>
To: lvm-devel@redhat.com
Subject: LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m ...
Date: 25 Mar 2010 21:19:27 -0000 [thread overview]
Message-ID: <20100325211927.29856.qmail@sourceware.org> (raw)
CVSROOT: /cvs/lvm2
Module name: LVM2
Changes by: agk at sourceware.org 2010-03-25 21:19:27
Modified files:
. : WHATS_NEW
lib/metadata : lv_manip.c pv_map.c pv_map.h
Log message:
Allow ALLOC_ANYWHERE to split contiguous areas.
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.1481&r2=1.1482
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.215&r2=1.216
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/pv_map.c.diff?cvsroot=lvm2&r1=1.35&r2=1.36
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/pv_map.h.diff?cvsroot=lvm2&r1=1.12&r2=1.13
--- LVM2/WHATS_NEW 2010/03/25 18:22:39 1.1481
+++ LVM2/WHATS_NEW 2010/03/25 21:19:26 1.1482
@@ -1,5 +1,6 @@
Version 2.02.63 -
================================
+ Allow ALLOC_ANYWHERE to split contiguous areas.
Use INTERNAL_ERROR for internal errors throughout tree.
Add some assertions to allocation code.
Introduce pv_area_used into allocation algorithm and add debug messages.
--- LVM2/lib/metadata/lv_manip.c 2010/03/25 18:16:55 1.215
+++ LVM2/lib/metadata/lv_manip.c 2010/03/25 21:19:27 1.216
@@ -1018,7 +1018,7 @@
struct pv_list *pvl;
unsigned already_found_one = 0;
unsigned contiguous = 0, cling = 0, preferred_count = 0;
- unsigned ix;
+ unsigned ix, last_ix;
unsigned ix_offset = 0; /* Offset for non-preferred allocations */
unsigned ix_log_offset; /* Offset to start of areas to use for log */
unsigned too_small_for_log_count; /* How many too small for log? */
@@ -1085,99 +1085,125 @@
log_needs_allocating = (ah->log_area_count &&
dm_list_empty(&ah->alloced_areas[ah->area_count])) ? 1 : 0;
- /*
- * Put the smallest area of each PV that is at least the
- * size we need into areas array. If there isn't one
- * that fits completely and we're allowed more than one
- * LV segment, then take the largest remaining instead.
- */
- dm_list_iterate_items(pvm, pvms) {
- if (dm_list_empty(&pvm->areas))
- continue; /* Next PV */
-
- if (alloc != ALLOC_ANYWHERE) {
- /* Don't allocate onto the log pv */
- if (ah->log_area_count)
- dm_list_iterate_items(aa, &ah->alloced_areas[ah->area_count])
- for (s = 0; s < ah->log_area_count; s++)
- if (!aa[s].pv)
+ do {
+ /*
+ * Provide for escape from the loop if no progress is made.
+ * This should not happen: ALLOC_ANYWHERE should be able to use
+ * all available space. (If there aren't enough extents, the code
+ * should not reach this point.)
+ */
+ last_ix = ix;
+
+ /*
+ * Put the smallest area of each PV that is at least the
+ * size we need into areas array. If there isn't one
+ * that fits completely and we're allowed more than one
+ * LV segment, then take the largest remaining instead.
+ */
+ dm_list_iterate_items(pvm, pvms) {
+ if (dm_list_empty(&pvm->areas))
+ continue; /* Next PV */
+
+ if (alloc != ALLOC_ANYWHERE) {
+ /* Don't allocate onto the log pv */
+ if (ah->log_area_count)
+ dm_list_iterate_items(aa, &ah->alloced_areas[ah->area_count])
+ for (s = 0; s < ah->log_area_count; s++)
+ if (!aa[s].pv)
+ goto next_pv;
+
+ /* Avoid PVs used by existing parallel areas */
+ if (parallel_pvs)
+ dm_list_iterate_items(pvl, parallel_pvs)
+ if (pvm->pv == pvl->pv)
goto next_pv;
+ }
- /* Avoid PVs used by existing parallel areas */
- if (parallel_pvs)
- dm_list_iterate_items(pvl, parallel_pvs)
- if (pvm->pv == pvl->pv)
+ already_found_one = 0;
+ /* First area in each list is the largest */
+ dm_list_iterate_items(pva, &pvm->areas) {
+ /* Skip fully-reserved areas (which are not currently removed from the list). */
+ if (!pva->unreserved)
+ continue;
+ if (contiguous) {
+ if (prev_lvseg &&
+ _check_contiguous(ah->cmd,
+ prev_lvseg,
+ pva, *areas_ptr,
+ *areas_size_ptr)) {
+ preferred_count++;
goto next_pv;
- }
-
- already_found_one = 0;
- /* First area in each list is the largest */
- dm_list_iterate_items(pva, &pvm->areas) {
- if (contiguous) {
- if (prev_lvseg &&
- _check_contiguous(ah->cmd,
- prev_lvseg,
- pva, *areas_ptr,
- *areas_size_ptr)) {
- preferred_count++;
- goto next_pv;
+ }
+ continue;
}
- continue;
- }
- if (cling) {
- if (prev_lvseg &&
- _check_cling(ah->cmd,
- prev_lvseg,
- pva, *areas_ptr,
- *areas_size_ptr)) {
- preferred_count++;
+ if (cling) {
+ if (prev_lvseg &&
+ _check_cling(ah->cmd,
+ prev_lvseg,
+ pva, *areas_ptr,
+ *areas_size_ptr)) {
+ preferred_count++;
+ }
+ goto next_pv;
}
- goto next_pv;
- }
-
- /* Is it big enough on its own? */
- if (pva->count * ah->area_multiple <
- max_parallel - *allocated &&
- ((!can_split && !ah->log_area_count) ||
- (already_found_one &&
- !(alloc == ALLOC_ANYWHERE))))
- goto next_pv;
-
- /*
- * Except with ALLOC_ANYWHERE, replace first area with this
- * one which is smaller but still big enough.
- */
- if (!already_found_one ||
- alloc == ALLOC_ANYWHERE) {
- ix++;
- already_found_one = 1;
- }
- if (ix + ix_offset - 1 < ah->area_count)
- required = (max_parallel - *allocated) / ah->area_multiple;
- else
- required = ah->log_len;
+ /* Is it big enough on its own? */
+ if (pva->unreserved * ah->area_multiple <
+ max_parallel - *allocated &&
+ ((!can_split && !ah->log_area_count) ||
+ (already_found_one &&
+ !(alloc == ALLOC_ANYWHERE))))
+ goto next_pv;
- if (required > pva->count)
- required = pva->count;
+ /*
+ * Except with ALLOC_ANYWHERE, replace first area with this
+ * one which is smaller but still big enough.
+ */
+ if (!already_found_one ||
+ alloc == ALLOC_ANYWHERE) {
+ ix++;
+ already_found_one = 1;
+ }
- /* Expand areas array if needed after an area was split. */
- if (ix + ix_offset > *areas_size_ptr) {
- *areas_size_ptr *= 2;
- *areas_ptr = dm_realloc(*areas_ptr, sizeof(**areas_ptr) * (*areas_size_ptr));
+ if (ix + ix_offset - 1 < ah->area_count)
+ required = (max_parallel - *allocated) / ah->area_multiple;
+ else
+ required = ah->log_len;
+
+ if (alloc == ALLOC_ANYWHERE) {
+ /*
+ * Update amount unreserved - effectively splitting an area
+ * into two or more parts. If the whole stripe doesn't fit,
+ * reduce amount we're looking for.
+ */
+ if (required >= pva->unreserved) {
+ required = pva->unreserved;
+ pva->unreserved = 0;
+ } else {
+ pva->unreserved -= required;
+ reinsert_reduced_pv_area(pva);
+ }
+ } else if (required > pva->count)
+ required = pva->count;
+
+ /* Expand areas array if needed after an area was split. */
+ if (ix + ix_offset > *areas_size_ptr) {
+ *areas_size_ptr *= 2;
+ *areas_ptr = dm_realloc(*areas_ptr, sizeof(**areas_ptr) * (*areas_size_ptr));
+ }
+ (*areas_ptr)[ix + ix_offset - 1].pva = pva;
+ (*areas_ptr)[ix + ix_offset - 1].used = required;
+ log_debug("Trying allocation area %" PRIu32 " on %s start PE %" PRIu32
+ " length %" PRIu32 " leaving %" PRIu32 ".",
+ ix + ix_offset - 1, dev_name(pva->map->pv->dev), pva->start, required,
+ (alloc == ALLOC_ANYWHERE) ? pva->unreserved : pva->count - required);
}
- (*areas_ptr)[ix + ix_offset - 1].pva = pva;
- (*areas_ptr)[ix + ix_offset - 1].used = required;
- log_debug("Trying allocation area %" PRIu32 " on %s start PE %" PRIu32
- " length %" PRIu32 " leaving %" PRIu32 ".",
- ix + ix_offset - 1, dev_name(pva->map->pv->dev), pva->start, required,
- pva->count - required);
+ next_pv:
+ if (ix + ix_offset >= ah->area_count + (log_needs_allocating ? ah->log_area_count : 0))
+ break;
}
- next_pv:
- if (ix + ix_offset >= ah->area_count + (log_needs_allocating ? ah->log_area_count : 0))
- break;
- }
+ } while (alloc == ALLOC_ANYWHERE && last_ix != ix && ix < ah->area_count + (log_needs_allocating ? ah->log_area_count : 0));
if ((contiguous || cling) && (preferred_count < ix_offset))
break;
@@ -1211,7 +1237,6 @@
if (ix + ix_offset < ah->area_count +
(log_needs_allocating ? ah->log_area_count +
too_small_for_log_count : 0))
- /* FIXME With ALLOC_ANYWHERE, need to split areas */
break;
if (!_alloc_parallel_area(ah, max_parallel, *areas_ptr, allocated,
--- LVM2/lib/metadata/pv_map.c 2010/03/16 14:37:38 1.35
+++ LVM2/lib/metadata/pv_map.c 2010/03/25 21:19:27 1.36
@@ -24,19 +24,25 @@
*
* FIXME Cope with overlap.
*/
-static void _insert_area(struct dm_list *head, struct pv_area *a)
+static void _insert_area(struct dm_list *head, struct pv_area *a, unsigned reduced)
{
struct pv_area *pva;
-
- dm_list_iterate_items(pva, head) {
- if (a->count > pva->count)
+ uint32_t count = reduced ? a->unreserved : a->count;
+
+ dm_list_iterate_items(pva, head)
+ if (count > pva->count)
break;
- }
dm_list_add(&pva->list, &a->list);
a->map->pe_count += a->count;
}
+static void _remove_area(struct pv_area *a)
+{
+ dm_list_del(&a->list);
+ a->map->pe_count -= a->count;
+}
+
static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
uint32_t start, uint32_t length)
{
@@ -50,7 +56,8 @@
pva->map = pvm;
pva->start = start;
pva->count = length;
- _insert_area(&pvm->areas, pva);
+ pva->unreserved = pva->count;
+ _insert_area(&pvm->areas, pva, 0);
return 1;
}
@@ -184,8 +191,7 @@
void consume_pv_area(struct pv_area *pva, uint32_t to_go)
{
- dm_list_del(&pva->list);
- pva->map->pe_count -= pva->count;
+ _remove_area(pva);
assert(to_go <= pva->count);
@@ -193,10 +199,21 @@
/* split the area */
pva->start += to_go;
pva->count -= to_go;
- _insert_area(&pva->map->areas, pva);
+ pva->unreserved = pva->count;
+ _insert_area(&pva->map->areas, pva, 0);
}
}
+/*
+ * Remove an area from list and reinsert it based on its new smaller size
+ * after a provisional allocation.
+ */
+void reinsert_reduced_pv_area(struct pv_area *pva)
+{
+ _remove_area(pva);
+ _insert_area(&pva->map->areas, pva, 1);
+}
+
uint32_t pv_maps_size(struct dm_list *pvms)
{
struct pv_map *pvm;
--- LVM2/lib/metadata/pv_map.h 2010/03/25 02:40:09 1.12
+++ LVM2/lib/metadata/pv_map.h 2010/03/25 21:19:27 1.13
@@ -31,6 +31,9 @@
uint32_t start;
uint32_t count;
+ /* Number of extents unreserved during ALLOC_ANYWHERE allocation. */
+ uint32_t unreserved;
+
struct dm_list list; /* pv_map.areas */
};
@@ -66,5 +69,6 @@
void reinsert_reduced_pv_area(struct pv_area *pva);
uint32_t pv_maps_size(struct dm_list *pvms);
+void reinsert_reduced_pv_area(struct pv_area *pva);
#endif
next reply other threads:[~2010-03-25 21:19 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-25 21:19 agk [this message]
-- strict thread matches above, loose matches on Subject: below --
2012-02-23 17:36 LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m jbrassow
2012-02-23 3:57 jbrassow
2012-02-15 15:18 zkabelac
2012-02-08 13:05 zkabelac
2012-02-01 2:10 agk
2011-10-22 16:42 zkabelac
2011-09-06 18:49 agk
2011-08-18 19:41 jbrassow
2011-08-11 3:29 jbrassow
2011-06-23 14:01 jbrassow
2011-04-09 19:05 zkabelac
2011-01-24 14:19 agk
2011-01-11 17:05 jbrassow
2010-10-14 20:03 jbrassow
2010-04-23 19:27 snitzer
2010-04-09 1:00 agk
2010-03-25 2:31 agk
2010-01-08 22:32 jbrassow
2010-01-11 13:34 ` Zdenek Kabelac
2009-05-13 21:29 mbroz
2009-05-13 21:28 mbroz
2009-04-21 14:32 mbroz
2009-04-07 10:20 mbroz
2008-03-28 19:08 wysochanski
2008-01-26 0:25 agk
2008-01-18 22:00 agk
2007-12-20 18:55 agk
2007-08-28 16:14 wysochanski
2007-08-03 21:22 wysochanski
2006-12-13 3:39 agk
2006-10-23 15:54 agk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100325211927.29856.qmail@sourceware.org \
--to=agk@sourceware.org \
--cc=lvm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.