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:
parent
5053603d2a
commit
97d344e2cb
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user