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

Improve segment merge/split code.

This commit is contained in:
Alasdair Kergon 2003-09-15 18:22:50 +00:00
parent a7617ea224
commit 85c1926171
7 changed files with 167 additions and 51 deletions

View File

@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
return (list_end(head, elem) ? NULL : elem->n); return (list_end(head, elem) ? NULL : elem->n);
} }
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
#define list_item(v, t) \ #define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list)) ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
/* Given a known element in a known structure, locate the list head */ /* Given a known element in a known structure, locate the list head */
#define list_head(v, t, e) struct_field(v, t, e, list) #define list_head(v, t, e) struct_field(v, t, e, list)
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
#define list_iterate_items(v, head) \
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
v = list_item(v->list.n, typeof(*v)))
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
#endif #endif

View File

@ -321,7 +321,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
_inc_indent(f); _inc_indent(f);
list_iterate(pvh, &vg->pvs) { list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv; pv = list_item(pvh, struct pv_list)->pv;
if (!(name = _get_pv_name(f, pv))) { if (!(name = _get_pv_name(f, pv))) {
@ -522,7 +521,7 @@ static int _print_snapshots(struct formatter *f, struct volume_group *vg)
static int _print_lvs(struct formatter *f, struct volume_group *vg) static int _print_lvs(struct formatter *f, struct volume_group *vg)
{ {
struct list *lvh, *segh; struct list *lvh;
struct logical_volume *lv; struct logical_volume *lv;
struct lv_segment *seg; struct lv_segment *seg;
char buffer[256]; char buffer[256];
@ -571,9 +570,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
f->nl(f); f->nl(f);
seg_count = 1; seg_count = 1;
list_iterate(segh, &lv->segments) { list_iterate_items(seg, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!_print_segment(f, vg, seg_count++, seg)) { if (!_print_segment(f, vg, seg_count++, seg)) {
stack; stack;
return 0; return 0;

14
lib/metadata/lv_alloc.h Normal file
View File

@ -0,0 +1,14 @@
/*
* Copyright (C) 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*
* This is the in core representation of a volume group and its
* associated physical and logical volumes.
*/
#ifndef _LVM_LV_ALLOC_H
#include "pool.h"
struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes);
#endif

View File

@ -10,6 +10,7 @@
#include "pv_map.h" #include "pv_map.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "lv_alloc.h"
/* /*
* These functions adjust the pe counts in pv's * These functions adjust the pe counts in pv's
@ -49,7 +50,7 @@ static void _put_extents(struct lv_segment *seg)
} }
} }
static struct lv_segment *_alloc_segment(struct pool *mem, uint32_t stripes) struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes)
{ {
struct lv_segment *seg; struct lv_segment *seg;
uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0])); uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0]));
@ -75,7 +76,7 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
if (smallest < area_len) if (smallest < area_len)
area_len = smallest; area_len = smallest;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, stripes))) { if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, stripes))) {
log_err("Couldn't allocate new stripe segment."); log_err("Couldn't allocate new stripe segment.");
return 0; return 0;
} }
@ -188,7 +189,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
if (count > remaining) if (count > remaining)
count = remaining; count = remaining;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 1))) { if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 1))) {
log_err("Couldn't allocate new stripe segment."); log_err("Couldn't allocate new stripe segment.");
return 0; return 0;
} }
@ -224,7 +225,7 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
if (count > remaining) if (count > remaining)
count = remaining; count = remaining;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 2))) { if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 2))) {
log_err("Couldn't allocate new mirrored segment."); log_err("Couldn't allocate new mirrored segment.");
return 0; return 0;
} }
@ -731,8 +732,11 @@ int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
lv = list_item(lvh, struct lv_list)->lv; lv = list_item(lvh, struct lv_list)->lv;
if (!lock_vol(cmd, lv->lvid.s, flags)) { if (!lock_vol(cmd, lv->lvid.s, flags)) {
log_error("Failed to lock %s", lv->name); log_error("Failed to lock %s", lv->name);
/* FIXME Only unlock the locked ones */ list_uniterate(lvh, lvs, lvh) {
unlock_lvs(cmd, lvs); lv = list_item(lvh, struct lv_list)->lv;
unlock_lv(cmd, lv->lvid.s);
}
return 0; return 0;
} }
} }

View File

@ -6,6 +6,8 @@
#include "lib.h" #include "lib.h"
#include "metadata.h" #include "metadata.h"
#include "toolcontext.h"
#include "lv_alloc.h"
/* /*
* Test whether two segments could be merged by the current merging code * Test whether two segments could be merged by the current merging code
@ -100,3 +102,89 @@ int lv_check_segments(struct logical_volume *lv)
return 1; return 1;
} }
/*
* Split the supplied segment at the supplied logical extent
*/
static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
uint32_t le)
{
size_t len;
struct lv_segment *split_seg;
uint32_t s;
uint32_t offset = le - seg->le;
if (seg->type == SEG_SNAPSHOT) {
log_error("Unable to split the snapshot segment at LE %" PRIu32
" in LV %s", le, lv->name);
return 0;
}
/* Clone the existing segment */
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem,
seg->area_count))) {
log_error("Couldn't allocate new LV segment.");
return 0;
}
len = sizeof(*seg) + (seg->area_count * sizeof(seg->area[0]));
memcpy(split_seg, seg, len);
/* In case of a striped segment, the offset has to be / stripes */
if (seg->type == SEG_STRIPED)
offset /= seg->area_count;
/* Adjust the PV mapping */
for (s = 0; s < seg->area_count; s++) {
/* Split area at the offset */
switch (seg->area[s].type) {
case AREA_LV:
split_seg->area[s].u.lv.le =
seg->area[s].u.lv.le + offset;
break;
case AREA_PV:
split_seg->area[s].u.pv.pe =
seg->area[s].u.pv.pe + offset;
break;
default:
log_error("Unrecognised segment type %u",
seg->area[s].type);
return 0;
}
}
split_seg->area_len = seg->area_len - offset;
seg->area_len = offset;
/* Add split off segment to the list _after_ the original one */
list_add_h(&seg->list, &split_seg->list);
return 1;
}
/*
* Ensure there's a segment boundary at the given logical extent
*/
int lv_split_segment(struct logical_volume *lv, uint32_t le)
{
struct lv_segment *seg;
if (!(seg = find_seg_by_le(lv, le))) {
log_error("Segment with extent %" PRIu32 " in LV %s not found",
le, lv->name);
return 0;
}
/* This is a segment start already */
if (le == seg->le)
return 1;
if (!_lv_split_segment(lv, seg, le)) {
stack;
return 0;
}
return 1;
}

View File

@ -468,6 +468,11 @@ int lv_check_segments(struct logical_volume *lv);
*/ */
int lv_merge_segments(struct logical_volume *lv); int lv_merge_segments(struct logical_volume *lv);
/*
* Ensure there's a segment boundary at a given LE, splitting if necessary
*/
int lv_split_segment(struct logical_volume *lv, uint32_t le);
/* /*
* Useful functions for managing snapshots. * Useful functions for managing snapshots.
*/ */

View File

@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
return (list_end(head, elem) ? NULL : elem->n); return (list_end(head, elem) ? NULL : elem->n);
} }
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
#define list_item(v, t) \ #define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list)) ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
/* Given a known element in a known structure, locate the list head */ /* Given a known element in a known structure, locate the list head */
#define list_head(v, t, e) struct_field(v, t, e, list) #define list_head(v, t, e) struct_field(v, t, e, list)
#define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
#define list_iterate_items(v, head) \
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
v = list_item(v->list.n, typeof(*v)))
static inline unsigned int list_size(const struct list *head)
{
unsigned int s = 0;
const struct list *v;
list_iterate(v, head)
s++;
return s;
}
#endif #endif