mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
move fields
This commit is contained in:
parent
8b99c8b6ec
commit
44c319cf0d
@ -70,12 +70,12 @@
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_SEPARATOR " "
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent"
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_percent"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,lv_uuid"
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,move_percent,lv_uuid"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||
|
@ -231,11 +231,13 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
|
||||
|
||||
seg->lv = lv;
|
||||
seg->type = SEG_MIRRORED;
|
||||
seg->status = 0u;
|
||||
seg->le = *ix;
|
||||
seg->len = count;
|
||||
seg->area_len = count;
|
||||
seg->stripe_size = 0;
|
||||
seg->area_count = 2;
|
||||
seg->extents_moved = 0u;
|
||||
/* FIXME Remove AREA_PV restriction here? */
|
||||
seg->area[0].type = AREA_PV;
|
||||
seg->area[0].u.pv.pv = mirrored_pv;
|
||||
@ -274,13 +276,14 @@ static int _alloc_contiguous(struct logical_volume *lv,
|
||||
|
||||
/* first item in the list is the biggest */
|
||||
pva = list_item(pvm->areas.n, struct pv_area);
|
||||
if (pva->count < lv->le_count)
|
||||
continue;
|
||||
|
||||
if (!_alloc_linear_area(lv, &allocated, pvm, pva)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (allocated == lv->le_count)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -303,7 +306,9 @@ static int _alloc_mirrored(struct logical_volume *lv,
|
||||
struct list *tmp1;
|
||||
struct pv_map *pvm;
|
||||
struct pv_area *pva;
|
||||
uint32_t max_found = 0;
|
||||
|
||||
/* Try each PV in turn */
|
||||
list_iterate(tmp1, pvms) {
|
||||
pvm = list_item(tmp1, struct pv_map);
|
||||
|
||||
@ -312,6 +317,10 @@ static int _alloc_mirrored(struct logical_volume *lv,
|
||||
|
||||
/* first item in the list is the biggest */
|
||||
pva = list_item(pvm->areas.n, struct pv_area);
|
||||
if (pva->count < lv->le_count - allocated) {
|
||||
max_found = pva->count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_alloc_mirrored_area(lv, &allocated, pvm, pva,
|
||||
mirrored_pv, mirrored_pe)) {
|
||||
@ -325,7 +334,7 @@ static int _alloc_mirrored(struct logical_volume *lv,
|
||||
if (allocated != lv->le_count) {
|
||||
log_error("Insufficient contiguous allocatable extents (%u) "
|
||||
"for logical volume %s: %u required",
|
||||
allocated, lv->name, lv->le_count);
|
||||
allocated + max_found, lv->name, lv->le_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -371,11 +380,13 @@ 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,
|
||||
struct physical_volume *mirrored_pv, uint32_t mirrored_pe)
|
||||
struct physical_volume *mirrored_pv, uint32_t mirrored_pe,
|
||||
uint32_t status)
|
||||
{
|
||||
int r = 0;
|
||||
struct pool *scratch;
|
||||
struct list *pvms, *old_tail = lv->segments.p, *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
if (!(scratch = pool_create(1024))) {
|
||||
stack;
|
||||
@ -413,8 +424,11 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
* Iterate through the new segments, updating pe
|
||||
* counts in pv's.
|
||||
*/
|
||||
for (segh = lv->segments.p; segh != old_tail; segh = segh->p)
|
||||
_get_extents(list_item(segh, struct lv_segment));
|
||||
for (segh = lv->segments.p; segh != old_tail; segh = segh->p) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
_get_extents(seg);
|
||||
seg->status = status;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Put the segment list back how we found it.
|
||||
@ -428,7 +442,7 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *_generate_lv_name(struct volume_group *vg,
|
||||
static char *_generate_lv_name(struct volume_group *vg, const char *format,
|
||||
char *buffer, size_t len)
|
||||
{
|
||||
struct list *lvh;
|
||||
@ -438,14 +452,14 @@ static char *_generate_lv_name(struct volume_group *vg,
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = (list_item(lvh, struct lv_list)->lv);
|
||||
|
||||
if (sscanf(lv->name, "lvol%d", &i) != 1)
|
||||
if (sscanf(lv->name, format, &i) != 1)
|
||||
continue;
|
||||
|
||||
if (i > high)
|
||||
high = i;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(buffer, len, "lvol%d", high + 1) < 0)
|
||||
if (lvm_snprintf(buffer, len, format, high + 1) < 0)
|
||||
return NULL;
|
||||
|
||||
return buffer;
|
||||
@ -453,6 +467,7 @@ static char *_generate_lv_name(struct volume_group *vg,
|
||||
|
||||
struct logical_volume *lv_create_empty(struct format_instance *fi,
|
||||
const char *name,
|
||||
const char *name_format,
|
||||
uint32_t status,
|
||||
alloc_policy_t alloc,
|
||||
struct volume_group *vg)
|
||||
@ -468,7 +483,8 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!name && !(name = _generate_lv_name(vg, dname, sizeof(dname)))) {
|
||||
if (!name && !(name = _generate_lv_name(vg, name_format, dname,
|
||||
sizeof(dname)))) {
|
||||
log_error("Failed to generate unique name for the new "
|
||||
"logical volume");
|
||||
return NULL;
|
||||
@ -547,7 +563,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(lv = lv_create_empty(fi, name, status, alloc, vg))) {
|
||||
if (!(lv = lv_create_empty(fi, name, "lvol%d", status, alloc, vg))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@ -556,7 +572,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
|
||||
lv->le_count = extents;
|
||||
|
||||
if (!_allocate(vg, lv, allocatable_pvs, 0u, stripes, stripe_size,
|
||||
NULL, 0u)) {
|
||||
NULL, 0u, 0u)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@ -618,7 +634,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, NULL, 0u)) {
|
||||
stripes, stripe_size, NULL, 0u, 0u)) {
|
||||
lv->le_count = old_le_count;
|
||||
lv->size = old_size;
|
||||
stack;
|
||||
@ -643,7 +659,8 @@ 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 extents, struct list *allocatable_pvs,
|
||||
uint32_t status)
|
||||
{
|
||||
uint32_t old_le_count = lv->le_count;
|
||||
uint64_t old_size = lv->size;
|
||||
@ -652,7 +669,7 @@ int lv_extend_mirror(struct format_instance *fid,
|
||||
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)) {
|
||||
1, extents, mirrored_pv, mirrored_pe, status)) {
|
||||
lv->le_count = old_le_count;
|
||||
lv->size = old_size;
|
||||
stack;
|
||||
@ -690,23 +707,6 @@ int lv_remove(struct volume_group *vg, struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Lock a list of LVs */
|
||||
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unlock list of LVs */
|
||||
int unlock_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
{
|
||||
@ -720,3 +720,22 @@ int unlock_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Lock a list of LVs */
|
||||
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
|
||||
list_iterate(lvh, lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
/* FIXME Only unlock the locked ones */
|
||||
unlock_lvs(cmd, lvs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
}
|
||||
}
|
||||
|
||||
if ((correct_vg->status & PVMOVE_VG) && !pvmove_mode()) {
|
||||
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
|
||||
log_error("WARNING: Interrupted pvmove detected in "
|
||||
"volume group %s", vg->name);
|
||||
log_error("Please restore the metadata by running "
|
||||
|
@ -39,7 +39,8 @@
|
||||
#define FIXED_MINOR 0x00000080 /* LV */
|
||||
/* FIXME Remove when metadata restructuring is completed */
|
||||
#define SNAPSHOT 0x00001000 /* LV - tmp internal use only */
|
||||
#define PVMOVE_VG 0x00002000 /* VG - tmp use only */
|
||||
#define PVMOVE 0x00002000 /* VG LV SEG */
|
||||
#define LOCKED 0x00004000 /* LV */
|
||||
|
||||
#define LVM_READ 0x00000100 /* LV VG */
|
||||
#define LVM_WRITE 0x00000200 /* LV VG */
|
||||
@ -179,6 +180,8 @@ struct lv_segment {
|
||||
uint32_t le;
|
||||
uint32_t len;
|
||||
|
||||
uint32_t status;
|
||||
|
||||
/* FIXME Fields depend on segment type */
|
||||
uint32_t stripe_size;
|
||||
uint32_t area_count;
|
||||
@ -186,6 +189,7 @@ struct lv_segment {
|
||||
struct logical_volume *origin;
|
||||
struct logical_volume *cow;
|
||||
uint32_t chunk_size;
|
||||
uint32_t extents_moved;
|
||||
|
||||
/* There will be one area for each stripe */
|
||||
struct {
|
||||
@ -384,6 +388,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
|
||||
|
||||
struct logical_volume *lv_create_empty(struct format_instance *fi,
|
||||
const char *name,
|
||||
const char *name_format,
|
||||
uint32_t status,
|
||||
alloc_policy_t alloc,
|
||||
struct volume_group *vg);
|
||||
@ -402,7 +407,8 @@ 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 extents, struct list *allocatable_pvs,
|
||||
uint32_t status);
|
||||
|
||||
/* Lock list of LVs */
|
||||
int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags);
|
||||
@ -485,8 +491,16 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
|
||||
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);
|
||||
int remove_pvmove_mirrors(struct volume_group *vg,
|
||||
struct logical_volume *lv_mirr);
|
||||
struct logical_volume *find_pvmove_lv(struct volume_group *vg,
|
||||
struct device *dev);
|
||||
struct physical_volume *get_pvmove_pv_from_lv(struct logical_volume *lv);
|
||||
struct physical_volume *get_pvmove_pv_from_lv_mirr(struct logical_volume
|
||||
*lv_mirr);
|
||||
float pvmove_percent(struct logical_volume *lv_mirr);
|
||||
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct logical_volume *lv);
|
||||
|
||||
static inline int validate_name(const char *n)
|
||||
{
|
||||
|
@ -18,6 +18,8 @@ FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size")
|
||||
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count")
|
||||
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin")
|
||||
FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
|
||||
FIELD(LVS, lv, NUM, "Move%", lvid, 6, movepercent, "move_percent")
|
||||
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
|
||||
|
||||
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
|
||||
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
|
||||
|
@ -171,14 +171,18 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_origin(lv))
|
||||
if (lv->status & PVMOVE)
|
||||
repstr[0] = 'p';
|
||||
else if (lv_is_origin(lv))
|
||||
repstr[0] = 'o';
|
||||
else if (find_cow(lv))
|
||||
repstr[0] = 's';
|
||||
else
|
||||
repstr[0] = '-';
|
||||
|
||||
if (lv->status & LVM_WRITE)
|
||||
if (lv->status & PVMOVE)
|
||||
repstr[1] = '-';
|
||||
else if (lv->status & LVM_WRITE)
|
||||
repstr[1] = 'w';
|
||||
else
|
||||
repstr[1] = 'r';
|
||||
@ -188,6 +192,9 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
else
|
||||
repstr[2] = 'n';
|
||||
|
||||
if (lv->status & LOCKED)
|
||||
repstr[2] = toupper(repstr[2]);
|
||||
|
||||
if (lv->status & FIXED_MINOR)
|
||||
repstr[3] = 'm'; /* Fixed Minor */
|
||||
else
|
||||
@ -313,6 +320,28 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _movepv_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
const char *name;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
if (!(seg->status & PVMOVE))
|
||||
continue;
|
||||
name = dev_name(seg->area[0].u.pv.pv->dev);
|
||||
return _string_disp(rh, field, &name);
|
||||
}
|
||||
|
||||
field->report_string = "";
|
||||
field->sort_value = (const void *) field->report_string;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _size32_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
@ -581,9 +610,6 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snap_percent == -1)
|
||||
snap_percent = 100;
|
||||
|
||||
if (lvm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
|
||||
log_error("snapshot percentage too large");
|
||||
return 0;
|
||||
@ -596,6 +622,48 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _movepercent_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
struct logical_volume *lv = (struct logical_volume *) data;
|
||||
float move_percent;
|
||||
uint64_t *sortval;
|
||||
char *repstr;
|
||||
|
||||
if (!(sortval = pool_alloc(rh->mem, sizeof(uint64_t)))) {
|
||||
log_error("pool_alloc failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(lv->status & PVMOVE)) {
|
||||
field->report_string = "";
|
||||
*sortval = UINT64_C(0);
|
||||
field->sort_value = sortval;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Update percentage done in lv metadata in core */
|
||||
lv_mirror_percent(lv, 0, &move_percent, NULL);
|
||||
|
||||
move_percent = pvmove_percent(lv);
|
||||
|
||||
if (!(repstr = pool_zalloc(rh->mem, 8))) {
|
||||
log_error("pool_alloc failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 7, "%.2f", move_percent) < 0) {
|
||||
log_error("move percentage too large");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*sortval = move_percent * UINT64_C(1000);
|
||||
field->sort_value = sortval;
|
||||
field->report_string = repstr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Import column definitions
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user