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

basic pvmove support

This commit is contained in:
Alasdair Kergon 2003-04-30 15:23:43 +00:00
parent 5053603d2a
commit 97d344e2cb
3 changed files with 151 additions and 7 deletions

View File

@ -211,6 +211,45 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
return 1; return 1;
} }
static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
struct pv_map *map, struct pv_area *pva,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
uint32_t count, remaining;
struct lv_segment *seg;
count = pva->count;
remaining = lv->le_count - *ix;
if (count > remaining)
count = remaining;
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 2))) {
log_err("Couldn't allocate new mirrored segment.");
return 0;
}
seg->lv = lv;
seg->type = SEG_MIRRORED;
seg->le = *ix;
seg->len = count;
seg->area_len = count;
seg->stripe_size = 0;
seg->area_count = 2;
/* FIXME Remove AREA_PV restriction here? */
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = mirrored_pv;
seg->area[0].u.pv.pe = mirrored_pe;
seg->area[1].type = AREA_PV;
seg->area[1].u.pv.pv = map->pvl->pv;
seg->area[1].u.pv.pe = pva->start;
list_add(&lv->segments, &seg->list);
consume_pv_area(pva, count);
*ix += count;
return 1;
}
/* /*
* Only one area per pv is allowed, so we search * Only one area per pv is allowed, so we search
* for the biggest area, or the first area that * for the biggest area, or the first area that
@ -255,6 +294,44 @@ static int _alloc_contiguous(struct logical_volume *lv,
return 1; return 1;
} }
/* FIXME Contiguous depends on *segment* (i.e. stripe) not LV */
static int _alloc_mirrored(struct logical_volume *lv,
struct list *pvms, uint32_t allocated,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe)
{
struct list *tmp1;
struct pv_map *pvm;
struct pv_area *pva;
list_iterate(tmp1, pvms) {
pvm = list_item(tmp1, struct pv_map);
if (list_empty(&pvm->areas))
continue;
/* first item in the list is the biggest */
pva = list_item(pvm->areas.n, struct pv_area);
if (!_alloc_mirrored_area(lv, &allocated, pvm, pva,
mirrored_pv, mirrored_pe)) {
stack;
return 0;
}
break;
}
if (allocated != lv->le_count) {
log_error("Insufficient contiguous allocatable extents (%u) "
"for logical volume %s: %u required",
allocated, lv->name, lv->le_count);
return 0;
}
return 1;
}
/* /*
* Areas just get allocated in order until the lv * Areas just get allocated in order until the lv
* is full. * is full.
@ -293,7 +370,8 @@ static int _alloc_next_free(struct logical_volume *lv,
*/ */
static int _allocate(struct volume_group *vg, struct logical_volume *lv, static int _allocate(struct volume_group *vg, struct logical_volume *lv,
struct list *allocatable_pvs, uint32_t allocated, struct list *allocatable_pvs, uint32_t allocated,
uint32_t stripes, uint32_t stripe_size) uint32_t stripes, uint32_t stripe_size,
struct physical_volume *mirrored_pv, uint32_t mirrored_pe)
{ {
int r = 0; int r = 0;
struct pool *scratch; struct pool *scratch;
@ -313,6 +391,9 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
if (stripes > 1) if (stripes > 1)
r = _alloc_striped(lv, pvms, allocated, stripes, stripe_size); r = _alloc_striped(lv, pvms, allocated, stripes, stripe_size);
else if (mirrored_pv)
r = _alloc_mirrored(lv, pvms, allocated, mirrored_pv,
mirrored_pe);
else if (lv->alloc == ALLOC_CONTIGUOUS) else if (lv->alloc == ALLOC_CONTIGUOUS)
r = _alloc_contiguous(lv, pvms, allocated); r = _alloc_contiguous(lv, pvms, allocated);
@ -474,7 +555,8 @@ struct logical_volume *lv_create(struct format_instance *fi,
lv->size = (uint64_t) extents *vg->extent_size; lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents; lv->le_count = extents;
if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size)) { if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size,
NULL, 0u)) {
stack; stack;
return NULL; return NULL;
} }
@ -536,7 +618,7 @@ int lv_extend(struct format_instance *fi,
lv->size += (uint64_t) extents *lv->vg->extent_size; lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count, if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
stripes, stripe_size)) { stripes, stripe_size, NULL, 0u)) {
lv->le_count = old_le_count; lv->le_count = old_le_count;
lv->size = old_size; lv->size = old_size;
stack; stack;
@ -557,6 +639,34 @@ int lv_extend(struct format_instance *fi,
return 1; return 1;
} }
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, allocatable_pvs, old_le_count,
1, extents, mirrored_pv, mirrored_pe)) {
lv->le_count = old_le_count;
lv->size = old_size;
stack;
return 0;
}
if (fid->fmt->ops->lv_setup && !fid->fmt->ops->lv_setup(fid, lv)) {
stack;
return 0;
}
return 1;
}
int lv_remove(struct volume_group *vg, struct logical_volume *lv) int lv_remove(struct volume_group *vg, struct logical_volume *lv)
{ {
struct list *segh; struct list *segh;

View File

@ -157,6 +157,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg; struct volume_group *vg;
struct pool *mem = cmd->mem; struct pool *mem = cmd->mem;
int consistent = 0; int consistent = 0;
int old_partial;
if (!(vg = pool_zalloc(mem, sizeof(*vg)))) { if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
stack; stack;
@ -164,12 +165,13 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
} }
/* is this vg name already in use ? */ /* is this vg name already in use ? */
old_partial = partial_mode();
init_partial(1); init_partial(1);
if (vg_read(cmd, vg_name, &consistent)) { if (vg_read(cmd, vg_name, &consistent)) {
log_err("A volume group called '%s' already exists.", vg_name); log_err("A volume group called '%s' already exists.", vg_name);
goto bad; goto bad;
} }
init_partial(0); init_partial(old_partial);
if (!id_create(&vg->id)) { if (!id_create(&vg->id)) {
log_err("Couldn't create uuid for volume group '%s'.", vg_name); log_err("Couldn't create uuid for volume group '%s'.", vg_name);
@ -614,8 +616,15 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
} }
} }
*consistent = 1; if ((correct_vg->status & PVMOVE_VG) && !pvmove_mode()) {
log_error("WARNING: Interrupted pvmove detected in "
"volume group %s", vg->name);
log_error("Please restore the metadata by running "
"vgcfgrestore.");
return NULL;
}
*consistent = 1;
return correct_vg; return correct_vg;
} }
@ -753,6 +762,8 @@ struct list *get_pvs(struct cmd_context *cmd)
struct list *vgnames, *slh; struct list *vgnames, *slh;
struct volume_group *vg; struct volume_group *vg;
int consistent = 0; int consistent = 0;
int old_partial;
int old_pvmove;
cache_label_scan(cmd, 0); cache_label_scan(cmd, 0);
@ -771,7 +782,10 @@ struct list *get_pvs(struct cmd_context *cmd)
/* Read every VG to ensure cache consistency */ /* Read every VG to ensure cache consistency */
/* Orphan VG is last on list */ /* Orphan VG is last on list */
old_partial = partial_mode();
old_pvmove = pvmove_mode();
init_partial(1); init_partial(1);
init_pvmove(1);
list_iterate(slh, vgnames) { list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str; vgname = list_item(slh, struct str_list)->str;
if (!vgname) if (!vgname)
@ -790,7 +804,8 @@ struct list *get_pvs(struct cmd_context *cmd)
list_add(results, pvh); list_add(results, pvh);
} }
} }
init_partial(0); init_pvmove(old_pvmove);
init_partial(old_partial);
return results; return results;
} }

