From 44c319cf0dcbd493795ccce905c1151b51261bc5 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 6 May 2003 12:06:02 +0000 Subject: [PATCH] move fields --- lib/config/defaults.h | 6 +-- lib/metadata/lv_manip.c | 83 +++++++++++++++++++++++++---------------- lib/metadata/metadata.c | 2 +- lib/metadata/metadata.h | 22 +++++++++-- lib/report/columns.h | 2 + lib/report/report.c | 78 +++++++++++++++++++++++++++++++++++--- 6 files changed, 148 insertions(+), 45 deletions(-) diff --git a/lib/config/defaults.h b/lib/config/defaults.h index 19025da06..5b7fe782a 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -58,7 +58,7 @@ #endif #define DEFAULT_STRIPE_FILLER "/dev/ioerror" -#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */ +#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */ #define DEFAULT_INTERVAL 15 #ifdef READLINE_SUPPORT @@ -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" diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b11312c00..7d1943060 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -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,14 +276,15 @@ 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; + break; } if (allocated != lv->le_count) { @@ -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; +} diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 8be7b818f..79449c169 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -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 " diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index b3b622f5b..2bd000997 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -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) { diff --git a/lib/report/columns.h b/lib/report/columns.h index 7c877de4e..2526fcd70 100644 --- a/lib/report/columns.h +++ b/lib/report/columns.h @@ -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") diff --git a/lib/report/report.c b/lib/report/report.c index f114bb1d9..92aa3c239 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -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 */