From 9e300c8427eae36c0640636a01408932e1376cef Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 2 Oct 2001 17:09:05 +0000 Subject: [PATCH] pvscan framework --- lib/datastruct/list.h | 4 - lib/metadata/metadata.h | 24 ++++- libdm/datastruct/list.h | 4 - tools/Makefile.in | 1 + tools/errors.h | 3 +- tools/lvactivate.c | 15 ++- tools/lvm.c | 29 +++--- tools/pvcreate.c | 10 +- tools/pvdisplay.c | 20 ++-- tools/pvscan.c | 222 ++++++++++++++++++++++++++++++++++++++++ tools/stub.h | 1 - tools/toollib.c | 73 +++++++------ tools/tools.h | 6 +- 13 files changed, 320 insertions(+), 92 deletions(-) create mode 100644 tools/pvscan.c diff --git a/lib/datastruct/list.h b/lib/datastruct/list.h index 5a80c762a..b0c0dd7a3 100644 --- a/lib/datastruct/list.h +++ b/lib/datastruct/list.h @@ -3,8 +3,6 @@ #ifndef _LVM_LIST_H #define _LVM_LIST_H -#ifdef __KERNEL__ - /* * Simple doubly linked list implementation. * @@ -109,6 +107,4 @@ static __inline__ void list_splice(struct list_head *list, struct list_head *hea #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) -#endif /* __KERNEL__ */ - #endif diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index fedfca18f..b8b81bb04 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -12,9 +12,10 @@ #include #include "dev-cache.h" +#include "list.h" #define ID_LEN 32 - +#define NAME_LEN 128 /* Various flags */ /* Note that the bits no longer necessarily correspond to LVM1 disk format */ @@ -42,8 +43,13 @@ +#define EXPORTED_TAG "PV_EXP" /* Identifier of exported PV */ +#define IMPORTED_TAG "PV_IMP" /* Identifier of imported PV */ + + + struct id { - __uint8_t chars[ID_LEN]; + __uint8_t uuid[ID_LEN]; }; struct logical_volume; @@ -52,6 +58,7 @@ struct physical_volume { struct id *id; struct device *dev; char *vg_name; + char *exported; __uint32_t status; __uint64_t size; @@ -101,11 +108,20 @@ struct volume_group { struct logical_volume **lv; }; +struct string_list { + struct list_head list; + char * string; +}; + +struct pv_list { + struct list_head list; + struct physical_volume pv; +}; /* ownership of returned objects passes */ struct io_space { - struct str_list *(*get_vgs)(struct io_space *is); - struct dev_list *(*get_pvs)(struct io_space *is); + struct string_list *(*get_vgs)(struct io_space *is); + struct pv_list *(*get_pvs)(struct io_space *is); struct physical_volume *(*pv_read)(struct io_space *is, struct device *dev); diff --git a/libdm/datastruct/list.h b/libdm/datastruct/list.h index 5a80c762a..b0c0dd7a3 100644 --- a/libdm/datastruct/list.h +++ b/libdm/datastruct/list.h @@ -3,8 +3,6 @@ #ifndef _LVM_LIST_H #define _LVM_LIST_H -#ifdef __KERNEL__ - /* * Simple doubly linked list implementation. * @@ -109,6 +107,4 @@ static __inline__ void list_splice(struct list_head *list, struct list_head *hea #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) -#endif /* __KERNEL__ */ - #endif diff --git a/tools/Makefile.in b/tools/Makefile.in index 7c51ca1a5..5022f8204 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -24,6 +24,7 @@ SOURCES=\ lvm.c\ pvcreate.c\ pvdisplay.c\ + pvscan.c\ lvactivate.c TARGETS=\ diff --git a/tools/errors.h b/tools/errors.h index 44ceaa001..304a775da 100644 --- a/tools/errors.h +++ b/tools/errors.h @@ -22,9 +22,10 @@ #define _LVM_ERROR_H_INCLUDE #define LVM_EINVALID_CMD_LINE 1 -#define LVM_ENOMEM 2 +#define LVM_ENOMEM 2 #define LVM_ENO_SUCH_CMD 3 #define LVM_ECMD_PROCESSED 4 +#define LVM_ECMD_FAILED 5 #endif /* #ifndef _LVM_ERROR_H_INCLUDE */ diff --git a/tools/lvactivate.c b/tools/lvactivate.c index 30786ffea..019add95d 100644 --- a/tools/lvactivate.c +++ b/tools/lvactivate.c @@ -70,15 +70,14 @@ int lvactivate(int argc, char **argv) for (p = 0; p < pv->pe_total; p++) { int l = pv->pe[p].lv_num; int le = pv->pe[p].le_num; - long pe_size_guess = lvs[l - 1].lv_size / - lvs[l - 1].lv_allocated_le; - + long pe_size_guess = lvs[l - 1].lv_size / + lvs[l - 1].lv_allocated_le; + if (l && !strcmp(lv, lvs[l - 1].lv_name)) - printf("%012ld %ld linear %s %012ld\n", - pe_size_guess * le, - pe_size_guess, - pv_name, - get_pe_offset(p, pv)); + printf("%012ld %ld linear %s %012ld\n", + pe_size_guess * le, + pe_size_guess, + pv_name, get_pe_offset(p, pv)); } if (pv) diff --git a/tools/lvm.c b/tools/lvm.c index 13cdc7149..cba835218 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -42,7 +42,6 @@ struct arg the_args[ARG_COUNT + 1] = { }; - /* a register of the lvm commands */ struct command { const char *name; @@ -236,7 +235,7 @@ char yes_no_prompt(char *prompt, ...) } c = tolower(getchar()); } - while (getchar() != '\n'); + while (getchar() != '\n') ; return c; } @@ -263,7 +262,7 @@ static void register_command(const char *name, command_fn fn, va_end(ap); /* allocate space for them */ - if (!(args = dbg_malloc(sizeof(*args) * nargs))) { + if (!(args = dbg_malloc(sizeof (*args) * nargs))) { log_fatal("Out of memory."); exit(LVM_ENOMEM); } @@ -319,7 +318,7 @@ static void create_new_command(const char *name, command_fn command, static void __alloc(int size) { - if (!(_commands = dbg_realloc(_commands, sizeof(*_commands) * size))) { + if (!(_commands = dbg_realloc(_commands, sizeof (*_commands) * size))) { log_fatal("Couldn't allocate memory."); exit(LVM_ENOMEM); } @@ -377,7 +376,7 @@ static int process_command_line(struct command *com, int *argc, char ***argv) add_getopt_arg(com->valid_args[i], &ptr, &o); *ptr = '\0'; - memset(o, 0, sizeof(*o)); + memset(o, 0, sizeof (*o)); /* initialise getopt_long & scan for command line switches */ optarg = 0; @@ -545,15 +544,18 @@ static int split(char *str, int *argc, char **argv, int max) return *argc; } -struct config_file *active_config_file(void) { +struct config_file *active_config_file(void) +{ return _cf; } -struct dev_filter *active_filter(void) { +struct dev_filter *active_filter(void) +{ return _filter; } -struct io_space *active_ios(void) { +struct io_space *active_ios(void) +{ return _ios; } @@ -579,7 +581,7 @@ static int init(void) const char *e = getenv("LVM_CONFIG_FILE"); struct stat info; - if (!(_cf=create_config_file())) { + if (!(_cf = create_config_file())) { stack; goto out; } @@ -644,7 +646,6 @@ static void fin(void) fclose(_log); } - static int run_script(int argc, char **argv) { FILE *script; @@ -656,15 +657,15 @@ static int run_script(int argc, char **argv) if ((script = fopen(argv[0], "r")) == NULL) return LVM_ENO_SUCH_CMD; - while (fgets(buffer, sizeof(buffer), script) != NULL) { + while (fgets(buffer, sizeof (buffer), script) != NULL) { if (!magic_number) { if (buffer[0] == '#' && buffer[1] == '!') magic_number = 1; else return LVM_ENO_SUCH_CMD; } - if ((strlen(buffer) == sizeof(buffer) - 1) - && (buffer[sizeof(buffer) - 1] - 2 != '\n')) { + if ((strlen(buffer) == sizeof (buffer) - 1) + && (buffer[sizeof (buffer) - 1] - 2 != '\n')) { buffer[50] = '\0'; log_error("Line too long (max 255) beginning: %s", buffer); @@ -776,7 +777,7 @@ static char *list_args(char *text, int state) char c; if (!(c = (the_args + com->valid_args[match_no++])->short_arg)) - continue; + continue; sprintf(s, "-%c", c); if (!strncmp(text, s, len)) diff --git a/tools/pvcreate.c b/tools/pvcreate.c index 810e1bfe9..f606b4c8b 100644 --- a/tools/pvcreate.c +++ b/tools/pvcreate.c @@ -69,8 +69,8 @@ void pvcreate_single(const char *pv_name) pv = ios->pv_read(ios, pv_dev); if (pv && (pv->status & STATUS_EXPORTED)) { - log_error ("Physical volume %s belongs to exported volume" - " group %s", pv_name, pv->vg_name); + log_error("Physical volume %s belongs to exported volume" + " group %s", pv_name, pv->vg_name); return; } @@ -95,18 +95,15 @@ void pvcreate_single(const char *pv_name) } if (pv && (pv->status & STATUS_ACTIVE)) { - log_error("Can't create on active physical volume %s", - pv_name); + log_error("Can't create on active physical volume %s", pv_name); return; } - if (!pv) { if (!(pv = pv_create())) return; /* FIXME: Set up initial size & PEs here */ } - if (arg_count(force_ARG)) { /* FIXME: Change to log_print */ @@ -123,7 +120,6 @@ void pvcreate_single(const char *pv_name) log_verbose("setting up physical volume for %s with %u sectors", pv_name, size); - log_verbose("writing physical volume data to disk %s", pv_name); if (!(pv_write(ios, pv))) { diff --git a/tools/pvdisplay.c b/tools/pvdisplay.c index 1a4fc6caf..e12fda87e 100644 --- a/tools/pvdisplay.c +++ b/tools/pvdisplay.c @@ -70,8 +70,7 @@ void pvdisplay_device(const char *pv_name) } sz = display_size(size / 2, SIZE_SHORT); - log_print("Device \"%s\" has a capacity of %s", - pv_name, sz); + log_print("Device \"%s\" has a capacity of %s", pv_name, sz); dbg_free(sz); } @@ -114,21 +113,21 @@ void pvdisplay_device(const char *pv_name) goto pvdisplay_device_out; } - pv_display_full(pv); + pv_display_full(pv); - if (!arg_count(verbose_ARG)) + if (!arg_count(verbose_ARG)) goto pvdisplay_device_out; if (pv->pe_allocated) { - if (!(pv->pe = pv_read_pe (pv_name, pv))) - goto pvdisplay_device_out; + if (!(pv->pe = pv_read_pe(pv_name, pv))) + goto pvdisplay_device_out; if (!(lvs = pv_read_lvs(pv))) { - log_error("Failed to read LVs on %s", pv->pv_name); + log_error("Failed to read LVs on %s", pv->pv_name); goto pvdisplay_device_out; } - pv_display_pe_text(pv, pv->pe, lvs); + pv_display_pe_text(pv, pv->pe, lvs); } else - log_print ("no logical volume on physical volume %s", pv_name); + log_print("no logical volume on physical volume %s", pv_name); pvdisplay_device_out: if (pv) @@ -138,6 +137,3 @@ void pvdisplay_device(const char *pv_name) return; } - - - diff --git a/tools/pvscan.c b/tools/pvscan.c new file mode 100644 index 000000000..98ae77861 --- /dev/null +++ b/tools/pvscan.c @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * LVM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LVM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LVM; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "tools.h" + +void pvscan_display_single(struct physical_volume *pv); + +int pv_max_name_len = 0; +int vg_max_name_len = 0; + +int pvscan(int argc, char **argv) +{ + int new_pvs_found = 0; + int pvs_found = 0; + char *s1, *s2, *s3; + + struct io_space *ios; + struct pv_list *pvs_list, *pvl; + struct list_head *pvh; + struct physical_volume *pv; + + __uint64_t size_total = 0; + __uint64_t size_new = 0; + __uint64_t size = 0; + + int len = 0; + pv_max_name_len = 0; + vg_max_name_len = 0; + + if (arg_count(novolumegroup_ARG) && arg_count(exported_ARG)) { + log_error("options e and n incompatible"); + return LVM_EINVALID_CMD_LINE; + } + + if (arg_count(exported_ARG) || arg_count(novolumegroup_ARG)) + log_print("WARNING: only considering physical volumes %s", + arg_count(exported_ARG) ? + "of exported volume group(s)" : "in no volume group"); + + log_verbose("Walking through all physical volumes"); + + ios = active_ios(); + + if (!(pvs_list = ios->get_pvs(ios))) + return LVM_ECMD_FAILED; + + /* eliminate exported/new if required */ + list_for_each(pvh, &pvs_list->list) { + pvl = list_entry(pvh, struct pv_list, list); + pv = &pvl->pv; + + if ((arg_count(exported_ARG) && !(pv->status & STATUS_EXPORTED)) + || (arg_count(novolumegroup_ARG) && (pv->vg_name[0]))) { + list_del(&pvl->list); /* Plus deallocation? */ + continue; + } + + /* Also check for MD use? */ +/******* + if (MAJOR(pv_create_kdev_t(pv[p]->pv_name)) != MD_MAJOR) { + log_print + ("WARNING: physical volume \"%s\" belongs to a meta device", + pv[p]->pv_name); + } + if (MAJOR(pv[p]->pv_dev) != MD_MAJOR) + continue; +********/ + pvs_found++; + + size = dev_get_size(pv->dev); + size_total += size; + + if (pv->vg_name[0]) { + new_pvs_found++; + size_new += size; + } + } + + /* find maximum pv name length */ + pv_max_name_len = vg_max_name_len = 0; + list_for_each(pvh, &pvs_list->list) { + pvl = list_entry(pvh, struct pv_list, list); + pv = &pvl->pv; + len = strlen(pv->dev->name); + if (pv_max_name_len < len) + pv_max_name_len = len; + len = strlen(pv->vg_name); + if (vg_max_name_len < len) + vg_max_name_len = len; + } + pv_max_name_len += 2; + vg_max_name_len += 2; + + list_for_each(pvh, &pvs_list->list) { + pvl = list_entry(pvh, struct pv_list, list); + pv = &pvl->pv; + + pvscan_display_single(pv); + } + + if (!pvs_found) { + log_print("No matching physical volumes found"); + return 0; + } + + log_print("total: %d [%s] / in use: %d [%s] / in no VG: %d [%s]", + pvs_found, + (s1 = display_size(size_total / 2, SIZE_SHORT)), + pvs_found - new_pvs_found, + (s2 = + display_size((size_total - size_new) / 2, SIZE_SHORT)), + new_pvs_found, (s3 = + display_size(size_new / 2, + SIZE_SHORT))); + dbg_free(s1); + dbg_free(s2); + dbg_free(s3); + + return 0; +} + +void pvscan_display_single(struct physical_volume *pv) +{ + + int vg_name_len = 0; + const char *active_str; + + char *s1, *s2; + + char pv_tmp_name[NAME_LEN] = { 0, }; + char vg_tmp_name[NAME_LEN] = { 0, }; + char vg_name_this[NAME_LEN] = { 0, }; + + /* short listing? */ + if (arg_count(short_ARG) > 0) { + log_print("%s", pv->dev->name); + return; + } + + if (arg_count(verbose_ARG) > 1) { + pv_show(pv); + log_print("System Id %s", pv->exported); + log_print(""); + return; + } + + memset(pv_tmp_name, 0, sizeof (pv_tmp_name)); + + active_str = (pv->status & STATUS_ACTIVE) ? "ACTIVE " : "inactive "; + + vg_name_len = strlen(pv->vg_name) - sizeof (EXPORTED) + 1; + + if (arg_count(uuid_ARG)) { + sprintf(pv_tmp_name, + "%-*s with UUID %s", + pv_max_name_len - 2, + pv->dev->name, display_uuid(pv->id->uuid)); + } else { + sprintf(pv_tmp_name, "%s", pv->dev.name); + } + + if (!pv->vg_name[0]) { + log_print("%s PV %-*s is in no VG [%s]", active_str, + pv_max_name_len, pv_tmp_name, + (s1 = display_size(pv->size / 2, SIZE_SHORT))); + dbg_free(s1); + return; + } + + /* FIXME What is pe_total now? */ + if (strcmp(&pv->vg_name[vg_name_len], EXPORTED_TAG) == 0) { + strncpy(vg_name_this, pv->vg_name, vg_name_len); + log_print("%sPV %-*s is in EXPORTED VG %s [%s / %s free]", + active_str, pv_max_name_len, pv_tmp_name, + vg_name_this, (s1 = + display_size(pv->pe_total * + pv->pe_size / 2, + SIZE_SHORT)), + (s2 = display_size((pv->pe_total - pv->pe_allocated) + * pv->pe_size / 2, SIZE_SHORT))); + dbg_free(s1); + dbg_free(s2); + return; + } + + if (!vg_check_name(pv->vg_name)) { + log_print + ("%sPV %-*s is associated to an unknown VG ", + active_str, pv_max_name_len, pv_tmp_name); + return; + } + + sprintf(vg_tmp_name, "%s", pv->vg_name); + log_print + ("%sPV %-*s of VG %-*s [%s / %s free]", active_str, pv_max_name_len, + pv_tmp_name, vg_max_name_len, vg_tmp_name, + (s1 = display_size(pv->pe_total * pv->pe_size / 2, SIZE_SHORT)), + (s2 = + display_size((pv->pe_total - pv->pe_allocated) * pv->pe_size / 2, + SIZE_SHORT))); + dbg_free(s1); + dbg_free(s2); + + return; +} diff --git a/tools/stub.h b/tools/stub.h index e31ac887d..91d64ad30 100644 --- a/tools/stub.h +++ b/tools/stub.h @@ -33,7 +33,6 @@ int lvrename(int argc, char **argv) {return 1;} int lvscan(int argc, char **argv) {return 1;} int pvchange(int argc, char **argv) {return 1;} int pvdata(int argc, char **argv) {return 1;} -int pvscan(int argc, char **argv) {return 1;} int vgcfgbackup(int argc, char **argv) {return 1;} int vgcfgrestore(int argc, char **argv) {return 1;} int vgchange(int argc, char **argv) {return 1;} diff --git a/tools/toollib.c b/tools/toollib.c index 059b24b57..e2c6d2bc5 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -24,54 +24,59 @@ static int _autobackup = 1; int autobackup_set() { - return _autobackup; + return _autobackup; } int init_autobackup() { - char *lvm_autobackup; + char *lvm_autobackup; - if (arg_count(autobackup_ARG)) - _autobackup = strcmp(arg_str_value(autobackup_ARG, "y"), "n"); - else { - _autobackup = 1; /* default */ + if (arg_count(autobackup_ARG)) + _autobackup = strcmp(arg_str_value(autobackup_ARG, "y"), "n"); + else { + _autobackup = 1; /* default */ - lvm_autobackup = getenv("LVM_AUTOBACKUP"); - if (lvm_autobackup) { - log_print("using environment variable LVM_AUTOBACKUP to set option A"); - if (strcasecmp(lvm_autobackup, "no") == 0) - _autobackup = 0; - else if (strcasecmp(lvm_autobackup, "yes") != 0) { - log_error("environment variable LVM_AUTOBACKUP has invalid value \"%s\"!", - lvm_autobackup); - return -1; - } + lvm_autobackup = getenv("LVM_AUTOBACKUP"); + if (lvm_autobackup) { + log_print + ("using environment variable LVM_AUTOBACKUP to set option A"); + if (strcasecmp(lvm_autobackup, "no") == 0) + _autobackup = 0; + else if (strcasecmp(lvm_autobackup, "yes") != 0) { + log_error + ("environment variable LVM_AUTOBACKUP has invalid value \"%s\"!", + lvm_autobackup); + return -1; + } + } } - } - return 0; + return 0; } int do_autobackup(char *vg_name, vg_t * vg) { - int ret; + int ret; - log_verbose("Changing lvmtab"); - if ((ret = vg_cfgbackup(vg_name, LVMTAB_DIR, vg))) { - log_error("\"%s\" writing \"%s\"", lvm_error(ret), LVMTAB); - return LVM_E_VG_CFGBACKUP; - } + log_verbose("Changing lvmtab"); + if ((ret = vg_cfgbackup(vg_name, LVMTAB_DIR, vg))) { + log_error("\"%s\" writing \"%s\"", lvm_error(ret), LVMTAB); + return LVM_E_VG_CFGBACKUP; + } - if (!autobackup_set()) { - log_print("WARNING: You don't have an automatic backup of \"%s\"", vg_name); - return 0; - } + if (!autobackup_set()) { + log_print + ("WARNING: You don't have an automatic backup of \"%s\"", + vg_name); + return 0; + } - log_print("Creating automatic backup of volume group \"%s\"", vg_name); - if ((ret = vg_cfgbackup(vg_name, VG_BACKUP_DIR, vg))) { - log_error("\"%s\" writing VG backup of \"%s\"", lvm_error(ret), vg_name); - return LVM_E_VG_CFGBACKUP; - } + log_print("Creating automatic backup of volume group \"%s\"", vg_name); + if ((ret = vg_cfgbackup(vg_name, VG_BACKUP_DIR, vg))) { + log_error("\"%s\" writing VG backup of \"%s\"", lvm_error(ret), + vg_name); + return LVM_E_VG_CFGBACKUP; + } - return 0; + return 0; } diff --git a/tools/tools.h b/tools/tools.h index 9a548fa3d..32cacf9d9 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -79,9 +79,6 @@ int permission_arg(struct arg *a); char yes_no_prompt(char *prompt, ...); -struct dev_mgr *active_dev_mgr(void); -struct config_file *active_config_file(void); - /* we use the enums to access the switches */ static inline int arg_count(int a) { return the_args[a].count; @@ -107,3 +104,6 @@ static inline int arg_count_increment(int a) } #endif +struct config_file *active_config_file(void); +struct dev_filter *active_filter(void); +struct io_space *active_ios(void); -- 2.43.5