diff --git a/WHATS_NEW b/WHATS_NEW index 076386089..9174d95b0 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.01.10 - ================================ + Initial pv_segment support. vgchange --physicalextentsize Internal snapshot restructuring. Remove unused internal non-persistent snapshot option. diff --git a/include/.symlinks b/include/.symlinks index 86acfea29..49c64bf02 100644 --- a/include/.symlinks +++ b/include/.symlinks @@ -31,6 +31,7 @@ ../lib/log/log.h ../lib/metadata/lv_alloc.h ../lib/metadata/metadata.h +../lib/metadata/pv_alloc.h ../lib/metadata/segtype.h ../lib/mm/dbg_malloc.h ../lib/mm/memlock.h diff --git a/lib/Makefile.in b/lib/Makefile.in index 4d57b736b..2261c77d2 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -70,6 +70,7 @@ SOURCES =\ metadata/merge.c \ metadata/metadata.c \ metadata/mirror.c \ + metadata/pv_manip.c \ metadata/pv_map.c \ metadata/segtype.c \ metadata/snapshot_manip.c \ diff --git a/lib/config/defaults.h b/lib/config/defaults.h index f7af81ac5..c4dcb815b 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -95,15 +95,18 @@ #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_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size" #define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_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,dev_size,pv_uuid" #define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize" +#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size" #define DEFAULT_LVS_SORT "vg_name,lv_name" #define DEFAULT_VGS_SORT "vg_name" #define DEFAULT_PVS_SORT "pv_name" #define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start" +#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start" #endif /* _LVM_DEFAULTS_H */ diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c index 0fdb3e9f0..a3d923284 100644 --- a/lib/format1/import-export.c +++ b/lib/format1/import-export.c @@ -26,6 +26,7 @@ #include "filter.h" #include "toolcontext.h" #include "segtype.h" +#include "pv_alloc.h" #include @@ -89,6 +90,13 @@ int import_pv(struct pool *mem, struct device *dev, pv->pe_alloc_count = pvd->pe_allocated; list_init(&pv->tags); + list_init(&pv->segments); + list_init(&pv->free_segments); + + if (!alloc_pv_segment_whole_pv(mem, pv)) { + stack; + return 0; + } return 1; } diff --git a/lib/format_pool/import_export.c b/lib/format_pool/import_export.c index 52284082c..ec4d157b8 100644 --- a/lib/format_pool/import_export.c +++ b/lib/format_pool/import_export.c @@ -21,6 +21,7 @@ #include "disk_rep.h" #include "sptype_names.h" #include "lv_alloc.h" +#include "pv_alloc.h" #include "str_list.h" #include "display.h" #include "segtype.h" @@ -182,6 +183,13 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem, pv->pe_alloc_count = pv->pe_count; list_init(&pv->tags); + list_init(&pv->segments); + list_init(&pv->free_segments); + + if (!alloc_pv_segment_whole_pv(mem, pv)) { + stack; + return 0; + } return 1; } diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 74a88fed3..e5d4213bf 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -22,6 +22,7 @@ #include "toolcontext.h" #include "lvmcache.h" #include "lv_alloc.h" +#include "pv_alloc.h" #include "segtype.h" #include "text_import.h" @@ -190,6 +191,8 @@ static int _read_pv(struct format_instance *fid, struct pool *mem, } list_init(&pv->tags); + list_init(&pv->segments); + list_init(&pv->free_segments); /* Optional tags */ if ((cn = find_config_node(pvn, "tags")) && @@ -208,6 +211,11 @@ static int _read_pv(struct format_instance *fid, struct pool *mem, pv->pe_alloc_count = 0; pv->fmt = fid->fmt; + if (!alloc_pv_segment_whole_pv(mem, pv)) { + stack; + return 0; + } + vg->pv_count++; list_add(&vg->pvs, &pvl->list); diff --git a/lib/report/columns.h b/lib/report/columns.h index 530eb591f..bf55c5d69 100644 --- a/lib/report/columns.h +++ b/lib/report/columns.h @@ -71,4 +71,7 @@ FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start") FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size") FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags") FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices") + +FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start") +FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size") /* *INDENT-ON* */ diff --git a/lib/report/report.c b/lib/report/report.c index f6e0de329..bc33b0ab5 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -31,6 +31,7 @@ static union { struct logical_volume _lv; struct volume_group _vg; struct lv_segment _seg; + struct pv_segment _pvseg; } _dummy; /* @@ -1078,6 +1079,9 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys, case SEGS: rh->field_prefix = "seg_"; break; + case PVSEGS: + rh->field_prefix = "pvseg_"; + break; default: rh->field_prefix = ""; } @@ -1097,6 +1101,8 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys, /* Ensure options selected are compatible */ if (rh->type & SEGS) rh->type |= LVS; + if (rh->type & PVSEGS) + rh->type |= PVS; if ((rh->type & LVS) && (rh->type & PVS)) { log_error("Can't report LV and PV fields at the same time"); return NULL; @@ -1107,6 +1113,8 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys, *report_type = SEGS; else if (rh->type & LVS) *report_type = LVS; + else if (rh->type & PVSEGS) + *report_type = PVSEGS; else if (rh->type & PVS) *report_type = PVS; @@ -1127,7 +1135,7 @@ void report_free(void *handle) */ int report_object(void *handle, struct volume_group *vg, struct logical_volume *lv, struct physical_volume *pv, - struct lv_segment *seg) + struct lv_segment *seg, struct pv_segment *pvseg) { struct report_handle *rh = handle; struct list *fh; @@ -1187,6 +1195,9 @@ int report_object(void *handle, struct volume_group *vg, break; case SEGS: data = (void *) seg + _fields[fp->field_num].offset; + break; + case PVSEGS: + data = (void *) pvseg + _fields[fp->field_num].offset; } if (skip) { diff --git a/lib/report/report.h b/lib/report/report.h index 5095c90a9..4f5cb765b 100644 --- a/lib/report/report.h +++ b/lib/report/report.h @@ -18,7 +18,7 @@ #include "metadata.h" -typedef enum { LVS = 1, PVS = 2, VGS = 4, SEGS = 8 } report_type_t; +typedef enum { LVS = 1, PVS = 2, VGS = 4, SEGS = 8, PVSEGS = 16 } report_type_t; struct field; struct report_handle; @@ -32,7 +32,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys, void report_free(void *handle); int report_object(void *handle, struct volume_group *vg, struct logical_volume *lv, struct physical_volume *pv, - struct lv_segment *seg); + struct lv_segment *seg, struct pv_segment *pvseg); int report_output(void *handle); #endif diff --git a/tools/commands.h b/tools/commands.h index 9d8ef7256..22931f01b 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -491,6 +491,7 @@ xx(pvs, "\t[--nosuffix]\n" "\t[-o|--options [+]Field[,Field]]\n" "\t[-O|--sort [+|-]key1[,[+|-]key2[,...]]]\n" + "\t[--segments]\n" "\t[--separator Separator]\n" "\t[--unbuffered]\n" "\t[--units hsbkmgtHKMGT]\n" @@ -499,8 +500,8 @@ xx(pvs, "\t[PhysicalVolume [PhysicalVolume...]]\n", aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG, - nolocking_ARG, nosuffix_ARG, options_ARG, separator_ARG, sort_ARG, - unbuffered_ARG, units_ARG) + nolocking_ARG, nosuffix_ARG, options_ARG, segments_ARG, separator_ARG, + sort_ARG, unbuffered_ARG, units_ARG) xx(pvscan, "List all physical volumes", diff --git a/tools/reporter.c b/tools/reporter.c index bbf002b84..0a8d7d524 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -24,7 +24,7 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name, return ECMD_FAILED; } - if (!report_object(handle, vg, NULL, NULL, NULL)) + if (!report_object(handle, vg, NULL, NULL, NULL, NULL)) return ECMD_FAILED; return ECMD_PROCESSED; @@ -33,7 +33,7 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name, static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { - if (!report_object(handle, lv->vg, lv, NULL, NULL)) + if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL)) return ECMD_FAILED; return ECMD_PROCESSED; @@ -42,18 +42,50 @@ static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv, static int _segs_single(struct cmd_context *cmd, struct lv_segment *seg, void *handle) { - if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg)) + if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL)) return ECMD_FAILED; return ECMD_PROCESSED; } +static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg, + struct pv_segment *pvseg, void *handle) +{ + int consistent = 0; + struct physical_volume *pv = pvseg->pv; + int ret = ECMD_PROCESSED; + + if (!lock_vol(cmd, pv->vg_name, LCK_VG_READ)) { + log_error("Can't lock %s: skipping", pv->vg_name); + return ECMD_FAILED; + } + + if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) { + log_error("Can't read %s: skipping", pv->vg_name); + unlock_vg(cmd, pv->vg_name); + return ECMD_FAILED; + } + + if (!report_object(handle, vg, NULL, pv, NULL, pvseg)) + ret = ECMD_FAILED; + + unlock_vg(cmd, pv->vg_name); + return ret; +} + static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv, void *handle) { return process_each_segment_in_lv(cmd, lv, handle, _segs_single); } +static int _pvsegs_single(struct cmd_context *cmd, struct volume_group *vg, + struct physical_volume *pv, void *handle) +{ + return process_each_segment_in_pv(cmd, vg, pv, handle, + _pvsegs_sub_single); +} + static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv, void *handle) { @@ -73,7 +105,7 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg, } } - if (!report_object(handle, vg, NULL, pv, NULL)) + if (!report_object(handle, vg, NULL, pv, NULL, NULL)) ret = ECMD_FAILED; if (pv->vg_name) @@ -151,6 +183,18 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, "report/segs_cols_verbose", DEFAULT_SEGS_COLS_VERB); break; + case PVSEGS: + keys = find_config_str(cmd->cft->root, "report/pvsegs_sort", + DEFAULT_PVSEGS_SORT); + if (!arg_count(cmd, verbose_ARG)) + options = find_config_str(cmd->cft->root, + "report/pvsegs_cols", + DEFAULT_PVSEGS_COLS); + else + options = find_config_str(cmd->cft->root, + "report/pvsegs_cols_verbose", + DEFAULT_PVSEGS_COLS_VERB); + break; } /* If -o supplied use it, else use default for report_type */ @@ -208,6 +252,10 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle, &_lvsegs_single); break; + case PVSEGS: + r = process_each_pv(cmd, argc, argv, NULL, report_handle, + &_pvsegs_single); + break; } report_output(report_handle); @@ -235,5 +283,12 @@ int vgs(struct cmd_context *cmd, int argc, char **argv) int pvs(struct cmd_context *cmd, int argc, char **argv) { - return _report(cmd, argc, argv, PVS); + report_type_t type; + + if (arg_count(cmd, segments_ARG)) + type = PVSEGS; + else + type = PVS; + + return _report(cmd, argc, argv, type); } diff --git a/tools/toollib.c b/tools/toollib.c index 8fb2dbef8..cb6ddc256 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -288,6 +288,28 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, return ret_max; } +int process_each_segment_in_pv(struct cmd_context *cmd, + struct volume_group *vg, + struct physical_volume *pv, + void *handle, + int (*process_single) (struct cmd_context * cmd, + struct volume_group * vg, + struct pv_segment * pvseg, + void *handle)) +{ + struct pv_segment *pvseg; + int ret_max = 0; + int ret; + + list_iterate_items(pvseg, &pv->segments) { + ret = process_single(cmd, vg, pvseg, handle); + if (ret > ret_max) + ret_max = ret; + } + + return ret_max; +} + int process_each_segment_in_lv(struct cmd_context *cmd, struct logical_volume *lv, void *handle, @@ -475,6 +497,8 @@ static int _process_all_devs(struct cmd_context *cmd, void *handle, if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 0))) { memset(&pv_dummy, 0, sizeof(pv_dummy)); list_init(&pv_dummy.tags); + list_init(&pv_dummy.segments); + list_init(&pv_dummy.free_segments); pv_dummy.dev = dev; pv_dummy.fmt = NULL; pv = &pv_dummy; diff --git a/tools/toollib.h b/tools/toollib.h index ff663ed9d..b0536baac 100644 --- a/tools/toollib.h +++ b/tools/toollib.h @@ -40,6 +40,14 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv, struct volume_group * vg, struct physical_volume * pv, void *handle)); +int process_each_segment_in_pv(struct cmd_context *cmd, + struct volume_group *vg, + struct physical_volume *pv, + void *handle, + int (*process_single) (struct cmd_context * cmd, + struct volume_group * vg, + struct pv_segment * pvseg, + void *handle)); int process_each_lv(struct cmd_context *cmd, int argc, char **argv, int lock_type, void *handle,