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;
|
||||
}
|
||||
|
||||
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
|
||||
* for the biggest area, or the first area that
|
||||
@ -255,6 +294,44 @@ static int _alloc_contiguous(struct logical_volume *lv,
|
||||
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
|
||||
* 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,
|
||||
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;
|
||||
struct pool *scratch;
|
||||
@ -313,6 +391,9 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
if (stripes > 1)
|
||||
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)
|
||||
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->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;
|
||||
return NULL;
|
||||
}
|
||||
@ -536,7 +618,7 @@ int lv_extend(struct format_instance *fi,
|
||||
lv->size += (uint64_t) extents *lv->vg->extent_size;
|
||||
|
||||
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->size = old_size;
|
||||
stack;
|
||||
@ -557,6 +639,34 @@ int lv_extend(struct format_instance *fi,
|
||||
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)
|
||||
{
|
||||
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 pool *mem = cmd->mem;
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
|
||||
if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
|
||||
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 ? */
|
||||
old_partial = partial_mode();
|
||||
init_partial(1);
|
||||
if (vg_read(cmd, vg_name, &consistent)) {
|
||||
log_err("A volume group called '%s' already exists.", vg_name);
|
||||
goto bad;
|
||||
}
|
||||
init_partial(0);
|
||||
init_partial(old_partial);
|
||||
|
||||
if (!id_create(&vg->id)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -753,6 +762,8 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
struct list *vgnames, *slh;
|
||||
struct volume_group *vg;
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
int old_pvmove;
|
||||
|
||||
cache_label_scan(cmd, 0);
|
||||
|
||||
@ -771,7 +782,10 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
|
||||
/* Read every VG to ensure cache consistency */
|
||||
/* Orphan VG is last on list */
|
||||
old_partial = partial_mode();
|
||||
old_pvmove = pvmove_mode();
|
||||
init_partial(1);
|
||||
init_pvmove(1);
|
||||
list_iterate(slh, vgnames) {
|
||||
vgname = list_item(slh, struct str_list)->str;
|
||||
if (!vgname)
|
||||
@ -790,7 +804,8 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
list_add(results, pvh);
|
||||
}
|
||||
}
|
||||
init_partial(0);
|
||||
init_pvmove(old_pvmove);
|
||||
init_partial(old_partial);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
@ -38,7 +38,8 @@
|
||||
#define VISIBLE_LV 0x00000040 /* LV */
|
||||
#define FIXED_MINOR 0x00000080 /* LV */
|
||||
/* 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_WRITE 0x00000200 /* LV VG */
|
||||
@ -397,6 +398,12 @@ int lv_extend(struct format_instance *fi,
|
||||
uint32_t stripe_size,
|
||||
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 */
|
||||
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
register char c;
|
||||
|
Loading…
Reference in New Issue
Block a user