View File

@ -38,7 +38,8 @@
#define VISIBLE_LV 0x00000040 /* LV */ #define VISIBLE_LV 0x00000040 /* LV */
#define FIXED_MINOR 0x00000080 /* LV */ #define FIXED_MINOR 0x00000080 /* LV */
/* FIXME Remove when metadata restructuring is completed */ /* FIXME Remove when metadata restructuring is completed */
#define SNAPSHOT 0x00001000 /* LV - temp internal use only */ #define SNAPSHOT 0x00001000 /* LV - tmp internal use only */
#define PVMOVE_VG 0x00002000 /* VG - tmp use only */
#define LVM_READ 0x00000100 /* LV VG */ #define LVM_READ 0x00000100 /* LV VG */
#define LVM_WRITE 0x00000200 /* LV VG */ #define LVM_WRITE 0x00000200 /* LV VG */
@ -397,6 +398,12 @@ int lv_extend(struct format_instance *fi,
uint32_t stripe_size, uint32_t stripe_size,
uint32_t extents, struct list *allocatable_pvs); uint32_t extents, struct list *allocatable_pvs);
int lv_extend_mirror(struct format_instance *fid,
struct logical_volume *lv,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t extents, struct list *allocatable_pvs);
/* Lock list of LVs */ /* Lock list of LVs */
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags); int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
int unlock_lvs(struct cmd_context *cmd, struct list *lvs); int unlock_lvs(struct cmd_context *cmd, struct list *lvs);
@ -469,6 +476,18 @@ int vg_add_snapshot(struct logical_volume *origin,
int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow); int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
/*
* Mirroring functions
*/
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct physical_volume *pv,
struct logical_volume *lv,
struct list *allocatable_pvs,
struct list *lvs_changed);
int remove_pvmove_mirrors(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv_mirr, int commit);
static inline int validate_name(const char *n) static inline int validate_name(const char *n)
{ {
register char c; register char c;