From 269930c0da148443f48c9d86ead5e67ec5f76617 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 25 Sep 2001 12:49:28 +0000 Subject: [PATCH] lvactivate checkpoint commit --- lib/Makefile.in | 7 +- lib/config/config.h | 8 +- lib/dev-mgr/dev-manager.h | 5 +- lib/dev-mgr/hash.h | 6 +- lib/device/device.c | 64 +++ lib/device/device.h | 27 ++ lib/display/display.c | 90 +++++ lib/display/display.h | 31 ++ lib/display/metadata.c | 278 +++++++++++++ lib/display/metadata.h | 38 ++ lib/log/log.h | 15 +- lib/metadata/lvm_v1.c | 501 +++++++++++++++++++++++ lib/metadata/lvm_v1.h | 208 ++++++++++ lib/metadata/metadata.c | 53 +++ lib/metadata/metadata.h | 368 +++++++++++++++++ lib/mm/dbg_malloc.h | 14 +- lib/mm/pool.h | 6 +- man/pvdisplay.8 | 67 +++ tools/Makefile.in | 1 + tools/args.h | 73 ++++ tools/commands.h | 484 ++++++++++++++++++++++ tools/errors.h | 480 ++++++++++++++++++++++ tools/lvactivate.c | 95 +++++ tools/lvm.c | 829 ++++++++++++++++++++++++++++++++++++++ tools/pvdisplay.c | 141 +++++++ tools/stub.h | 55 +++ tools/toollib.c | 77 ++++ tools/toollib.h | 28 ++ tools/tools.h | 108 +++++ 29 files changed, 4117 insertions(+), 40 deletions(-) create mode 100644 lib/device/device.c create mode 100644 lib/device/device.h create mode 100644 lib/display/display.c create mode 100644 lib/display/display.h create mode 100644 lib/display/metadata.c create mode 100644 lib/display/metadata.h create mode 100644 lib/metadata/lvm_v1.c create mode 100644 lib/metadata/lvm_v1.h create mode 100644 lib/metadata/metadata.c create mode 100644 lib/metadata/metadata.h create mode 100644 man/pvdisplay.8 create mode 100644 tools/args.h create mode 100644 tools/commands.h create mode 100644 tools/errors.h create mode 100644 tools/lvactivate.c create mode 100644 tools/lvm.c create mode 100644 tools/pvdisplay.c create mode 100644 tools/stub.h create mode 100644 tools/toollib.c create mode 100644 tools/toollib.h create mode 100644 tools/tools.h diff --git a/lib/Makefile.in b/lib/Makefile.in index d1d949bcd..d275a41b7 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -24,9 +24,14 @@ SOURCES=\ config/config.c \ dev-mgr/dev-manager.c \ dev-mgr/hash.c \ + device/device.c \ + display/display.c \ + display/metadata.c \ log/log.c \ + metadata/lvm_v1.c \ + metadata/metadata.c \ mm/pool.c \ - mm/dbg_malloc.c + mm/dbg_malloc.c TARGETS=liblvm.a diff --git a/lib/config/config.h b/lib/config/config.h index 7b8c40fdb..470d77b79 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -1,9 +1,6 @@ /* - * tools/lib/config.h - * * Copyright (C) 2001 Sistina Software * - * * This LVM library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either @@ -20,8 +17,9 @@ * MA 02111-1307, USA */ -#ifndef LVM_CONFIG_H -#define LVM_CONFIG_H +#ifndef _LVM_CONFIG_H +#define _LVM_CONFIG_H + enum { CFG_STRING, diff --git a/lib/dev-mgr/dev-manager.h b/lib/dev-mgr/dev-manager.h index 2c1c9f173..f6285971d 100644 --- a/lib/dev-mgr/dev-manager.h +++ b/lib/dev-mgr/dev-manager.h @@ -19,9 +19,10 @@ * MA 02111-1307, USA */ -#ifndef DEV_MANAGER_H -#define DEV_MANAGER_H +#ifndef _LVM_DEV_MANAGER_H +#define _LVM_DEV_MANAGER_H +#include #include "config/config.h" struct device { diff --git a/lib/dev-mgr/hash.h b/lib/dev-mgr/hash.h index 0eaf231bc..be068e611 100644 --- a/lib/dev-mgr/hash.h +++ b/lib/dev-mgr/hash.h @@ -1,6 +1,4 @@ /* - * tools/lib/hash.h - * * Copyright (C) 2001 Sistina Software * * This LVM library is free software; you can redistribute it and/or @@ -19,8 +17,8 @@ * MA 02111-1307, USA */ -#ifndef HASH_H -#define HASH_H +#ifndef _LVM_HASH_H +#define _LVM_HASH_H extern unsigned char hash_nums[256]; diff --git a/lib/device/device.c b/lib/device/device.c new file mode 100644 index 000000000..edc090010 --- /dev/null +++ b/lib/device/device.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device.h" +#include "log/log.h" + +int do_ioctl(const char *file, int mode, unsigned long cmd, void *req) +{ + int ret, fd; + + if ((fd = open(file, mode)) < 0) { + log_sys_err("open"); + return errno; + } + + if ((ret = ioctl(fd, cmd, req)) < 0) { + log_sys_err("ioctl"); + ret = errno; + } + + close(fd); + return ret; +} + +int device_get_size(const char *dev_name) +{ + int ret, r; + + log_verbose("Getting device size"); + if (!(ret = do_ioctl(dev_name, O_RDONLY, BLKGETSIZE, &r))) + return r; + + return ret; +} diff --git a/lib/device/device.h b/lib/device/device.h new file mode 100644 index 000000000..4dbaf425e --- /dev/null +++ b/lib/device/device.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#ifndef _LVM_DEVICE_H +#define _LVM_DEVICE_H + +int do_ioctl(const char *file, int mode, unsigned long cmd, void *req); +int device_get_size(const char *dev_name); + +#endif + diff --git a/lib/display/display.c b/lib/display/display.c new file mode 100644 index 000000000..02f062b88 --- /dev/null +++ b/lib/display/display.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#include +#include +#include "display/display.h" +#include "metadata/metadata.h" +#include "mm/dbg_malloc.h" +#include "log/log.h" + +#define SIZE_BUF 128 + +char *display_size(unsigned long long size, size_len_t sl) +{ + int s; + ulong byte = 1024 * 1024 * 1024; + char *size_buf = NULL; + char *size_str[][2] = { + {"Terabyte", "TB"}, + {"Gigabyte", "GB"}, + {"Megabyte", "MB"}, + {"Kilobyte", "KB"}, + {"", ""} + }; + + if (!(size_buf = dbg_malloc(SIZE_BUF))) { + log_error("no memory for size display buffer"); + return NULL; + } + + if (size == 0LL) + sprintf(size_buf, "0"); + else { + s = 0; + while (size_str[s] && size < byte) + s++, byte /= 1024; + snprintf(size_buf, SIZE_BUF - 1, + "%.2f %s", (float) size / byte, size_str[s][sl]); + } + + /* Caller to deallocate */ + return size_buf; +} + +char *display_uuid(char *uuidstr) +{ + int i, j; + char *uuid; + + if ((!uuidstr) || !(uuid = dbg_malloc(NAME_LEN))) { + log_error("no memory for uuid display buffer"); + return NULL; + } + + memset(uuid, 0, NAME_LEN); + + i = 6; + memcpy(uuid, uuidstr, i); + uuidstr += i; + + for (j = 0; j < 6; j++) { + uuid[i++] = '-'; + memcpy(&uuid[i], uuidstr, 4); + uuidstr += 4; + i += 4; + } + + memcpy(&uuid[i], uuidstr, 2); + + /* Caller must free */ + return uuid; +} + diff --git a/lib/display/display.h b/lib/display/display.h new file mode 100644 index 000000000..81ab06cba --- /dev/null +++ b/lib/display/display.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#ifndef _LVM_DISPLAY_H +#define _LVM_DISPLAY_H + +typedef enum {SIZE_LONG=0, SIZE_SHORT=1} size_len_t; + +/* Specify size in KB */ +char *display_size(unsigned long long size, size_len_t sl); + +char *display_uuid(char *uuidstr); + +#endif diff --git a/lib/display/metadata.c b/lib/display/metadata.c new file mode 100644 index 000000000..ddb754bfc --- /dev/null +++ b/lib/display/metadata.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#include +#include +#include "display/display.h" +#include "display/metadata.h" +#include "mm/dbg_malloc.h" +#include "log/log.h" + +void pv_display_colons(pv_t * pv) +{ + char *uuid; + + if (!pv) + return; + + uuid = display_uuid(pv->pv_uuid); + + printf("%s:%s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%s\n", + pv->pv_name, + pv->vg_name, + pv->pv_size, + pv->pv_number, + pv->pv_status, + pv->pv_allocatable, + pv->lv_cur, + pv->pe_size / 2, + pv->pe_total, + pv->pe_total - pv->pe_allocated, + pv->pe_allocated, uuid ? uuid : "none"); + + dbg_free(uuid); + + return; +} + +void pv_display_full(pv_t * pv) +{ + ulong pe_free; + char *size = NULL; + char *uuid; + + if (!pv) + return; + + uuid = display_uuid(pv->pv_uuid); + + printf("--- %sPhysical volume ---\n", pv->pe_size ? "" : "NEW "); + printf("PV Name %s\n", pv->pv_name); + printf("VG Name %s\n", pv->vg_name); + + size = display_size(pv->pv_size / 2, SIZE_SHORT); + printf("PV Size %s", size); + dbg_free(size); + + if (pv->pe_size && pv->pe_total) { + size = + display_size((pv->pv_size - pv->pe_size * pv->pe_total) / 2, + SIZE_SHORT); + printf(" / NOT usable %s ", size); + dbg_free(size); + + size = + display_size( + (pv->pe_on_disk.base + + pv->pe_total * sizeof (pe_disk_t)) / 1024, + SIZE_SHORT); + printf("[LVM: %s]", size); + dbg_free(size); + } + + printf("\n"); + + printf("PV# %u\n", pv->pv_number); + printf("PV Status %savailable\n", + (pv->pv_status & PV_ACTIVE) ? "" : "NOT "); + + printf("Allocatable "); + pe_free = pv->pe_total - pv->pe_allocated; + if (pv->pe_total > 0 && (pv->pv_allocatable & PV_ALLOCATABLE)) { + printf("yes"); + if (pe_free == 0 && pv->pe_total > 0) + printf(" (but full)"); + printf("\n"); + } else + printf("NO\n"); + + printf("Cur LV %u\n", pv->lv_cur); + printf("PE Size (KByte) %u\n", pv->pe_size / 2); + printf("Total PE %u\n", pv->pe_total); + printf("Free PE %lu\n", pe_free); + printf("Allocated PE %u\n", pv->pe_allocated); + +#ifdef LVM_FUTURE + printf("Stale PE %u\n", pv->pe_stale); +#endif + + printf("PV UUID %s\n", uuid ? uuid : "none"); + printf("\n"); + + dbg_free(uuid); + + return; +} + +/******* +void pv_display_short(pv_t * pv) +{ + + if (pv != NULL) { + printf("PV Name (#) %s (%u)\n", pv->pv_name, + pv->pv_number); + printf("PV Status "); + if (!(pv->pv_status & PV_ACTIVE)) + printf("NOT "); + printf("available / "); + if (!(pv->pv_allocatable & PV_ALLOCATABLE)) + printf("NOT "); + printf("allocatable\n"); + printf("Total PE / Free PE %u / %u\n", + pv->pe_total, pv->pe_total - pv->pe_allocated); + } + + return; +} + +void pv_display_pe(pv_t * pv, pe_disk_t * pe) +{ + int p; + + for (p = 0; p < pv->pe_total; p++) + printf("pe#: %4d vg: %s lv: %d le: %d\n", + p, pv->vg_name, pe[p].lv_num, pe[p].le_num); + + return; +} +*******/ + +void pv_display_pe_text(pv_t * pv, pe_disk_t * pe, lv_disk_t * lvs) +{ + int flag = 0; + int lv_num_last = 0; + int p = 0; + int pe_free = 0; + int *pe_this_count = NULL; + int pt = 0; + int pt_count = 0; + lv_disk_t *lv; + char *lv_name_this = NULL; + char *lv_names = NULL; + char *lv_names_sav = NULL; + pe_disk_t *pe_this = NULL; + + if ((pe_this = dbg_malloc(pv->pe_total * sizeof (pe_disk_t))) == NULL) { + log_error("pe_this allocation failed"); + goto pv_display_pe_text_out; + } + + if ((pe_this_count = dbg_malloc(pv->pe_total * sizeof (int))) == NULL) { + log_error("pe_this_count allocation failed"); + goto pv_display_pe_text_out; + } + + memset(pe_this, 0, pv->pe_total * sizeof (pe_disk_t)); + memset(pe_this_count, 0, pv->pe_total * sizeof (int)); + + /* get PE and LE summaries */ + pt_count = 0; + for (p = pt_count; p < pv->pe_total; p++) { + if (pe[p].lv_num != 0) { + flag = 0; + for (pt = 0; pt < pt_count; pt++) { + if (pe_this[pt].lv_num == pe[p].lv_num) { + flag = 1; + break; + } + } + if (flag == 0) { + pe_this[pt_count].lv_num = pe[p].lv_num; + for (pt = 0; pt < pv->pe_total; pt++) + if (pe_this[pt_count].lv_num == + pe[pt].lv_num) + pe_this_count[pt_count]++; + pt_count++; + } + } + } + + lv = lvs; + printf(" --- Distribution of physical volume ---\n" + " LV Name LE of LV PE for LV\n"); + for (pt = 0; pt < pt_count; pt++) { + printf(" %-25s ", lv->lv_name); + if (strlen(lv->lv_name) > 25) + printf("\n "); + printf("%-8u %-8d\n", + lv->lv_allocated_le, + pe_this_count[pt]); + if (pe_this[pt].lv_num > lv_num_last) { + lv_num_last = pe_this[pt].lv_num; + lv_names_sav = lv_names; + if ((lv_names = dbg_realloc(lv_names, + lv_num_last * NAME_LEN)) == + NULL) { + log_error("realloc error in %s [line %d]", + __FILE__, __LINE__); + goto pv_display_pe_text_out; + } else + lv_names_sav = NULL; + } + strcpy(&lv_names[(pe_this[pt].lv_num - 1) * NAME_LEN], + lv->lv_name); + lv++; + } + + printf("\n --- Physical extents ---\n" + " PE LV LE Disk sector\n"); + pe_free = -1; + for (p = 0; p < pv->pe_total; p++) { + if (pe[p].lv_num != 0) { + if (pe_free > -1) { + pv_display_pe_free(pe_free, p); + pe_free = -1; + } + lv_name_this = &lv_names[(pe[p].lv_num - 1) * NAME_LEN]; + printf(" %05d %-25s ", p, lv_name_this); + if (strlen(lv_name_this) > 25) + printf("\n "); + printf("%05d %ld\n", pe[p].le_num, + get_pe_offset(p, pv)); + + } else if (pe_free == -1) + pe_free = p; + } + + if (pe_free > 0) + pv_display_pe_free(pe_free, p); + + pv_display_pe_text_out: + if (lv_names != NULL) + dbg_free(lv_names); + else if (lv_names_sav != NULL) + dbg_free(lv_names_sav); + if (pe_this != NULL) + dbg_free(pe_this); + if (pe_this_count != NULL) + dbg_free(pe_this_count); + + return; +} + +void pv_display_pe_free(int pe_free, int p) +{ + printf(" %05d free\n", pe_free); + + if (p - pe_free > 1) + printf(" .....\n %05d free\n", p - 1); + + return; +} diff --git a/lib/display/metadata.h b/lib/display/metadata.h new file mode 100644 index 000000000..ab23c789f --- /dev/null +++ b/lib/display/metadata.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#ifndef _LVM_DISPLAY_METADATA_H +#define _LVM_DISPLAY_METADATA_H + +#include "metadata/metadata.h" + +void pv_display_colons(pv_t * pv); +void pv_display_full(pv_t * pv); +void pv_show_short(pv_t * pv); +void pv_display_pe(pv_t * pv, pe_disk_t * pe); +void pv_display_pe_free(int pe_free, int p); +void pv_display_pe_text(pv_t * pv, pe_disk_t * pe, lv_disk_t * lvs); + +static inline unsigned long get_pe_offset(ulong p, pv_t *pv) +{ + return pv->pe_start + (p * pv->pe_size); +} + +#endif diff --git a/lib/log/log.h b/lib/log/log.h index 07396a183..8d478f3db 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -1,9 +1,6 @@ /* - * tools/lib/lvm_log.h - * * Copyright (C) 2001 Sistina Software * - * * This LVM library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either @@ -21,16 +18,8 @@ * */ -/* - * Changelog - * - * 22/01/2001 - First version (Joe Thornber) - * 25/04/2001 - Remove some spurious ##s that annoyed newer gcc versions. - * - */ - -#ifndef LVM_LOG_H -#define LVM_LOG_H +#ifndef _LVM_LOG_H +#define _LVM_LOG_H #include diff --git a/lib/metadata/lvm_v1.c b/lib/metadata/lvm_v1.c new file mode 100644 index 000000000..3306d50db --- /dev/null +++ b/lib/metadata/lvm_v1.c @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include + +#include "mm/dbg_malloc.h" +#include "dev-mgr/dev-manager.h" +#include "log/log.h" +#include "metadata/metadata.h" + +/* + * FIXME: these should not allocate memory + */ + +pv_t *pv_copy_from_disk(pv_disk_t * pv_disk) +{ + pv_t *pv; + + if (!pv_disk || !(pv = (pv_t *) dbg_malloc(sizeof (*pv)))) + return 0; + +#define xx16(v) pv->v = LVM_TO_CORE16(pv_disk->v) +#define xx32(v) pv->v = LVM_TO_CORE32(pv_disk->v) + + memset(pv, 0, sizeof (*pv)); + strncpy(pv->id, pv_disk->id, sizeof (pv->id)); + + xx16(version); + xx32(pv_on_disk.base); + xx32(pv_on_disk.size); + xx32(vg_on_disk.base); + xx32(vg_on_disk.size); + xx32(pv_uuidlist_on_disk.base); + xx32(pv_uuidlist_on_disk.size); + xx32(lv_on_disk.base); + xx32(lv_on_disk.size); + xx32(pe_on_disk.base); + xx32(pe_on_disk.size); + + memset(pv->pv_name, 0, sizeof (pv->pv_name)); + memset(pv->pv_uuid, 0, sizeof (pv->pv_uuid)); + memcpy(pv->pv_uuid, pv_disk->pv_uuid, UUID_LEN); + strncpy(pv->vg_name, pv_disk->vg_name, sizeof (pv->vg_name)); + strncpy(pv->system_id, pv_disk->system_id, sizeof (pv->system_id)); + + pv->pv_dev = LVM_TO_CORE32(pv_disk->pv_major); + + xx32(pv_number); + xx32(pv_status); + xx32(pv_allocatable); + xx32(pv_size); + xx32(lv_cur); + xx32(pe_size); + xx32(pe_total); + xx32(pe_allocated); + pv->pe_stale = 0; + xx32(pe_start); + +#undef xx16 +#undef xx32 + + return pv; +} + +pv_disk_t *pv_copy_to_disk(pv_t * pv_core) +{ + pv_disk_t *pv; + + if (!pv_core || !(pv = dbg_malloc(sizeof (*pv)))) + return 0; + +#define xx16(v) pv->v = LVM_TO_DISK16(pv_core->v) +#define xx32(v) pv->v = LVM_TO_DISK32(pv_core->v) + + memset(pv, 0, sizeof (*pv)); + strncpy(pv->id, pv_core->id, sizeof (pv->id)); + + xx16(version); + xx32(pv_on_disk.base); + xx32(pv_on_disk.size); + xx32(vg_on_disk.base); + xx32(vg_on_disk.size); + xx32(pv_uuidlist_on_disk.base); + xx32(pv_uuidlist_on_disk.size); + xx32(lv_on_disk.base); + xx32(lv_on_disk.size); + xx32(pe_on_disk.base); + xx32(pe_on_disk.size); + + memcpy(pv->pv_uuid, pv_core->pv_uuid, UUID_LEN); + strncpy(pv->vg_name, pv_core->vg_name, sizeof (pv->vg_name)); + strncpy(pv->system_id, pv_core->system_id, sizeof (pv->system_id)); + + /* core type is kdev_t; but no matter what it is, + only store major for check in pv_read() */ + pv->pv_major = LVM_TO_DISK32(MAJOR(pv_core->pv_dev)); + xx32(pv_number); + xx32(pv_status); + xx32(pv_allocatable); + xx32(pv_size); + xx32(lv_cur); + xx32(pe_size); + xx32(pe_total); + xx32(pe_allocated); + xx32(pe_start); + +#undef xx16 +#undef xx32 + + return pv; +} + +lv_t *lv_copy_from_disk(lv_disk_t * lv_disk) +{ + lv_t *lv; + + if (!lv_disk || !(lv = dbg_malloc(sizeof (*lv)))) + return 0; + + memset(lv, 0, sizeof (*lv)); + +#define xx16(v) lv->v = LVM_TO_CORE16(lv_disk->v) +#define xx32(v) lv->v = LVM_TO_CORE32(lv_disk->v) + + strncpy(lv->lv_name, lv_disk->lv_name, sizeof (lv->lv_name)); + strncpy(lv->vg_name, lv_disk->vg_name, sizeof (lv->vg_name)); + + xx32(lv_access); + xx32(lv_status); + + lv->lv_open = 0; + + xx32(lv_dev); + xx32(lv_number); + xx32(lv_mirror_copies); + xx32(lv_recovery); + xx32(lv_schedule); + xx32(lv_size); + + lv->lv_current_pe = NULL; + + xx32(lv_allocated_le); + + lv->lv_current_le = lv->lv_allocated_le; + + xx32(lv_stripes); + xx32(lv_stripesize); + xx32(lv_badblock); + xx32(lv_allocation); + xx32(lv_io_timeout); + xx32(lv_read_ahead); + + lv->lv_snapshot_org = NULL; + lv->lv_snapshot_prev = NULL; + lv->lv_snapshot_next = NULL; + lv->lv_block_exception = NULL; + lv->lv_remap_ptr = 0; + lv->lv_remap_end = 0; + + xx32(lv_snapshot_minor); + xx16(lv_chunk_size); + +#undef xx32 +#undef xx16 + + return lv; +} + +lv_disk_t *lv_copy_to_disk(lv_t * lv_core) +{ + lv_disk_t *lv; + + if (!lv_core || !(lv = dbg_malloc(sizeof (*lv)))) + return 0; + + memset(lv, 0, sizeof (*lv)); + +#define xx16(v) lv->v = LVM_TO_DISK16(lv_core->v) +#define xx32(v) lv->v = LVM_TO_DISK32(lv_core->v) + + strncpy(lv->lv_name, lv_core->lv_name, sizeof (lv->lv_name)); + strncpy(lv->vg_name, lv_core->vg_name, sizeof (lv->vg_name)); + + xx32(lv_access); + xx32(lv_status); + + lv->lv_open = 0; + + xx32(lv_dev); + xx32(lv_number); + xx32(lv_mirror_copies); + xx32(lv_recovery); + xx32(lv_schedule); + xx32(lv_size); + xx32(lv_snapshot_minor); + xx16(lv_chunk_size); + + lv->dummy = 0; + + xx32(lv_allocated_le); + xx32(lv_stripes); + xx32(lv_stripesize); + xx32(lv_badblock); + xx32(lv_allocation); + xx32(lv_io_timeout); + xx32(lv_read_ahead); + +#undef xx32 +#undef xx16 + + return lv; +} + +vg_t *vg_copy_from_disk(vg_disk_t * vg_disk) +{ + vg_t *vg; + + if (!vg_disk || !(vg = dbg_malloc(sizeof (*vg)))) + return 0; + +#define xx32(v) vg->v = LVM_TO_CORE32(vg_disk->v) + + memset(vg, 0, sizeof (vg_t)); + + xx32(vg_number); + xx32(vg_access); + xx32(vg_status); + xx32(lv_max); + xx32(lv_cur); + + vg->lv_open = 0; + + xx32(pv_max); + xx32(pv_cur); + xx32(pv_act); + + vg->dummy = 0; + + xx32(vgda); + xx32(pe_size); + xx32(pe_total); + xx32(pe_allocated); + xx32(pvg_total); + +#undef xx32 + + memset(&vg->pv, 0, sizeof (vg->pv)); + memset(&vg->lv, 0, sizeof (vg->lv)); + + memset(vg->vg_uuid, 0, sizeof (vg->vg_uuid)); + memcpy(vg->vg_uuid, vg_disk->vg_uuid, UUID_LEN); + + return vg; +} + +vg_disk_t *vg_copy_to_disk(vg_t * vg_core) +{ + vg_disk_t *vg; + + if (!vg_core || +/* FIXME: vg_check_consistency(vg_core) || */ + !(vg = dbg_malloc(sizeof (*vg)))) + return 0; + + memset(vg, 0, sizeof (*vg)); + +#define xx32(v) vg->v = LVM_TO_DISK32(vg_core->v) + + xx32(vg_number); + xx32(vg_access); + xx32(vg_status); + xx32(lv_max); + xx32(lv_cur); + + vg->lv_open = 0; + + xx32(pv_max); + xx32(pv_cur); + xx32(pv_act); + + vg->dummy = 0; + + xx32(vgda); + xx32(pe_size); + xx32(pe_total); + xx32(pe_allocated); + xx32(pvg_total); + +#undef xx32 + + memcpy(vg->vg_uuid, vg_core->vg_uuid, UUID_LEN); + + return vg; +} + +pe_disk_t *pe_copy_from_disk(pe_disk_t * pe_file, int count) +{ + int i; + pe_disk_t *pe; + size_t s = sizeof (*pe) * count; + + if (!pe_file || count <= 0 || !(pe = dbg_malloc(s))) + return 0; + + memset(pe, 0, s); + for (i = 0; i < count; i++) { + pe[i].lv_num = LVM_TO_CORE16(pe_file[i].lv_num); + pe[i].le_num = LVM_TO_CORE16(pe_file[i].le_num); + } + + return pe; +} + +pe_disk_t *pe_copy_to_disk(pe_disk_t * pe_core, int count) +{ + int i; + pe_disk_t *pe; + size_t s = sizeof (*pe) * count; + + if (!pe_core || count <= 0 || !(pe = dbg_malloc(s))) + return 0; + + memset(pe, 0, s); + for (i = 0; i < count; i++) { + pe[i].lv_num = LVM_TO_DISK16(pe_core[i].lv_num); + pe[i].le_num = LVM_TO_DISK16(pe_core[i].le_num); + } + + return pe; +} + +pv_t *pv_read_lvm_v1(struct dev_mgr * dm, const char *pv_name) +{ + int pv_handle = -1; + ssize_t read_ret; + ssize_t bytes_read = 0; + static pv_disk_t pv_this; + struct stat stat_b; + pv_t *pv = NULL; + struct device *pv_dev; + + if ((pv_handle = open(pv_name, O_RDONLY)) == -1) { + log_error("%s: open failed: %s", pv_name, strerror(errno)); + return NULL; + } + + if ((fstat(pv_handle, &stat_b))) { + log_error("%s: fstat failed: %s", pv_name, strerror(errno)); + goto pv_read_lvm_v1_out; + } + + while ((bytes_read < sizeof (pv_this) && + (read_ret = read(pv_handle, &pv_this + bytes_read, + sizeof (pv_this) - bytes_read)) != -1)) + bytes_read += read_ret; + + if (read_ret == -1) { + log_error("%s: read failed: %s", pv_name, strerror(errno)); + goto pv_read_lvm_v1_out; + } + + pv = pv_copy_from_disk(&pv_this); + + /* correct for imported/moved volumes */ + if (!(pv_dev = dev_by_dev(dm, stat_b.st_rdev))) { + log_error("Device missing from cache"); + goto pv_read_lvm_v1_out; + } + + memset(pv->pv_name, 0, sizeof (pv->pv_name)); + strncpy(pv->pv_name, pv_dev->name, sizeof (pv->pv_name) - 1); + + /* FIXME: Deleted version / consistency / export checks! */ + + pv->pv_dev = stat_b.st_rdev; + + pv_read_lvm_v1_out: + if (pv_handle != -1) + close(pv_handle); + + return pv; +} + +pe_disk_t *pv_read_pe_lvm_v1(const char *pv_name, const pv_t * pv) +{ + int pv_handle = -1; + uint size = 0; + ssize_t read_ret; + ssize_t bytes_read = 0; + pe_disk_t *pe = NULL; + pe_disk_t *pe_this; + + size = pv->pe_total * sizeof (pe_disk_t); + if (size > pv->pe_on_disk.size) { + log_error("PEs extend beyond end of volume group!"); + return pe; /*NULL*/ + } + + if ((pv_handle = open(pv_name, O_RDONLY)) == -1) { + log_error("%s: open failed: %s", pv_name, strerror(errno)); + goto pv_read_pe_out; + } + + if (lseek(pv_handle, pv->pe_on_disk.base, SEEK_SET) != + pv->pe_on_disk.base) { + log_error("%s: lseek to PE failed: %s", pv_name, strerror(errno)); + goto pv_read_pe_out; + } + + if (!(pe_this = dbg_malloc(size))) { + log_error("PE malloc failed"); + goto pv_read_pe_out; + } + + while ((bytes_read < size && + (read_ret = read(pv_handle, (void *)pe_this + bytes_read, + size - bytes_read)) != -1)) + bytes_read += read_ret; + + if (read_ret == -1) { + log_error("%s: read failed: %s", pv_name, strerror(errno)); + goto pv_read_pe_out; + } + + pe = pe_copy_from_disk(pe_this, pv->pe_total); + + pv_read_pe_out: + if (pv_handle != -1) + close(pv_handle); + + dbg_free(pe_this); + + return pe; +} + +lv_disk_t *pv_read_lvs_lvm_v1(const pv_t *pv) +{ + int pv_handle = -1; + uint size = 0; + ssize_t read_ret; + ssize_t bytes_read = 0; + lv_disk_t *lvs; + + /* FIXME: replace lv_cur? */ + size = pv->lv_cur * sizeof (lv_disk_t); + + if ((pv_handle = open(pv->pv_name, O_RDONLY)) == -1) { + log_error("%s: open failed: %s", pv->pv_name, strerror(errno)); + goto pv_read_lvs_out; + } + + if (lseek(pv_handle, pv->lv_on_disk.base, SEEK_SET) != + pv->lv_on_disk.base) { + log_error("%s: lseek to LV failed: %s", pv->pv_name, strerror(errno)); + goto pv_read_lvs_out; + } + + if (!(lvs = dbg_malloc(size))) { + log_error("PE malloc failed"); + goto pv_read_lvs_out; + } + + while ((bytes_read < size && + (read_ret = read(pv_handle, (void *) lvs + bytes_read, + size - bytes_read)) != -1)) + bytes_read += read_ret; + + if (read_ret == -1) { + log_error("%s: read failed: %s", pv->pv_name, strerror(errno)); + goto pv_read_lvs_out; + } + + pv_read_lvs_out: + if (pv_handle != -1) + close(pv_handle); + + /* Caller frees */ + return lvs; +} + diff --git a/lib/metadata/lvm_v1.h b/lib/metadata/lvm_v1.h new file mode 100644 index 000000000..556c6565c --- /dev/null +++ b/lib/metadata/lvm_v1.h @@ -0,0 +1,208 @@ +/* + * 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 GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _LVM_V1_H_INCLUDE +#define _LVM_V1_H_INCLUDE + +#ifdef __KERNEL__ +#include +#include +#else +#define __KERNEL__ +#include +#include +#undef __KERNEL__ +#endif /* #ifndef __KERNEL__ */ + +#include +#include +#include +#include +#include + +#include +#include + +typedef unsigned long blkoff_t; + +#ifndef uint8_t +# define uint8_t unsigned char +#endif +#ifndef uint16_t +# define uint16_t unsigned short int +#endif +#ifndef uint32_t +# define uint32_t unsigned int +#endif +#ifndef uint64_t +# define uint64_t unsigned long long int +#endif + +/* + * This is basically the on disk metadata layout version. + */ +#define LVM_STRUCT_VERSION 2 + +/* + * Limits for VGs, PVs per VG and LVs per VG. The ABS_* limit's are + * used in defining the data structures, MAX_* are the real limits + * used. + */ +#define MAX_VG 99 +#define MAX_PV 256 +#define MAX_LV 256 /* caused by 8 bit minor */ + +#define NAME_LEN 128 /* the maximum length of various names */ +#define UUID_LEN 32 /* some components have unique identifiers */ + + +/* + * A little struct to hold a sector range on a block device. Used to + * hold the location of on disk metadata + */ +typedef struct { + uint32_t base; + uint32_t size; +} lvm_disk_data_t; + + +/*********************************************************** + * On disk representation: + * + * The beginning of each PV contains metadata, known int the Volume + * Group Data Area (VGDA). This metadata has the following structure: + * + * offset description size + * --------------- ---------------------------------- ------------ + * 0 physical volume structure ~500 byte + * 1K volume group structure ~200 byte + * 6K namelist of physical volumes 128 byte each + * + n * ~300byte n logical volume structures ~300 byte each + * + m * 4byte m physical extent alloc. structs 4 byte each + * + ~ 1 PE size physical extents total * size + * + * Spaces are left between the structures for later extensions. + ***********************************************************/ + +/* + * physical volume - disk + */ +typedef struct { + uint8_t id[2]; /* identifier */ + uint16_t version; /* lvm struct version */ + + /* these define the locations of various bits of on disk metadata */ + lvm_disk_data_t pv_on_disk; /* pv_disk_t location */ + lvm_disk_data_t vg_on_disk; /* vg_disk_t location */ + lvm_disk_data_t pv_uuidlist_on_disk; /* uuid list location */ + lvm_disk_data_t lv_on_disk; /* lv_disk_t locations */ + lvm_disk_data_t pe_on_disk; /* pe mapping table location */ + + uint8_t pv_uuid[NAME_LEN]; /* uuid for this PV */ + uint8_t vg_name[NAME_LEN]; /* which vg it belongs to */ + uint8_t system_id[NAME_LEN]; /* for vgexport/vgimport */ + uint32_t pv_major; + uint32_t pv_number; + uint32_t pv_status; + uint32_t pv_allocatable; + uint32_t pv_size; + uint32_t lv_cur; + uint32_t pe_size; + uint32_t pe_total; + uint32_t pe_allocated; + + /* data_location.base holds the start of the pe's in sectors */ + uint32_t pe_start; +} pv_disk_t; + +/* + * logical volume - disk + */ +typedef struct { + uint8_t lv_name[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + uint32_t lv_access; + uint32_t lv_status; + uint32_t lv_open; + uint32_t lv_dev; + uint32_t lv_number; + uint32_t lv_mirror_copies; /* for future use */ + uint32_t lv_recovery; /* " */ + uint32_t lv_schedule; /* " */ + uint32_t lv_size; + uint32_t lv_snapshot_minor; /* minor number of origin */ + uint16_t lv_chunk_size; /* chunk size of snapshot */ + uint16_t dummy; + uint32_t lv_allocated_le; + uint32_t lv_stripes; + uint32_t lv_stripesize; + uint32_t lv_badblock; /* for future use */ + uint32_t lv_allocation; + uint32_t lv_io_timeout; /* for future use */ + uint32_t lv_read_ahead; +} lv_disk_t; + +/* + * volume group - disk + */ +typedef struct { + uint8_t vg_uuid[UUID_LEN]; /* volume group UUID */ + + /* rest of v1 VG name */ + uint8_t vg_name_dummy[NAME_LEN-UUID_LEN]; + uint32_t vg_number; /* volume group number */ + uint32_t vg_access; /* read/write */ + uint32_t vg_status; /* active or not */ + uint32_t lv_max; /* maximum logical volumes */ + uint32_t lv_cur; /* current logical volumes */ + uint32_t lv_open; /* open logical volumes */ + uint32_t pv_max; /* maximum physical volumes */ + uint32_t pv_cur; /* current physical volumes FU */ + uint32_t pv_act; /* active physical volumes */ + uint32_t dummy; + uint32_t vgda; /* volume group descriptor arrays FU */ + uint32_t pe_size; /* physical extent size in sectors */ + uint32_t pe_total; /* total of physical extents */ + uint32_t pe_allocated; /* allocated physical extents */ + uint32_t pvg_total; /* physical volume groups FU */ +} vg_disk_t; + +/* + * pe mapping - disk + */ +typedef struct { + uint16_t lv_num; + uint16_t le_num; +} pe_disk_t; + +/* + * copy on write tables - disk + */ +typedef struct lv_COW_table_disk_v1 { + uint64_t pv_org_number; + uint64_t pv_org_rsector; + uint64_t pv_snap_number; + uint64_t pv_snap_rsector; +} lv_COW_table_disk_t; + + + +#endif + diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c new file mode 100644 index 000000000..ab59bd7cb --- /dev/null +++ b/lib/metadata/metadata.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#include +#include "mm/dbg_malloc.h" +#include "dev-mgr/dev-manager.h" +#include "log/log.h" +#include "metadata/metadata.h" + +/* FIXME: Use registered fn ptrs to avoid including this? */ +/* Split into external/internal hdr files? */ +#include "metadata/lvm_v1.h" + +pv_t *pv_read(struct dev_mgr *dm, const char *pv_name) +{ + /* FIXME: Use config to select lvm_v1 format? Cache results? */ + /* Pass structure around rather than pv_name? */ + + log_very_verbose("Reading metadata from %s", pv_name); + + return pv_read_lvm_v1(dm, pv_name); + +} + +pe_disk_t *pv_read_pe(const char *pv_name, const pv_t * pv) +{ + log_very_verbose("Reading PE metadata from %s", pv_name); + + return pv_read_pe_lvm_v1(pv_name, pv); +} + +lv_disk_t *pv_read_lvs(const pv_t *pv) +{ + log_very_verbose("Reading LV metadata from %s", pv->pv_name); + + return pv_read_lvs_lvm_v1(pv); +} diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h new file mode 100644 index 000000000..6c7068f69 --- /dev/null +++ b/lib/metadata/metadata.h @@ -0,0 +1,368 @@ +/* + * 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 GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* FIXME: LVM1-format-specific stuff should be in lvm_v1.h instead */ + +#ifndef _LVM_METADATA_H +#define _LVM_METADATA_H + +#include "metadata/lvm_v1.h" + +/*********************************************************** + * In core data representation. + ***********************************************************/ + +/* + * physical volume - core + */ +typedef struct pv { + char id[2]; /* Identifier */ + unsigned short version; /* HM lvm version */ + lvm_disk_data_t pv_on_disk; + lvm_disk_data_t vg_on_disk; + lvm_disk_data_t pv_uuidlist_on_disk; + lvm_disk_data_t lv_on_disk; + lvm_disk_data_t pe_on_disk; + char pv_name[NAME_LEN]; + char vg_name[NAME_LEN]; + char system_id[NAME_LEN]; /* for vgexport/vgimport */ + kdev_t pv_dev; + uint pv_number; + uint pv_status; + uint pv_allocatable; + uint pv_size; /* HM */ + uint lv_cur; + uint pe_size; + uint pe_total; + uint pe_allocated; + uint pe_stale; /* for future use */ + pe_disk_t *pe; /* HM */ + struct block_device *bd; + char pv_uuid[UUID_LEN+1]; +#ifdef __KERNEL__ +#else + uint32_t pe_start; + char dummy[39]; +#endif +} pv_t; + + +/* + * extent descriptor - core + */ +typedef struct { + kdev_t dev; + uint32_t pe; /* to be changed if > 2TB */ + uint32_t reads; + uint32_t writes; +} pe_t; + +/* + * block exception descriptor for snapshots - core + */ +typedef struct lv_block_exception_v1 { + struct list_head hash; + uint32_t rsector_org; + kdev_t rdev_org; + uint32_t rsector_new; + kdev_t rdev_new; +} lv_block_exception_t; + + +/* + * logical volume - core + */ +typedef struct lv { + char lv_name[NAME_LEN]; + char vg_name[NAME_LEN]; + uint lv_access; + uint lv_status; + uint lv_open; + kdev_t lv_dev; + uint lv_number; + uint lv_mirror_copies; /* for future use */ + uint lv_recovery; /* " */ + uint lv_schedule; /* " */ + uint lv_size; + pe_t *lv_current_pe; + uint lv_current_le; /* for future use */ + uint lv_allocated_le; + uint lv_stripes; + uint lv_stripesize; + uint lv_badblock; /* for future use */ + uint lv_allocation; + uint lv_io_timeout; /* for future use */ + uint lv_read_ahead; + + /* delta to version 1 starts here */ + struct lv *lv_snapshot_org; + struct lv *lv_snapshot_prev; + struct lv *lv_snapshot_next; + lv_block_exception_t *lv_block_exception; + uint lv_remap_ptr; + uint lv_remap_end; + uint lv_chunk_size; + uint lv_snapshot_minor; + uint32_t chunk_shift; + uint32_t chunk_mask; + +} lv_t; + +/* + * volume group - core + */ +typedef struct { + char vg_name[NAME_LEN]; /* volume group name */ + uint vg_number; /* volume group number */ + uint vg_access; /* read/write */ + uint vg_status; /* active or not */ + uint lv_max; /* maximum logical volumes */ + uint lv_cur; /* current logical volumes */ + uint lv_open; /* open logical volumes */ + uint pv_max; /* maximum physical volumes */ + uint pv_cur; /* current physical volumes FU */ + uint pv_act; /* active physical volumes */ + uint dummy; /* was obsolete max_pe_per_pv */ + uint vgda; /* volume group descriptor arrays FU */ + uint pe_size; /* physical extent size in sectors */ + uint pe_total; /* total of physical extents */ + uint pe_allocated; /* allocated physical extents */ + uint pvg_total; /* physical volume groups FU */ + struct proc_dir_entry *proc; + pv_t *pv[MAX_PV]; /* physical volume struct pointers */ + lv_t *lv[MAX_LV]; /* logical volume struct pointers */ + char vg_uuid[UUID_LEN+1]; /* volume group UUID */ + uint32_t pe_shift; + uint32_t pe_mask; + + struct proc_dir_entry *vg_dir_pde; + struct proc_dir_entry *lv_subdir_pde; + struct proc_dir_entry *pv_subdir_pde; +} vg_t; + + +/*********************************************************** + * Status flags + **********************************************************/ + +/* volume group */ +#define VG_ACTIVE 0x01 /* vg_status */ +#define VG_EXPORTED 0x02 /* " */ +#define VG_EXTENDABLE 0x04 /* " */ + +#define VG_READ 0x01 /* vg_access */ +#define VG_WRITE 0x02 /* " */ +#define VG_CLUSTERED 0x04 /* " */ +#define VG_SHARED 0x08 /* " */ + +/* logical volume */ +#define LV_ACTIVE 0x01 /* lv_status */ +#define LV_SPINDOWN 0x02 /* " */ + +#define LV_READ 0x01 /* lv_access */ +#define LV_WRITE 0x02 /* " */ +#define LV_SNAPSHOT 0x04 /* " */ +#define LV_SNAPSHOT_ORG 0x08 /* " */ + +#define LV_BADBLOCK_ON 0x01 /* lv_badblock */ + +#define LV_STRICT 0x01 /* lv_allocation */ +#define LV_CONTIGUOUS 0x02 /* " */ + +/* physical volume */ +#define PV_ACTIVE 0x01 /* pv_status */ +#define PV_ALLOCATABLE 0x02 /* pv_allocatable */ + + +/* misc */ +#define LVM_SNAPSHOT_DROPPED_SECTOR 1 + + +/*********************************************************** + * Constants and limits + **********************************************************/ + +/* + * LVM_PE_T_MAX corresponds to: + * 8KB PE size can map a ~512 MB logical volume at the cost of 1MB memory, + * 128MB PE size can map a 8TB logical volume at the same cost of memory. + * + * Default PE size of 4 MB gives a maximum logical volume size of 256 GB. + * Maximum PE size of 16GB gives a maximum logical volume size of 1024 TB. + * + * AFAIK, the actual kernels limit this to 1 TB. + * + * Should be a sufficient spectrum + */ + +/* This is the usable size of pe_disk_t.le_num */ +#define LVM_PE_T_MAX ((1 << (sizeof(uint16_t) * 8)) - 2) + +/* FIXME: these numbers look like they could get too big */ +#define LVM_LV_SIZE_MAX(a) \ +((long long) LVM_PE_T_MAX * (a)->pe_size > \ + (long long) 1024 * 1024 / SECTOR_SIZE * 1024 * 1024 ? \ + (long long) 1024 * 1024 / SECTOR_SIZE * 1024 * 1024 : \ + (long long) LVM_PE_T_MAX * (a)->pe_size) + +#define LVM_MIN_PE_SIZE (8192L / SECTOR_SIZE) /* 8 KB in sectors */ + +/* 16GB in sectors */ +#define LVM_MAX_PE_SIZE ((16L * 1024L * 1024L / SECTOR_SIZE) * 1024) + +/* 4 MB in sectors */ +#define LVM_DEFAULT_PE_SIZE (4096L * 1024 / SECTOR_SIZE) + +#define LVM_DEFAULT_STRIPE_SIZE 16L /* 16 KB */ + +/* PAGESIZE in sectors */ +#define LVM_MIN_STRIPE_SIZE (PAGE_SIZE / SECTOR_SIZE) + +/* 512 KB in sectors */ +#define LVM_MAX_STRIPE_SIZE (512L * 1024 / SECTOR_SIZE) + +#define LVM_MAX_STRIPES 128 /* max # of stripes */ + +/* 1TB[sectors] */ +#define LVM_MAX_SIZE (1024LU * 1024 / SECTOR_SIZE * 1024 * 1024) + +#define LVM_MAX_MIRRORS 2 /* future use */ +#define LVM_MIN_READ_AHEAD 2 /* minimum read ahead sectors */ +#define LVM_MAX_READ_AHEAD 120 /* maximum read ahead sectors */ +#define LVM_MAX_LV_IO_TIMEOUT 60 /* seconds I/O timeout (future use) */ +#define LVM_PARTITION 0xfe /* LVM partition id */ +#define LVM_NEW_PARTITION 0x8e /* new LVM partition id (10/09/1999) */ +#define LVM_PE_SIZE_PV_SIZE_REL 5 /* max relation PV size and PE size */ + +#define LVM_SNAPSHOT_MAX_CHUNK 1024 /* 1024 KB */ +#define LVM_SNAPSHOT_DEF_CHUNK 64 /* 64 KB */ +#define LVM_SNAPSHOT_MIN_CHUNK (PAGE_SIZE / 1024) /* 4 or 8 KB */ + +#define lvm_version "device-mapper-1" + +#ifdef _G_LSEEK64 +int lseek64 ( unsigned int, unsigned long long, unsigned int); +#define llseek lseek64 +#else +int llseek ( unsigned int, unsigned long long, unsigned int); +#endif + +#define LVM_ID "HM" /* Identifier PV (id in pv_t) */ +#define EXPORTED "PV_EXP" /* Identifier exported PV (system_id in pv_t) */ +#define IMPORTED "PV_IMP" /* Identifier imported PV ( " ) */ +#define DISK_NAME_LEN 8 +#define LV_MIN_NAME_LEN 5 +#define LV_MAX_NAME_LEN 7 +#define MIN_PART 1 +#define MAX_PART 15 + +/* some metadata on the disk need to be aligned */ +#define LVM_VGDA_ALIGN 4096UL + +/* base of PV structure in disk partition */ +#define LVM_PV_DISK_BASE 0L + +/* size reserved for PV structure on disk */ +#define LVM_PV_DISK_SIZE 1024L + +/* base of VG structure in disk partition */ +#define LVM_VG_DISK_BASE round_up(LVM_PV_DISK_BASE + LVM_PV_DISK_SIZE, \ + LVM_VGDA_ALIGN) + +/* size reserved for VG structure */ +#define LVM_VG_DISK_SIZE (8 * 512L) + +/* name list of physical volumes on disk */ +#define LVM_PV_UUIDLIST_DISK_BASE round_up(LVM_VG_DISK_BASE + \ + LVM_VG_DISK_SIZE, LVM_VGDA_ALIGN) + +/* now for the dynamically calculated parts of the VGDA */ +#define LVM_LV_DISK_OFFSET(a, b) ((a)->lv_on_disk.base + sizeof(lv_disk_t) * b) + +#define LVM_VGDA_SIZE(pv) ((pv)->pe_on_disk.base + (pv)->pe_on_disk.size) + +#define LVM_PE_ALIGN (65536UL / SECTOR_SIZE) + +/* core <-> disk conversion macros */ +#if __BYTE_ORDER == __BIG_ENDIAN +#define LVM_TO_CORE16(x) ( \ + ((uint16_t)((((uint16_t)(x) & 0x00FFU) << 8) | \ + (((uint16_t)(x) & 0xFF00U) >> 8)))) + +#define LVM_TO_DISK16(x) LVM_TO_CORE16(x) + +#define LVM_TO_CORE32(x) ( \ + ((uint32_t)((((uint32_t)(x) & 0x000000FFU) << 24) | \ + (((uint32_t)(x) & 0x0000FF00U) << 8) | \ + (((uint32_t)(x) & 0x00FF0000U) >> 8) | \ + (((uint32_t)(x) & 0xFF000000U) >> 24)))) + +#define LVM_TO_DISK32(x) LVM_TO_CORE32(x) + +#define LVM_TO_CORE64(x) \ + ((uint64_t)((((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \ + (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \ + (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \ + (((uint64_t)(x) & 0x00000000FF000000ULL) << 8) | \ + (((uint64_t)(x) & 0x000000FF00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56))) + +#define LVM_TO_DISK64(x) LVM_TO_CORE64(x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define LVM_TO_CORE16(x) x +#define LVM_TO_DISK16(x) x +#define LVM_TO_CORE32(x) x +#define LVM_TO_DISK32(x) x +#define LVM_TO_CORE64(x) x +#define LVM_TO_DISK64(x) x +#else +#error "__BYTE_ORDER must be defined as __LITTLE_ENDIAN or __BIG_ENDIAN" +#endif /* #if __BYTE_ORDER == __BIG_ENDIAN */ + +/* return codes */ +#define LVM_VG_CFGBACKUP_NO_DIFF 100 + +#define BLOCK_SIZE 1024 +#define SECTOR_SIZE 512 + +#define UNDEF -1 + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + + +/* FIXME */ +#include "dev-mgr/dev-manager.h" +pv_t *pv_read_lvm_v1(struct dev_mgr *dm, const char *pv_name); +pv_t *pv_read(struct dev_mgr *dm, const char *pv_name); +pe_disk_t *pv_read_pe(const char *pv_name, const pv_t *pv); + +pe_disk_t *pv_read_pe_lvm_v1(const char *pv_name, const pv_t * pv); +lv_disk_t *pv_read_lvs(const pv_t *pv); +lv_disk_t *pv_read_lvs_lvm_v1(const pv_t *pv); + +#endif + diff --git a/lib/mm/dbg_malloc.h b/lib/mm/dbg_malloc.h index 3dbc251d8..94914cf87 100644 --- a/lib/mm/dbg_malloc.h +++ b/lib/mm/dbg_malloc.h @@ -1,7 +1,5 @@ /* - * debug.h - what a wonderfully original name for a file. - * - * Copyright (C) 2000, 2001 Sistina Software + * 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 @@ -18,16 +16,10 @@ * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * Changelog - * - * 9/11/2000 - First version by Joe Thornber - * - * TODO: - * */ -#ifndef DBG_MALLOC_H -#define DBG_MALLOC_H +#ifndef _LVM_DBG_MALLOC_H +#define _LVM_DBG_MALLOC_H #ifdef DEBUG_MEM void *malloc_aux(unsigned int s, const char *file, int line); diff --git a/lib/mm/pool.h b/lib/mm/pool.h index 89b6438a5..a9ba9d3f8 100644 --- a/lib/mm/pool.h +++ b/lib/mm/pool.h @@ -1,6 +1,4 @@ /* - * tools/lib/pool.h - * * Copyright (C) 2001 Sistina Software * * LVM is free software; you can redistribute it and/or modify @@ -19,8 +17,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef POOL_H -#define POOL_H +#ifndef _LVM_POOL_H +#define _LVM_POOL_H #include diff --git a/man/pvdisplay.8 b/man/pvdisplay.8 new file mode 100644 index 000000000..d32200e3a --- /dev/null +++ b/man/pvdisplay.8 @@ -0,0 +1,67 @@ +.TH PVDISPLAY 8 "LVM TOOLS" "Heinz Mauelshagen" \" -*- nroff -*- +.SH NAME +pvdisplay \- display attributes of a physical volume +.SH SYNOPSIS +.B pvdisplay +[\-c/\-\-colon] [\-d/\-\-debug] [\-h/\-?/\-\-help] [\-s/\-\-short] +[\-v[v]/\-\-verbose [\-\-verbose]] +PhysicalVolumePath [PhysicalVolumePath...] +.SH DESCRIPTION +pvdisplay allows you to see the attributes of one or more physical volumes +like size, physical extent size, space used for the volume group descriptor +area and so on. +.SS OPTIONS +.TP +.I \-c, \-\-colon +Generate colon seperated output for easier parsing in scripts or programs. +.nf + +The values are: + +* physical volume device name +* volume group name +* physical volume size in kilobytes +* internal physical volume number +* physical volume status +* physical volume (not) allocatable +* current number of logical volumes on this physical volume +* physical extent size in kilobytes +* total number of physical extents +* free number of physical extents +* allocated number of physical extents + +.fi +.TP +.I \-d, \-\-debug +Enables additional debugging output (if compiled with DEBUG). +.TP +.I \-h, \-?, \-\-help +Print a usage message on standard output and exit successfully. +.TP +.I \-s, \-\-short +Only display the size of the given physical volumes. +.TP +.I \-v, \-\-verbose +Display the mapping of physical extents to logical volumes and +logical extents. +.TP +.I \-vv, \-\-verbose \-\-verbose +Like \-v with verbose runtime information about pvdisplay's activities. +.SH DIAGNOSTICS +pvdisplay returns an code state of 0 for success and > 0 for error: +.nf + +1 no physical volume name on command line +2 error checking consistency of physical volume +3 error reading physical extent information from physical volume + +95 driver/module not in kernel +96 invalid I/O protocol version +97 error locking logical volume manager +98 invalid lvmtab (run vgscan(8)) +99 invalid command line +.fi +.SH See also +lvm(8), pvcreate(8), lvcreate(8), vgcreate(8) +.SH AUTHOR +Heinz Mauelshagen diff --git a/tools/Makefile.in b/tools/Makefile.in index 643a5ccdd..44604f572 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -22,6 +22,7 @@ VPATH = @srcdir@ SOURCES=\ lvm.c\ + lvactivate.c\ pvdisplay.c TARGETS=\ diff --git a/tools/args.h b/tools/args.h new file mode 100644 index 000000000..f1f2ee651 --- /dev/null +++ b/tools/args.h @@ -0,0 +1,73 @@ +/* + * 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. + * + */ + +xx(available_ARG, 'a', "available", yes_no_arg) +xx(all_ARG, 'a', "all", yes_no_arg) +xx(autobackup_ARG, 'A', "autobackup", yes_no_arg) +xx(activevolumegroups_ARG, 'A', "activevolumegroups", NULL) +xx(blockdevice_ARG, 'b', "blockdevice", NULL) +xx(chunksize_ARG, 'c', "chunksize", size_arg) +xx(colon_ARG, 'c', "colon", NULL) +xx(contiguous_ARG, 'C', "contiguous", yes_no_arg) +xx(debug_ARG, 'd', "debug", NULL) +xx(disk_ARG, 'D', "disk", NULL) +xx(exported_ARG, 'e', "exported", NULL) +xx(physicalextent_ARG, 'E', "physicalextent", NULL) +xx(file_ARG, 'f', "file", NULL) +xx(force_ARG, 'f', "force", NULL) +xx(full_ARG, 'f', "full", NULL) +xx(help_ARG, 'h', "help", NULL) +xx(stripesize_ARG, 'I', "stripesize", size_arg) +xx(stripes_ARG, 'i', "stripes", int_arg) +xx(iop_version_ARG, 'i', "iop_version", NULL) +xx(logicalvolume_ARG, 'l', "logicalvolume", int_arg) +xx(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg) +xx(extents_ARG, 'l', "extents", int_arg) +xx(lvmpartition_ARG, 'l', "lvmpartition", NULL) +xx(list_ARG, 'l', "list", NULL) +xx(size_ARG, 'L', "size", size_arg) +xx(logicalextent_ARG, 'L', "logicalextent", int_arg) +xx(name_ARG, 'n', "name", string_arg) +xx(oldpath_ARG, 'n', "oldpath", NULL) +xx(nofsck_ARG, 'n', "nofsck", NULL) +xx(novolumegroup_ARG, 'n', "novolumegroup", NULL) +xx(permission_ARG, 'p', "permission", permission_arg) +xx(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg) +xx(physicalvolume_ARG, 'P', "physicalvolume", NULL) +xx(readahead_ARG, 'r', "readahead", int_arg) +xx(reset_ARG, 'R', "reset", NULL) +xx(physicalextentsize_ARG, 's', "physicalextentsize", size_arg) +xx(stdin_ARG, 's', "stdin", NULL) +xx(snapshot_ARG, 's', "snapshot", NULL) +xx(short_ARG, 's', "short", NULL) +xx(test_ARG, 't', "test", NULL) +xx(uuid_ARG, 'u', "uuid", NULL) +xx(uuidlist_ARG, 'U', "uuidlist", NULL) +xx(verbose_ARG, 'v', "verbose", NULL) +xx(volumegroup_ARG, 'V', "volumegroup", NULL) +xx(version_ARG, '\0', "version", NULL) +xx(allocation_ARG, 'x', "allocation", yes_no_arg) +xx(yes_ARG, 'y', "yes", NULL) +xx(zero_ARG, 'Z', "zero", yes_no_arg) +xx(suspend_ARG, 'z', "suspend", NULL) + +/* this should always be last */ +xx(ARG_COUNT, '-', "", NULL) + diff --git a/tools/commands.h b/tools/commands.h new file mode 100644 index 000000000..593ddce26 --- /dev/null +++ b/tools/commands.h @@ -0,0 +1,484 @@ +/* + * 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. + * + */ + +xx(e2fsadm, + "Resize logical volume and ext2 filesystem", + "e2fsadm " + "[-d|--debug] " + "[-h|--help] " + "[-n|--nofsck]\n\t" + "{[-l|--extents] [+|-]LogicalExtentsNumber |\n\t" + " [-L|--size] [+|-]LogicalVolumeSize[kKmMgGtT]}\n\t" + "[-t|--test] " + "[-v|--verbose] " + "[--version] " + "LogicalVolumePath\n", + + extents_ARG, size_ARG, nofsck_ARG, test_ARG) + +xx(help, + "Display help for commands", + "help \n") + +xx(lvactivate, + "Activate logical volume on given partition(s)", + "lvactivate " + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "Physical Volume(s)\n") + +xx(lvchange, + "Change the attributes of logical volume(s)", + "lvchange\n" + "\t[-A/--autobackup y/n]\n" + "\t[-a/--available y/n]\n" + "\t[-C/--contiguous y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-p/--permission r/rw]\n" + "\t[-r/--readahead ReadAheadSectors]\n" + "\t[-v/--verbose]\n" + "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", + + autobackup_ARG, available_ARG, contiguous_ARG, + permission_ARG, readahead_ARG) + +xx(lvcreate, + "Create a logical volume", + "lvcreate " + "[-A|--autobackup {y|n}] " + "[-C|--contiguous {y|n}] " + "[-d|--debug]\n" + "\t[-h|--help] " + "[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n\t" + "{-l|--extents LogicalExtentsNumber |\n\t" + " -L|--size LogicalVolumeSize[kKmMgGtT]} " + "[-n|--name LogicalVolumeName]\n\t" + "[-p|--permission {r|rw}] " + "[-r|--readahead ReadAheadSectors]\n\t" + "[-v|--verbose] " + "[-Z|--zero {y|n}] " + "[--version]\n\t" + "VolumeGroupName [PhysicalVolumePath...]\n\n" + "lvcreate " + "-s|--snapshot " + "[-c|--chunksize ChunkSize]\n\t" + "{-l|--extents LogicalExtentsNumber |\n\t" + " -L|--size LogicalVolumeSize[kKmMgGtT]}\n\t" + "-n|--name SnapshotLogicalVolumeName\n\t" + "LogicalVolume[Path] [PhysicalVolumePath...]\n", + + autobackup_ARG, chunksize_ARG, contiguous_ARG, + stripes_ARG, stripesize_ARG, extents_ARG, size_ARG, name_ARG, + permission_ARG, readahead_ARG, snapshot_ARG, zero_ARG) + +xx(lvdisplay, + "Display information about a logical volume", + "lvdisplay\n" + "\t[-c/--colon]\n" + "\t[-d/--debug]\n" + "\t[-D/--disk]\n" + "\t[-h/-?/--help]\n" + "\t[-v[v]/--verbose [--verbose]]\n" + "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", + + colon_ARG, disk_ARG) + +xx(lvextend, + "Add space to a logical volume", + "lvextend\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t{-l/--extents [+]LogicalExtentsNumber |\n" + "\t -L/--size [+]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-v/--verbose]\n" + "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", + + autobackup_ARG, extents_ARG, size_ARG) + +xx(lvmchange, + "Reset the LVM driver - not for general use", + "lvmchange\n" + "\t[-d/--debug]\n" + "\t[-f/--force]\n" + "\t[-h/-?/--help]\n" + "\t[-i/-?/--iop_version]\n" + "\t[-R/--reset]\n" + "\t[-v/--verbose]\n", + + force_ARG, reset_ARG) + +xx(lvmdiskscan, + "List devices that may be used as physical volumes", + "lvmdiskscan\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-l/--lvmpartition]\n" + "\t[-v/--verbose]\n", + + lvmpartition_ARG) + +xx(lvmsadc, + "Collect activity data", + "lvmsadc\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\t[LogFilePath]\n" ) + +xx(lvmsar, + "Create activity report", + "lvmsar\n" + "\t[-d/--debug]\n" + "\t[-f/--full]\n" + "\t[-h/-?/--help]\n" + "\t[-s/--stdin]\n" + "\t[-v/--verbose]\n" + "\tLogFilePath\n", + + full_ARG, stdin_ARG) + +xx(lvreduce, + "Reduce the size of a logical volume", + "lvreduce\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-f/--force]\n" + "\t[-h/-?/--help]\n" + "\t{-l/--extents [-]LogicalExtentsNumber |\n" + "\t -L/--size [-]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-v/--verbose]\n" + "\tLogicalVolume[Path]\n", + + autobackup_ARG, force_ARG, extents_ARG, + size_ARG, yes_ARG) + +xx(lvremove, + "Remove logical volume(s) from the system", + "lvremove\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-f/--force]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\tLogicalVolume[Path] [LogicalVolume[Path]...]\n", + + autobackup_ARG, force_ARG) + +xx(lvrename, + "Rename a logical volume", + "lvrename " + "[-A|--autobackup {y|n}] " + "[-d|--debug] " + "[-h|--help] " + "[-v|--verbose]\n\t" + "[--version] " + "{ OldLogicalVolumePath NewLogicalVolumePath |\n\t" + " VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName }\n", + + autobackup_ARG) + +xx(lvscan, + "List all logical volumes in all volume groups", + "lvscan " + "[-b|--blockdevice] " + "[-d|--debug] " + "[-D|--disk]\n\t" + "[-h|--help] " + "[-v|--verbose] " + "[--version]\n", + + blockdevice_ARG, disk_ARG) + +xx(pvchange, + "Change attributes of physical volume(s)", + "pvchange\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\t[-a/--all]\n" + "\t[-x/--allocation y/n]\n" + "\t[PhysicalVolumePath...]\n", + + all_ARG, autobackup_ARG, allocation_ARG) + +xx(pvcreate, + "Initialize physical volume(s) for use by LVM", + "pvcreate " + "[-d|--debug]" + "[-f[f]|--force [--force]] " + "[-h|--help] " + "[-y|--yes]\n\t" + "[-v|--verbose] " + "[--version] " + "PhysicalVolume [PhysicalVolume...]\n", + + force_ARG, yes_ARG) + +xx(pvdata, + "Display the on-disk metadata for physical volume(s)", + "pvdata " + "[-a|--all] " + "[-d|--debug] " + "[-E|--physicalextent] " + "[-h|--help]\n\t" + "[-L|--logicalvolume] " + "[-P[P]|--physicalvolume [--physicalvolume]]\n\t" + "[-U|--uuidlist] " + "[-v[v]|--verbose [--verbose]] " + "[-V|--volumegroup]\n\t" + "[--version] " + "PhysicalVolume [PhysicalVolume...]\n", + + all_ARG, logicalextent_ARG, physicalextent_ARG, + physicalvolume_ARG, uuidlist_ARG, volumegroup_ARG) + +xx(pvdisplay, + "Display various attributes of logical volume(s)", + "pvdisplay\n" + "\t[-c/--colon]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-s/--short]\n" + "\t[-v[v]/--verbose [--verbose]]\n" + "\tPhysicalVolumePath [PhysicalVolumePath...]\n", + + colon_ARG, short_ARG) + +#if 0 +xx(pvmove, + "Move extents from one physical volume to another", + "pvmove " + "[-A|--autobackup {y|n}] " + "[-d|--debug] " + "[-f|--force]" + "[-h|--help]\n\t" + "[-t|--test] " + "[-v[v]|--verbose [--verbose]] " + "[--version]\n\t" + "[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n\t" + "SourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n\t" + "[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n", + + autobackup_ARG, force_ARG, name_ARG, test_ARG) +#endif + +xx(pvscan, + "List all physical volumes", + "pvscan " + "[-d|--debug] " + "{-e|--exported | -n/--novolumegroup} " + "[-h|--help]\n\t" + "[-s|--short] " + "[-u|--uuid] " + "[-v[v]|--verbose [--verbose]] " + "[--version]\n", + + exported_ARG, novolumegroup_ARG, short_ARG, uuid_ARG) + +xx(vgcfgbackup, + "Backup volume group configuration(s)", + "vgcfgbackup " + "[-d|--debug] " + "[-h|--help] " + "[-v|--verbose]\n\t" + "[-V|--version] " + "[VolumeGroupName...]\n" ) + +xx(vgcfgrestore, + "Restore volume group configuration", + "vgcfgrestore " + "[-d|--debug] " + "[-f|--file VGConfPath] " + "[-l[l]|--list [--list]]\n\t" + "[-n|--name VolumeGroupName] " + "[-h|--help]\n\t" + "[-o|--oldpath OldPhysicalVolumePath] " + "[-t|--test] " + "[-v|--verbose]\n\t" + "[--version] " + "[PhysicalVolumePath]\n", + + file_ARG, list_ARG, name_ARG, oldpath_ARG, test_ARG) + +xx(vgchange, + "Change volume group attributes", + "vgchange " + "[-A|--autobackup {y|n}] " + "[-d|--debug] " + "[-h|--help]\n\t" + "{-a|--available {y|n} [VolumeGroupName...] |\n\t " + " -x|--allocation {y|n} [VolumeGroupName...]\n\t" + " -l|--logicalvolume MaxLogicalVolumes}\n\t" + "[-v|--verbose] " + "[--version]\n", + + autobackup_ARG, available_ARG, logicalvolume_ARG, allocation_ARG ) + +xx(vgck, + "Check the consistency of volume group(s)", + "vgck " + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\t[VolumeGroupName...]\n" ) + +xx(vgcreate, + "Create a volume group", + "vgcreate" + "[-A|--autobackup {y|n}] " + "[-d|--debug]\n\t" + "[-l|--maxlogicalvolumes MaxLogicalVolumes]\n\t" + "[-p|--maxphysicalvolumes MaxPhysicalVolumes] " + "[-h|--help]\n\t" + "[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " + "[-v|--verbose]\n\t" + "[--version] " + "VolumeGroupName " + "PhysicalVolume [PhysicalVolume...]\n", + + autobackup_ARG, maxlogicalvolumes_ARG, maxphysicalvolumes_ARG, + physicalextentsize_ARG) + +xx(vgdisplay, + "Display volume group information", + "vgdisplay " + "[-c|--colon | -s|--short | -v[v]|--verbose [--verbose]]\n\t" + "[-d|--debug] " + "[-h|--help] " + "[--version]\n\t" + "[-A|--activevolumegroups | [-D|--disk] [VolumeGroupName...] ]\n", + + activevolumegroups_ARG, colon_ARG, disk_ARG, short_ARG) + +xx(vgexport, + "Unregister volume group(s) from the system", + "vgexport " + "[-a|--all] " + "[-d|--debug] " + "[-h|--help]\n\t" + "[-v|--verbose] " + "[--version] " + "VolumeGroupName [VolumeGroupName...]\n", + + all_ARG) + +xx(vgextend, + "Add physical volumes to a volume group", + "vgextend\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\tVolumeGroupName\n" + "\tPhysicalDevicePath [PhysicalDevicePath...]\n", + + autobackup_ARG) + +xx(vgimport, + "Register exported volume group with system", + "vgimport " + "[-d|--debug] " + "[-f|--force] " + "[-h|--help] " + "[-v|--verbose]\n\t" + "VolumeGroupName PhysicalVolumePath " + "[PhysicalVolumePath...]\n", + + force_ARG) + +xx(vgmerge, + "Merge volume groups", + "vgmerge\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-l/--list]\n" + "\t[-t/--test]\n" + "\t[-v/--verbose]\n" + "\tDestinationVolumeGroupName SourceVolumeGroupName\n", + + autobackup_ARG, list_ARG, test_ARG) + +xx(vgmknodes, + "Create the special files for volume group devices in /dev", + "vgmknodes\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\t[VolumeGroupName...]\n" ) + +xx(vgreduce, + "Remove physical volume(s) from a volume group", + "vgreduce\n" + "\t[-a/--all]\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\tVolumeGroupName\n" + "\t[PhysicalVolumePath...]\n", + + all_ARG, autobackup_ARG) + +xx(vgremove, + "Remove volume group(s)", + "vgremove\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\tVolumeGroupName [VolumeGroupName...]\n" ) + +xx(vgrename, + "Rename a volume group", + "vgrename\n" + "\t[-A/--autobackup y/n]\n" + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" + "\tOldVolumeGroupPath NewVolumeGroupPath /\n" + "\tOldVolumeGroupName NewVolumeGroupName\n", + + autobackup_ARG) + +xx(vgscan, + "Search for all volume groups", + "vgscan " + "\t[-d/--debug]\n" + "\t[-h/-?/--help]\n" + "\t[-v/--verbose]\n" ) + +xx(vgsplit, + "Move physical volumes into a new volume group", + "vgsplit " + "[-A|--autobackup {y|n}] " + "[-d|--debug] " + "[-h|--help] " + "[-l|--list]\n\t" + "[-t|--test] " + "[-v|--verbose] " + "[--version]\n\t" + "ExistingVolumeGroupName NewVolumeGroupName\n\t" + "PhysicalVolumePath [PhysicalVolumePath...]\n", + + autobackup_ARG, list_ARG, test_ARG) diff --git a/tools/errors.h b/tools/errors.h new file mode 100644 index 000000000..a5a5fd8c1 --- /dev/null +++ b/tools/errors.h @@ -0,0 +1,480 @@ +/* + * 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. + * + */ + +#ifndef _LVM_ERROR_H_INCLUDE +#define _LVM_ERROR_H_INCLUDE + +/* Tool return codes */ + +#define LVM_E_CHECK_ERRORS 1 +#define LVM_E_FCLOSE 4 +#define LVM_E_FOPEN 5 +#define LVM_E_FSCK_PATH 6 +#define LVM_E_FSCK_RUN 7 +#define LVM_E_FSSIZE_CHANGE 9 +#define LVM_E_GET_FREE_VG_NUMBER 10 +#define LVM_E_INVALID 11 +#define LVM_E_LV_CHECK_ACTIVE 15 +#define LVM_E_LV_CHECK_EXIST 16 +#define LVM_E_LV_CHECK_EXIST_OLD 18 +#define LVM_E_LV_CHECK_NAME 19 +#define LVM_E_LV_COUNT 21 +#define LVM_E_LV_CREATE 22 +#define LVM_E_LV_CREATE_NODE 23 +#define LVM_E_LV_EXISTS 25 +#define LVM_E_LV_EXTEND 26 +#define LVM_E_LV_EXTEND_PATH 27 +#define LVM_E_LV_EXTEND_RUN 28 +#define LVM_E_LV_GET_INDEX 29 +#define LVM_E_LV_INIT_COW_TABLE 31 +#define LVM_E_LV_LSTAT 32 +#define LVM_E_LV_MISSING 34 +#define LVM_E_LVMTAB 35 +#define LVM_E_LVM_TAB_VG_INSERT 36 +#define LVM_E_LVM_TAB_VG_REMOVE 37 +#define LVM_E_LV_OPEN 41 +#define LVM_E_LV_PATH 42 +#define LVM_E_LV_READ 43 +#define LVM_E_LV_READ_COW_TABLE 44 +#define LVM_E_LV_REDUCE 45 +#define LVM_E_LV_REDUCE_PATH 46 +#define LVM_E_LV_REDUCE_RUN 47 +#define LVM_E_LV_RELEASE 48 +#define LVM_E_LV_REMOVE 49 +#define LVM_E_LV_RENAME 50 +#define LVM_E_LV_SET_ACCESS 51 +#define LVM_E_LV_SET_ALLOCATION 52 +#define LVM_E_LV_SET_STATUS 53 +#define LVM_E_LV_SETUP 54 +#define LVM_E_LV_SETUP_COW_TABLE_FOR_CREATE 55 +#define LVM_E_LV_SIZE 56 +#define LVM_E_LV_SIZE_FREE 57 +#define LVM_E_LV_SIZE_MAX 58 +#define LVM_E_LV_SNAPSHOT 59 +#define LVM_E_LV_WRITE 63 +#define LVM_E_LV_WRITE_ALL_PV 64 +#define LVM_E_MALLOC 65 +#define LVM_E_MAX_LV 66 +#define LVM_E_MAX_VG 67 +#define LVM_E_NO_DEV 69 +#define LVM_E_NO_DISKS_FOUND 70 +#define LVM_E_NO_EMPTY_PV 71 +#define LVM_E_NO_EXT2 72 +#define LVM_E_NO_FILES_FOUND 73 +#define LVM_E_NO_PV_FOUND 75 +#define LVM_E_NOT_EXTENDABLE 76 +#define LVM_E_NO_VALID_PV 77 +#define LVM_E_NO_VG 78 +#define LVM_E_NO_VG_NAME 79 +#define LVM_E_NO_VGS 80 +#define LVM_E_OPEN 81 +#define LVM_E_PE_FREE 83 +#define LVM_E_PE_OVERLAP 86 +#define LVM_E_PV_CHANGE 88 +#define LVM_E_PV_CHECK_CONSISTENCY 89 +#define LVM_E_PV_CHECK_IN_VG 90 +#define LVM_E_PV_CHECK_NEW 93 +#define LVM_E_PV_COUNT 94 +#define LVM_E_PV_FIND_ALL_PV_NAMES 95 +#define LVM_E_PV_GET_SIZE 97 +#define LVM_E_PV_MAX 98 +#define LVM_E_PV_MISSING 99 +#define LVM_E_PV_MULTIPLE 101 +#define LVM_E_PV_NAME 102 +#define LVM_E_PV_NUMBER 103 +#define LVM_E_PV_ONLINE 104 +#define LVM_E_PV_READ 105 +#define LVM_E_PV_READ_ALL_PV 106 +#define LVM_E_PV_READ_PE 107 +#define LVM_E_PV_SETUP 108 +#define LVM_E_PV_TOO_SMALL 110 +#define LVM_E_PV_WRITE 111 +#define LVM_E_PV_WRITE_ALL_PV_OF_VG 112 +#define LVM_E_READ_AHEAD 113 +#define LVM_E_REALLOC 114 +#define LVM_E_RESET 115 +#define LVM_E_RESIZE_PATH 116 +#define LVM_E_RESIZE_RUN 117 +#define LVM_E_SOME_INVALID_PV 118 +#define LVM_E_STRIPE_COUNT 119 +#define LVM_E_VG_CFGBACKUP 123 +#define LVM_E_VG_CFG_BACKUP 124 +#define LVM_E_VG_CFGBACKUP_LVMTAB 125 +#define LVM_E_VG_CFGRESTORE 126 +#define LVM_E_VG_CHECK_ACTIVE 127 +#define LVM_E_VG_CHECK_CONSISTENCY 128 +#define LVM_E_VG_CHECK_DIR 129 +#define LVM_E_VG_CHECK_EXIST 130 +#define LVM_E_VG_CHECK_EXIST_NEW 131 +#define LVM_E_VG_CHECK_EXIST_OLD 132 +#define LVM_E_VG_CHECK_NAME_NEW 134 +#define LVM_E_VG_CHECK_NAME_OLD 135 +#define LVM_E_VG_CREATE 136 +#define LVM_E_VG_CREATE_DIR_AND_GROUP_NODES 137 +#define LVM_E_VG_CREATE_DIR_AND_GROUP_NODES_EXIST 138 +#define LVM_E_VG_CREATE_DIR_AND_GROUP_NODES_NEW 139 +#define LVM_E_VG_DIFF 140 +#define LVM_E_VG_DIR_NEW 141 +#define LVM_E_VG_DIR_OLD 142 +#define LVM_E_VG_EEXIST 143 +#define LVM_E_VG_ERROR 144 +#define LVM_E_VG_EXTEND 145 +#define LVM_E_VG_INSERT 146 +#define LVM_E_VG_MISSING 147 +#define LVM_E_VG_NAME 148 +#define LVM_E_VG_NAMES 150 +#define LVM_E_VG_NAMES_IDENTICAL 151 +#define LVM_E_VG_NOT_FOUND 152 +#define LVM_E_VG_NOT_REDUCABLE 153 +#define LVM_E_VG_PV_NAMES 154 +#define LVM_E_VG_READ 155 +#define LVM_E_VG_REDUCE 159 +#define LVM_E_VG_REMOVE 160 +#define LVM_E_VG_REMOVE_DIR 161 +#define LVM_E_VG_REMOVE_DIR_AND_GROUP_NODES 162 +#define LVM_E_VG_RENAME 163 +#define LVM_E_VG_SETUP 164 +#define LVM_E_VG_SIZE 165 +#define LVM_E_VG_STATUS 166 +#define LVM_E_VG_WRITE 167 +#define LVM_ECMD_PROCESSED 170 +#define LVM_EVG_CHECK_ACTIVE 171 +#define LVM_EVG_READ 172 +#define LVM_ELV_STATUS 173 +#define LVM_EVG_WRITE 175 +#define LVM_ENOMEM 176 +#define LVM_EDRIVER 177 +#define LVM_EINVALID_IOP 178 +#define LVM_ELVMTAB 180 +#define LVM_EINVALID_CMD_LINE 181 +#define LVM_EPARAM 182 +#define LVM_ENO_SUCH_CMD 490 + + +/* Library return codes */ + +#define LVM_ELVM_CHECK_CHARS 183 +#define LVM_ELVM_FIND_VG_REALLOC 184 +#define LVM_ELVM_IOP_VERSION_OPEN 185 +#define LVM_ELVM_LOCK_YET_LOCKED 186 +#define LVM_ELVM_NOT_LOCKED 187 +#define LVM_ELVM_TAB_CREATE_LVMTAB 188 +#define LVM_ELVM_TAB_CREATE_LVMTAB_DIR 189 +#define LVM_ELVM_TAB_GET_FREE_BLK_DEV_LVM_TAB_VG_CHECK_EXIST 190 +#define LVM_ELVM_TAB_GET_FREE_BLK_DEV_NO_DEV 191 +#define LVM_ELVM_TAB_GET_FREE_BLK_DEV_REALLOC 192 +#define LVM_ELVM_TAB_GET_FREE_VG_NUMBER_MALLOC 193 +#define LVM_ELVM_TAB_LV_READ_BY_NAME_LVM_TAB_VG_READ_WITH_PV_AND_LV 194 +#define LVM_ELVM_TAB_LV_READ_BY_NAME_LV_GET_INDEX_BY_NAME 195 +#define LVM_ELVM_TAB_READ_FSTAT 196 +#define LVM_ELVM_TAB_READ_MALLOC 197 +#define LVM_ELVM_TAB_READ_OPEN 198 +#define LVM_ELVM_TAB_READ_PV_CHECK_NAME 199 +#define LVM_ELVM_TAB_READ_READ 200 +#define LVM_ELVM_TAB_READ_SIZE 201 +#define LVM_ELVM_TAB_READ_VG_CHECK_NAME 202 +#define LVM_ELVM_TAB_VG_CHECK_EXIST_ALL_VG_REALLOC 203 +#define LVM_ELVM_TAB_VG_INSERT_REALLOC 204 +#define LVM_ELVM_TAB_VG_INSERT_VG_EXISTS 205 +#define LVM_ELVM_TAB_VG_REMOVE_NOT_EXISTS 206 +#define LVM_ELVM_TAB_VG_REMOVE_UNLINK 207 +#define LVM_ELVM_TAB_WRITE_FCHMOD 208 +#define LVM_ELVM_TAB_WRITE_OPEN 209 +#define LVM_ELVM_TAB_WRITE_WRITE 210 +#define LVM_ELV_ACCESS 211 +#define LVM_ELV_ALLOCATED_LE 212 +#define LVM_ELV_ALLOCATION 213 +#define LVM_ELV_BADBLOCK 214 +#define LVM_ELV_CHECK_NAME_LV_NAME 215 +#define LVM_ELV_CHECK_NAME_LV_NUM 216 +#define LVM_ELV_CHECK_NAME_VG_NAME 217 +#define LVM_ELV_CHECK_STRIPE_SIZE 218 +#define LVM_ELV_CREATE_NODE_CHMOD 219 +#define LVM_ELV_CREATE_NODE_CHOWN 220 +#define LVM_ELV_CREATE_NODE_MKNOD 221 +#define LVM_ELV_CREATE_NODE_UNLINK 222 +#define LVM_ELV_CREATE_REMOVE_OPEN 223 +#define LVM_ELV_CURRENT_LE 224 +#define LVM_ELV_EXTEND_REDUCE_OPEN 225 +#define LVM_ELV_INIT_COW_TABLE_CLOSE 226 +#define LVM_ELV_INIT_COW_TABLE_LLSEEK 227 +#define LVM_ELV_INIT_COW_TABLE_MALLOC 228 +#define LVM_ELV_INIT_COW_TABLE_OPEN 229 +#define LVM_ELV_INIT_COW_TABLE_WRITE 230 +#define LVM_ELV_LE_REMAP_OPEN 231 +#define LVM_ELV_LVNAME 232 +#define LVM_ELV_MIRROR_COPIES 233 +#define LVM_ELV_NUMBER 234 +#define LVM_ELV_OPEN 235 +#define LVM_ELV_READ_ALL_LV_LSEEK 236 +#define LVM_ELV_READ_ALL_LV_MALLOC 237 +#define LVM_ELV_READ_ALL_LV_NL 238 +#define LVM_ELV_READ_ALL_LV_OPEN 239 +#define LVM_ELV_READ_ALL_LV_READ 240 +#define LVM_ELV_READ_ALL_LV_VG_READ 241 +#define LVM_ELV_READ_BYINDEX_LV_READ_ALL_LV 242 +#define LVM_ELV_READ_BYINDEX_VG_NAME 243 +#define LVM_ELV_READ_BYINDEX_VG_READ 244 +#define LVM_ELV_READ_COW_TABLE_CLOSE 245 +#define LVM_ELV_READ_COW_TABLE_LLSEEK 246 +#define LVM_ELV_READ_COW_TABLE_MALLOC 247 +#define LVM_ELV_READ_COW_TABLE_OPEN 248 +#define LVM_ELV_READ_COW_TABLE_READ 249 +#define LVM_ELV_READ_LV 250 +#define LVM_ELV_READ_LV_NAME 251 +#define LVM_ELV_READ_LV_READ_ALL_LV 252 +#define LVM_ELV_READ_VG_NAME 253 +#define LVM_ELV_READ_VG_READ 254 +#define LVM_ELV_RECOVERY 255 +#define LVM_ELV_RELEASE_LV_NUM 257 +#define LVM_ELV_RENAME_OPEN 258 +#define LVM_ELV_SCHEDULE 259 +#define LVM_ELV_SETUP_COW_TABLE_FOR_CREATE_MALLOC 260 +#define LVM_ELV_SETUP_FOR_CREATE_LVM_TAB_GET_FREE_BLK_DEV 261 +#define LVM_ELV_SETUP_FOR_CREATE_LV_MAX 262 +#define LVM_ELV_SETUP_FOR_CREATE_MALLOC 263 +#define LVM_ELV_SETUP_FOR_CREATE_PE 264 +#define LVM_ELV_SETUP_FOR_CREATE_STRIPES 265 +#define LVM_ELV_SETUP_FOR_CREATE_STRIPESIZE 266 +#define LVM_ELV_SETUP_FOR_EXTEND_LV_INDEX 267 +#define LVM_ELV_SETUP_FOR_EXTEND_REALLOC 268 +#define LVM_ELV_SETUP_FOR_EXTEND_STRIPES 269 +#define LVM_ELV_SETUP_FOR_REDUCE_LV_INDEX 270 +#define LVM_ELV_SETUP_FOR_REDUCE_MALLOC 271 +#define LVM_ELV_SHOW_CURRENT_PE_TEXT_LV_INDEX 272 +#define LVM_ELV_SHOW_VG_READ_WITH_PV_AND_LV 273 +#define LVM_ELV_SIZE 274 +#define LVM_ELV_STATUS_ALL_LV_OF_VG_MALLOC 275 +#define LVM_ELV_STATUS_BYINDEX_MALLOC 276 +#define LVM_ELV_STATUS_BYNAME_MALLOC 277 +#define LVM_ELV_STATUS_INTERNAL_OPEN 278 +#define LVM_ELV_STATUS_NL 279 +#define LVM_ELV_STRIPES 280 +#define LVM_ELV_STRIPESIZE 281 +#define LVM_ELV_TIMEOUT 282 +#define LVM_ELV_VGNAME 283 +#define LVM_ELV_WRITE_ALL_LV_LSEEK 284 +#define LVM_ELV_WRITE_ALL_LV_MALLOC 285 +#define LVM_ELV_WRITE_ALL_LV_OPEN 286 +#define LVM_ELV_WRITE_ALL_LV_WRITE 287 +#define LVM_ELV_WRITE_LSEEK 288 +#define LVM_ELV_WRITE_OPEN 289 +#define LVM_ELV_WRITE_WRITE 290 +#define LVM_EPE_LOCK 291 +#define LVM_EPV_CHANGE_ALL_PV_FOR_LV_OF_VG_LV_NUM 292 +#define LVM_EPV_CHANGE_OPEN 293 +#define LVM_EPV_CHECK_CONSISTENCY_ALL_PV_PE 294 +#define LVM_EPV_CHECK_CONSISTENCY_LVM_ID 295 +#define LVM_EPV_CHECK_CONSISTENCY_LV_CUR 296 +#define LVM_EPV_CHECK_CONSISTENCY_MAJOR 297 +#define LVM_EPV_CHECK_CONSISTENCY_PE_ALLOCATED 298 +#define LVM_EPV_CHECK_CONSISTENCY_PE_SIZE 299 +#define LVM_EPV_CHECK_CONSISTENCY_PE_STALE 300 +#define LVM_EPV_CHECK_CONSISTENCY_PE_TOTAL 301 +#define LVM_EPV_CHECK_CONSISTENCY_PV_ALLOCATABLE 302 +#define LVM_EPV_CHECK_CONSISTENCY_PV_NAME 303 +#define LVM_EPV_CHECK_CONSISTENCY_PV_SIZE 304 +#define LVM_EPV_CHECK_CONSISTENCY_PV_STATUS 305 +#define LVM_EPV_CHECK_CONSISTENCY_STRUCT_VERSION 306 +#define LVM_EPV_CHECK_CONSISTENCY_VG_NAME 307 +#define LVM_EPV_CHECK_NAME 308 +#define LVM_EPV_CHECK_NAME_STAT 309 +#define LVM_EPV_CHECK_NUMBER_MALLOC 310 +#define LVM_EPV_CHECK_NUMBER_MAX_NUMBER 311 +#define LVM_EPV_CHECK_NUMBER_PV_NUMBER 312 +#define LVM_EPV_CHECK_PART 313 +#define LVM_EPV_FIND_ALL_PV_PV_READ 314 +#define LVM_EPV_FLUSH_OPEN 315 +#define LVM_EPV_GET_SIZE_IOCTL 316 +#define LVM_EPV_GET_SIZE_LLSEEK 317 +#define LVM_EPV_GET_SIZE_LVM_DIR_CACHE 318 +#define LVM_EPV_GET_SIZE_NO_EXTENDED 319 +#define LVM_EPV_GET_SIZE_NO_PRIMARY 320 +#define LVM_EPV_GET_SIZE_OPEN 321 +#define LVM_EPV_GET_SIZE_PART 322 +#define LVM_EPV_GET_SIZE_READ 323 +#define LVM_EPV_MOVE_LV_LE_REMAP 324 +#define LVM_EPV_MOVE_PES_ALLOC_STRIPES 325 +#define LVM_EPV_MOVE_PES_NO_PES 326 +#define LVM_EPV_MOVE_PES_NO_SPACE 327 +#define LVM_EPV_MOVE_PES_REALLOC 328 +#define LVM_EPV_MOVE_PE_LLSEEK_IN 329 +#define LVM_EPV_MOVE_PE_LLSEEK_OUT 330 +#define LVM_EPV_MOVE_PE_LOCK 331 +#define LVM_EPV_MOVE_PE_LV_GET_NAME 332 +#define LVM_EPV_MOVE_PE_OPEN 333 +#define LVM_EPV_MOVE_PE_OPEN_IN 334 +#define LVM_EPV_MOVE_PE_READ_IN 335 +#define LVM_EPV_MOVE_PE_UNLOCK 336 +#define LVM_EPV_MOVE_PE_WRITE_OUT 337 +#define LVM_EPV_MOVE_PV_CHANGE_DEST 338 +#define LVM_EPV_MOVE_PV_CHANGE_SRC 339 +#define LVM_EPV_MOVE_PV_PV_WRITE_WITH_PE_DEST 340 +#define LVM_EPV_MOVE_PV_PV_WRITE_WITH_PE_SRC 341 +#define LVM_EPV_READ_ALL_PE_OF_VG_MALLOC 342 +#define LVM_EPV_READ_ALL_PE_OF_VG_PV_NUMBER 343 +#define LVM_EPV_READ_ALL_PV_LVM_DIR_CACHE 344 +#define LVM_EPV_READ_ALL_PV_MALLOC 345 +#define LVM_EPV_READ_ALL_PV_OF_VG_MALLOC 346 +#define LVM_EPV_READ_ALL_PV_OF_VG_NP 347 +#define LVM_EPV_READ_ALL_PV_OF_VG_NP_SORT 348 +#define LVM_EPV_READ_ALL_PV_OF_VG_PV_NUMBER 349 +#define LVM_EPV_READ_ID_INVALID 350 +#define LVM_EPV_READ_LVM_STRUCT_VERSION 351 +#define LVM_EPV_READ_MAJOR 352 +#define LVM_EPV_READ_MD_DEVICE 353 +#define LVM_EPV_READ_OPEN 354 +#define LVM_EPV_READ_PE_LSEEK 355 +#define LVM_EPV_READ_PE_MALLOC 356 +#define LVM_EPV_READ_PE_OPEN 357 +#define LVM_EPV_READ_PE_READ 358 +#define LVM_EPV_READ_PE_SIZE 359 +#define LVM_EPV_READ_PV_CREATE_NAME_FROM_KDEV_T 360 +#define LVM_EPV_READ_PV_EXPORTED 361 +#define LVM_EPV_READ_PV_FLUSH 362 +#define LVM_EPV_READ_RDEV 363 +#define LVM_EPV_READ_READ 364 +#define LVM_EPV_READ_STAT 365 +#define LVM_EPV_READ_UUIDLIST_LSEEK 366 +#define LVM_EPV_READ_UUIDLIST_OPEN 367 +#define LVM_EPV_READ_UUIDLIST_READ 368 +#define LVM_EPV_READ_UUIDLIST_MALLOC 369 +#define LVM_EPV_RELEASE_PE_NO_PV 370 +#define LVM_EPV_RELEASE_PE_REALLOC 371 +#define LVM_EPV_SHOW_PE_TEXT_MALLOC 372 +#define LVM_EPV_SHOW_PE_TEXT_REALLOC 373 +#define LVM_EPV_SHOW_PE_TEXT_VG_READ_WITH_PV_AND_LV 374 +#define LVM_EPV_STATUS_ALL_PV_LVM_DIR_CACHE 375 +#define LVM_EPV_STATUS_ALL_PV_OF_VG_MALLOC 376 +#define LVM_EPV_STATUS_ALL_PV_OF_VG_NP 377 +#define LVM_EPV_STATUS_OPEN 378 +#define LVM_EPV_TIME_CHECK 379 +#define LVM_EPV_WRITE_LSEEK 380 +#define LVM_EPV_WRITE_OPEN 381 +#define LVM_EPV_WRITE_PE_LSEEK 382 +#define LVM_EPV_WRITE_PE_OPEN 383 +#define LVM_EPV_WRITE_PE_SIZE 384 +#define LVM_EPV_WRITE_PE_WRITE 385 +#define LVM_EPV_WRITE_UUIDLIST_LSEEK 386 +#define LVM_EPV_WRITE_UUIDLIST_MALLOC 387 +#define LVM_EPV_WRITE_UUIDLIST_OPEN 388 +#define LVM_EPV_WRITE_UUIDLIST_WRITE 389 +#define LVM_EPV_WRITE_WRITE 390 +#define LVM_EREMOVE_RECURSIVE_MALLOC 391 +#define LVM_EREMOVE_RECURSIVE_OPENDIR 392 +#define LVM_ESIZE 393 +#define LVM_ESYSTEM_ID_SET_UNAME 394 +#define LVM_EVG_CFGBACKUP_FILE_EXISTS 395 +#define LVM_EVG_CFGBACKUP_MALLOC 396 +#define LVM_EVG_CFGBACKUP_OPEN 397 +#define LVM_EVG_CFGBACKUP_READ 398 +#define LVM_EVG_CFGBACKUP_RENAME 399 +#define LVM_EVG_CFGBACKUP_TMP_FILE 400 +#define LVM_EVG_CFGBACKUP_UNLINK 401 +#define LVM_EVG_CFGBACKUP_VG_CHECK_EXIST 402 +#define LVM_EVG_CFGBACKUP_VG_READ_WITH_PV_AND_LV 403 +#define LVM_EVG_CFGBACKUP_WRITE 404 +#define LVM_EVG_CFGRESTORE_FILE_EXISTS 405 +#define LVM_EVG_CFGRESTORE_LV_CHECK_CONSISTENCY 406 +#define LVM_EVG_CFGRESTORE_MALLOC 407 +#define LVM_EVG_CFGRESTORE_OPEN 408 +#define LVM_EVG_CFGRESTORE_PV_CHECK_CONSISTENCY 409 +#define LVM_EVG_CFGRESTORE_READ 410 +#define LVM_EVG_CFGRESTORE_VG_CHECK_CONSISTENCY 411 +#define LVM_EVG_CFGRESTORE_VG_CHECK_CONSISTENCY_WITH_PV_AND_LV 412 +#define LVM_EVG_CHECK_ACTIVE_ALL_VG_COUNT 413 +#define LVM_EVG_CHECK_ACTIVE_ALL_VG_MALLOC 414 +#define LVM_EVG_CHECK_ACTIVE_ALL_VG_NAMELIST 415 +#define LVM_EVG_CHECK_CONSISTENCY 416 +#define LVM_EVG_CHECK_CONSISTENCY_LV_CUR 417 +#define LVM_EVG_CHECK_CONSISTENCY_PE_ALLOCATED 419 +#define LVM_EVG_CHECK_CONSISTENCY_PE_SIZE 420 +#define LVM_EVG_CHECK_CONSISTENCY_PE_TOTAL 421 +#define LVM_EVG_CHECK_CONSISTENCY_PVG_TOTAL 422 +#define LVM_EVG_CHECK_CONSISTENCY_PV_ACT 423 +#define LVM_EVG_CHECK_CONSISTENCY_PV_CUR 424 +#define LVM_EVG_CHECK_CONSISTENCY_VGDA 425 +#define LVM_EVG_CHECK_CONSISTENCY_VG_ACCESS 426 +#define LVM_EVG_CHECK_CONSISTENCY_VG_NAME 427 +#define LVM_EVG_CHECK_CONSISTENCY_VG_STATUS 428 +#define LVM_EVG_CHECK_EXIST_PV_COUNT 429 +#define LVM_EVG_CHECK_NAME 430 +#define LVM_EVG_CHECK_ONLINE_ALL_PV 431 +#define LVM_EVG_CHECK_ONLINE_ALL_PV_MALLOC 432 +#define LVM_EVG_CHECK_PE_SIZE 433 +#define LVM_EVG_CREATE_DIR_AND_GROUP_CHMOD_DIR 434 +#define LVM_EVG_CREATE_DIR_AND_GROUP_CHMOD_GROUP 435 +#define LVM_EVG_CREATE_DIR_AND_GROUP_CHOWN_GROUP 436 +#define LVM_EVG_CREATE_DIR_AND_GROUP_MKDIR 437 +#define LVM_EVG_CREATE_DIR_AND_GROUP_MKNOD 438 +#define LVM_EVG_CREATE_REMOVE_OPEN 439 +#define LVM_EVG_EXTEND_REDUCE_OPEN 440 +#define LVM_EVG_READ_LSEEK 441 +#define LVM_EVG_READ_LVM_STRUCT_VERSION 442 +#define LVM_EVG_READ_OPEN 443 +#define LVM_EVG_READ_PV 444 +#define LVM_EVG_READ_READ 445 +#define LVM_EVG_READ_VG_EXPORTED 446 +#define LVM_EVG_READ_WITH_PV_AND_LV_LV_ALLOCATED_LE 447 +#define LVM_EVG_READ_WITH_PV_AND_LV_MALLOC 448 +#define LVM_EVG_READ_WITH_PV_AND_LV_PV_CUR 449 +#define LVM_EVG_RENAME_OPEN 450 +#define LVM_EVG_SETUP_FOR_CREATE_MALLOC 451 +#define LVM_EVG_SETUP_FOR_CREATE_PV_SIZE_MIN 452 +#define LVM_EVG_SETUP_FOR_CREATE_VG_NUMBER 453 +#define LVM_EVG_SETUP_FOR_EXTEND_MALLOC 454 +#define LVM_EVG_SETUP_FOR_EXTEND_MAX_PV 455 +#define LVM_EVG_SETUP_FOR_EXTEND_NO_PV 456 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_ALREADY 457 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_CHECK_NAME 458 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_CHECK_NEW 459 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_GET_SIZE 460 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_SIZE 461 +#define LVM_EVG_SETUP_FOR_EXTEND_PV_SIZE_REL 462 +#define LVM_EVG_SETUP_FOR_MERGE_BLK_DEV 463 +#define LVM_EVG_SETUP_FOR_MERGE_LV_MAX 464 +#define LVM_EVG_SETUP_FOR_MERGE_PE_SIZE 465 +#define LVM_EVG_SETUP_FOR_MERGE_PV_MAX 466 +#define LVM_EVG_SETUP_FOR_MERGE_VG_CHECK_CONSISTENCY_WITH_PV_AND_LV 467 +#define LVM_EVG_SETUP_FOR_REDUCE_LAST_PV 468 +#define LVM_EVG_SETUP_FOR_REDUCE_LAST_PV_NOT_IN_VG 469 +#define LVM_EVG_SETUP_FOR_REDUCE_LV 470 +#define LVM_EVG_SETUP_FOR_REDUCE_NO_PV_TO_REDUCE 471 +#define LVM_EVG_SETUP_FOR_REDUCE_PV_INVALID 472 +#define LVM_EVG_SETUP_FOR_REDUCE_REALLOC 473 +#define LVM_EVG_SETUP_FOR_SPLIT_LV_ON_PV 474 +#define LVM_EVG_SETUP_FOR_SPLIT_MALLOC 475 +#define LVM_EVG_SETUP_FOR_SPLIT_PV 476 +#define LVM_EVG_SETUP_FOR_SPLIT_PV_COUNT 477 +#define LVM_EVG_SETUP_FOR_SPLIT_VG_NUMBER 478 +#define LVM_EVG_SET_CLEAR_EXTENDABLE_OPEN 479 +#define LVM_EVG_STATUS_GET_COUNT_OPEN 480 +#define LVM_EVG_STATUS_GET_NAMELIST_OPEN 481 +#define LVM_EVG_STATUS_MALLOC 482 +#define LVM_EVG_STATUS_OPEN 483 +#define LVM_EVG_WRITE_LSEEK 484 +#define LVM_EVG_WRITE_OPEN 485 +#define LVM_EVG_WRITE_WRITE 486 +#define LVM_ELV_PV_CREATE_NAME_FROM_KDEV_T 487 +#define LVM_EPV_FLUSH_STAT 488 +#define LVM_EVG_SETUP_FOR_CREATE_PV_SIZE_MAX 489 + +#endif /* #ifndef _LVM_ERROR_H_INCLUDE */ + diff --git a/tools/lvactivate.c b/tools/lvactivate.c new file mode 100644 index 000000000..13189bf6d --- /dev/null +++ b/tools/lvactivate.c @@ -0,0 +1,95 @@ +/* + * 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" + +int lvactivate(int argc, char **argv) +{ + int p; + + struct dev_mgr *dm; + struct device *pv_dev; + + char *lv; + char *pv_name; + + pv_t *pv = NULL; + lv_disk_t *lvs = NULL; + + if (argc < 2) { + log_error("please enter logical volume & physical volume(s)"); + return LVM_EINVALID_CMD_LINE; + } + + lv = argv[0]; + argc--; + argv++; + + dm = active_dev_mgr(); + + while (argc--) { + pv_name = argv[argc]; + if (!(pv_dev = dev_by_name(dm, pv_name))) { + log_error("device \"%s\" not found", pv_name); + return -1; + } + + if (!(pv = pv_read(dm, pv_name))) { + return -1; + } + + if (pv->pe_allocated) { + 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); + goto pvdisplay_device_out; + } + } else + log_print("no logical volume on physical volume %s", + pv_name); + + 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; + + 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)); + } + + dbg_free(pv); + dbg_free(lvs); + } + + return 0; + + pvdisplay_device_out: + dbg_free(pv); + dbg_free(lvs); + + return -1; +} diff --git a/tools/lvm.c b/tools/lvm.c new file mode 100644 index 000000000..a691879f4 --- /dev/null +++ b/tools/lvm.c @@ -0,0 +1,829 @@ +/* + * 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 GNU CC; 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" + +#include +#include +#include +#include +#include +#include + +#include "stub.h" + +#ifdef READLINE_SUPPORT +#include +#include +#endif + +/* define the table of valid switches */ +struct arg the_args[ARG_COUNT + 1] = { + +#define xx(a, b, c, d) {b, "--" c, d, 0, NULL}, +#include "args.h" +#undef xx + +}; + + +/* a register of the lvm commands */ +struct command { + const char *name; + const char *desc; + const char *usage; + command_fn fn; + + int num_args; + int *valid_args; +}; + +static int _array_size; +static int _num_commands; +static struct command *_commands; + +static struct dev_mgr *_dm; +static struct config_file *_cf; + +static int _interactive; +static FILE *_log; +static int _debug_level; + +/* static functions */ +static void register_commands(void); +static struct command *find_command(const char *name); +static void register_command(const char *name, command_fn fn, + const char *desc, const char *usage, ...); +static void create_new_command(const char *name, command_fn command, + const char *desc, const char *usage, + int nargs, int *args); + +static void alloc_command(void); +static void add_getopt_arg(int arg, char **ptr, struct option **o); +static int process_command_line(struct command *com, int *argc, char ***argv); +static struct arg *find_arg(struct command *com, int a); +static int process_common_commands(struct command *com); +static int run_command(int argc, char **argv); +static int init(void); +static void fin(void); +static int run_script(int argc, char **argv); + +#ifdef READLINE_SUPPORT +static int shell(void); +static char **lvm_completion(char *text, int start_pos, int end_pos); +static char *list_cmds(char *text, int state); +static char *list_args(char *text, int state); +#endif + +static void display_help(void); + +int main(int argc, char **argv) +{ + char *namebase, *base; + int ret, alias = 0; + + if (!init()) + return -1; + + namebase = strdup(argv[0]); + base = basename(namebase); + if (strcmp(base, "lvm")) + alias = 1; + free(namebase); + + register_commands(); + +#ifdef READLINE_SUPPORT + if (!alias && argc == 1) { + ret = shell(); + goto out; + } +#endif + + if (!alias) { + if (argc < 2) { + log_fatal("Please supply an LVM command."); + display_help(); + ret = LVM_EINVALID_CMD_LINE; + goto out; + } + + argc--; + argv++; + } + + ret = run_command(argc, argv); + if ((ret == LVM_ENO_SUCH_CMD) && (!alias)) + ret = run_script(argc, argv); + if (ret == LVM_ENO_SUCH_CMD) + log_error("No such command"); + + out: + fin(); + return ret; +} + +void usage(const char *name) +{ + struct command *com = find_command(name); + + if (!com) + return; + + log_error("%s: %s\n\n%s", com->name, com->desc, com->usage); +} + +int yes_no_arg(struct arg *a) +{ + if (!strcmp(a->value, "y")) + a->i_value = 1; + + else if (!strcmp(a->value, "n")) + a->i_value = 0; + + else + return 0; + + return 1; +} + +int size_arg(struct arg *a) +{ + static char *suffixes = "kmgt"; + + char *ptr; + int i; + long v = strtol(a->value, &ptr, 10); + + if (ptr == a->value) + return 0; + + if (*ptr) { + for (i = strlen(suffixes) - 1; i >= 0; i--) + if (suffixes[i] == tolower((int) *ptr)) + break; + + if (i < 0) + return 0; + + while (i-- > 0) + v *= 1024; + } + + a->i_value = (int) v; + return 1; + +} + +int int_arg(struct arg *a) +{ + char *ptr; + long v = strtol(a->value, &ptr, 10); + + if (ptr == a->value || *ptr) + return 0; + + a->i_value = (int) v; + return 1; +} + +int string_arg(struct arg *a) +{ + return 1; +} + +int permission_arg(struct arg *a) +{ + if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr"))) + a->i_value = LV_READ | LV_WRITE; + + else if (!strcmp(a->value, "r")) + a->i_value = LV_READ; + + else + return 0; + + return 1; +} + +char yes_no_prompt(char *prompt, ...) +{ + int c = 0; + va_list ap; + + while (c != 'y' && c != 'n') { + if (c == '\n' || c == 0) { + va_start(ap, prompt); + vprintf(prompt, ap); + va_end(ap); + } + c = tolower(getchar()); + } + while (getchar() != '\n'); + return c; +} + +static void register_commands() +{ +#define xx(a, b, c...) register_command(# a, a, b, ## c, \ + debug_ARG, help_ARG, suspend_ARG, \ + version_ARG, verbose_ARG, -1); +#include "commands.h" +#undef xx +} + +static void register_command(const char *name, command_fn fn, + const char *desc, const char *usage, ...) +{ + int nargs = 0, i; + int *args; + va_list ap; + + /* count how many arguments we have */ + va_start(ap, usage); + while (va_arg(ap, int) >= 0) + nargs++; + va_end(ap); + + /* allocate space for them */ + if (!(args = dbg_malloc(sizeof(*args) * nargs))) { + log_fatal("Out of memory."); + exit(LVM_ENOMEM); + } + + /* fill them in */ + va_start(ap, usage); + for (i = 0; i < nargs; i++) + args[i] = va_arg(ap, int); + va_end(ap); + + /* enter the command in the register */ + create_new_command(name, fn, desc, usage, nargs, args); +} + +static struct command *find_command(const char *name) +{ + int i; + char *namebase, *base; + + namebase = strdup(name); + base = basename(namebase); + + for (i = 0; i < _num_commands; i++) { + if (!strcmp(base, _commands[i].name)) + break; + } + + free(namebase); + + if (i >= _num_commands) + return 0; + + return _commands + i; +} + +static void create_new_command(const char *name, command_fn command, + const char *desc, const char *usage, + int nargs, int *args) +{ + struct command *nc; + + alloc_command(); + + nc = _commands + _num_commands++; + + nc->name = name; + nc->desc = desc; + nc->usage = usage; + nc->fn = command; + nc->num_args = nargs; + nc->valid_args = args; +} + +static void __alloc(int size) +{ + if (!(_commands = dbg_realloc(_commands, sizeof(*_commands) * size))) { + log_fatal("Couldn't allocate memory."); + exit(LVM_ENOMEM); + } + + _array_size = size; +} + +static void alloc_command(void) +{ + if (!_array_size) + __alloc(32); + + if (_array_size <= _num_commands) + __alloc(2 * _array_size); +} + +static void add_getopt_arg(int arg, char **ptr, struct option **o) +{ + struct arg *a = the_args + arg; + + if (a->short_arg) { + *(*ptr)++ = a->short_arg; + + if (a->fn) + *(*ptr)++ = ':'; + } + + if (*(a->long_arg + 2)) { + (*o)->name = a->long_arg + 2; + (*o)->has_arg = a->fn ? 1 : 0; + (*o)->flag = NULL; + (*o)->val = a->short_arg ? a->short_arg : (int) a; + (*o)++; + } +} + +static int process_command_line(struct command *com, int *argc, char ***argv) +{ + int i, opt; + char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str; + struct option opts[ARG_COUNT + 1], *o = opts; + struct arg *a; + + for (i = 0; i < ARG_COUNT; i++) { + struct arg *a = the_args + i; + + /* zero the count and arg */ + a->count = 0; + a->value = 0; + a->i_value = 0; + } + + /* fill in the short and long opts */ + for (i = 0; i < com->num_args; i++) + add_getopt_arg(com->valid_args[i], &ptr, &o); + + *ptr = '\0'; + memset(o, 0, sizeof(*o)); + + /* initialise getopt_long & scan for command line switches */ + optarg = 0; + optind = 0; + while ((opt = getopt_long(*argc, *argv, str, opts, NULL)) >= 0) { + + a = find_arg(com, opt); + + if (!a) { + log_fatal("Unrecognised option."); + return 0; + } + + if (a->fn) { + if (!optarg) { + log_error("Option requires argument."); + return 0; + } + + a->value = optarg; + + if (!a->fn(a)) { + log_error("Invalid argument %s", optarg); + return 0; + } + } + + a->count++; + } + + *argc -= optind; + *argv += optind; + return 1; +} + +static struct arg *find_arg(struct command *com, int opt) +{ + struct arg *a; + int i; + + for (i = 0; i < com->num_args; i++) { + a = the_args + com->valid_args[i]; + + if ((opt == a->short_arg) || (opt == (int) a)) + return a; + } + + return 0; +} + +static int process_common_commands(struct command *com) +{ + int l; + + if (arg_count(suspend_ARG)) + kill(getpid(), SIGSTOP); + + l = arg_count(debug_ARG); + init_debug(l ? l : _debug_level); + + init_verbose(arg_count(verbose_ARG)); + + init_test(arg_count(test_ARG)); + + if (arg_count(help_ARG)) { + usage(com->name); + return LVM_ECMD_PROCESSED; + } + + if (arg_count(version_ARG)) { + /* FIXME: Add driver version */ + log_error("%s: %s", com->name, lvm_version); + return LVM_ECMD_PROCESSED; + } + + /* Set autobackup if command takes this option */ + for (l = 0; l < com->num_args; l++) + if (com->valid_args[l] == autobackup_ARG) { + if (init_autobackup()) + return LVM_EINVALID_CMD_LINE; + else + break; + } + + return 0; +} + +int help(int argc, char **argv) +{ + if (!argc) + display_help(); + else { + int i; + for (i = 0; i < argc; i++) + usage(argv[i]); + } + + return 0; +} + +static void display_help() +{ + int i; + + log_error("Available lvm commands:"); + log_error("Use 'lvm help ' for more information"); + log_error(""); + + for (i = 0; i < _num_commands; i++) { + struct command *com = _commands + i; + + log_error("%-16.16s%s", com->name, com->desc); + } +} + +static int run_command(int argc, char **argv) +{ + int ret = 0; + struct command *com; + + if (!(com = find_command(argv[0]))) + return LVM_ENO_SUCH_CMD; + + if (!process_command_line(com, &argc, &argv)) { + log_error("Error during parsing of command line."); + return LVM_EINVALID_CMD_LINE; + } + + if ((ret = process_common_commands(com))) + return ret; + + ret = com->fn(argc, argv); + + if (ret == LVM_EINVALID_CMD_LINE && !_interactive) + usage(com->name); + + return ret; +} + +static int split(char *str, int *argc, char **argv, int max) +{ + char *b = str, *e; + *argc = 0; + + while (*b) { + while (*b && isspace(*b)) + b++; + + if ((!*b) || (*b == '#')) + break; + + e = b; + while (*e && !isspace(*e)) + e++; + + argv[(*argc)++] = b; + if (!*e) + break; + *e++ = '\0'; + b = e; + if (*argc == max) + break; + } + + return *argc; +} + +struct dev_mgr *active_dev_mgr(void) { + return _dm; +} + +struct config_file *active_config_file(void) { + return _cf; +} + +static void __init_log(struct config_file *cf) +{ + const char *log_file = find_config_str(cf->root, "log/file", '/', 0); + + if (log_file) { + /* set up the logging */ + if (!(_log = fopen(log_file, "w"))) + log_error("couldn't open log file %s\n", log_file); + else + init_log(_log); + } + + _debug_level = find_config_int(cf->root, "log/level", '/', 0); + init_debug(_debug_level); +} + +static int init(void) +{ + int ret = 0; + const char *e = getenv("LVM_CONFIG_FILE"); + struct stat info; + + if (!(_cf=create_config_file())) { + stack; + goto out; + } + + /* Use LOG_USER for syslog messages by default */ + init_syslog(LOG_USER); + + /* send log messages to stderr for now */ + init_log(stderr); + + e = e ? e : "/etc/lvm/lvm.conf"; + if (stat(e, &info) != -1) { + /* we've found a config file */ + if (!read_config(_cf, e)) { + stack; + goto out; + } + + __init_log(_cf); + } + + if (!(_dm = init_dev_manager(_cf->root))) { + stack; + goto out; + } + + ret = 1; + + out: + return ret; +} + +static void __fin_commands(void) +{ + int i; + + for (i = 0; i < _num_commands; i++) + dbg_free(_commands[i].valid_args); + + dbg_free(_commands); +} + +static void fin(void) +{ + fin_dev_manager(_dm); + destroy_config_file(_cf); + __fin_commands(); + dump_memory(); + fin_log(); + + if (_log) + fclose(_log); +} + + +static int run_script(int argc, char **argv) +{ + FILE *script; + + char buffer[CMD_LEN]; + int ret = 0; + int magic_number = 0; + + if ((script = fopen(argv[0], "r")) == NULL) + return LVM_ENO_SUCH_CMD; + + 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')) { + buffer[50] = '\0'; + log_error("Line too long (max 255) beginning: %s", + buffer); + ret = LVM_EINVALID_CMD_LINE; + break; + } + if (split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) { + buffer[50] = '\0'; + log_error("Too many arguments: %s", buffer); + ret = LVM_EINVALID_CMD_LINE; + break; + } + if (!argc) + continue; + if (!strcmp(argv[0], "quit")) + break; + run_command(argc, argv); + } + + fclose(script); + return ret; +} + +#ifdef READLINE_SUPPORT +/* Custom completion function */ +static char **lvm_completion(char *text, int start_pos, int end_pos) +{ + char **match_list = NULL; + int p = 0; + + while (isspace((int) *(rl_line_buffer + p))) + p++; + + /* First word should be one of our commands */ + if (start_pos == p) + match_list = completion_matches(text, list_cmds); + else if (*text == '-') + match_list = completion_matches(text, list_args); + /* else other args */ + + /* No further completion */ + rl_attempted_completion_over = 1; + return match_list; +} + +/* List matching commands */ +static char *list_cmds(char *text, int state) +{ + static int i = 0; + static int len = 0; + + /* Initialise if this is a new completion attempt */ + if (!state) { + i = 0; + len = strlen(text); + } + + while (i < _num_commands) + if (!strncmp(text, _commands[i++].name, len)) + return strdup(_commands[i - 1].name); + + return NULL; +} + +/* List matching arguments */ +static char *list_args(char *text, int state) +{ + static int match_no = 0; + static int len = 0; + static struct command *com; + + /* Initialise if this is a new completion attempt */ + if (!state) { + char *s = rl_line_buffer; + int j = 0; + + match_no = 0; + com = NULL; + len = strlen(text); + + /* Find start of first word in line buffer */ + while (isspace(*s)) + s++; + + /* Look for word in list of commands */ + for (j = 0; j < _num_commands; j++) { + char *p; + char *q = s; + + p = (char *) _commands[j].name; + while (*p == *q) { + p++; + q++; + } + if ((!*p) && *q == ' ') { + com = _commands + j; + break; + } + } + + if (!com) + return NULL; + } + + /* Short form arguments */ + if (len < 3) { + while (match_no < com->num_args) { + char s[3]; + char c; + if (!(c = (the_args + + com->valid_args[match_no++])->short_arg)) + continue; + + sprintf(s, "-%c", c); + if (!strncmp(text, s, len)) + return strdup(s); + } + } + + /* Long form arguments */ + if (match_no < com->num_args) + match_no = com->num_args; + + while (match_no - com->num_args < com->num_args) { + char *l; + l = (the_args + + com->valid_args[match_no++ - com->num_args])->long_arg; + if (!strncmp(text, l, len)) + return strdup(l); + } + + return NULL; +} + +static int shell(void) +{ + int argc; + char *input, *argv[MAX_ARGS]; + + rl_readline_name = "lvm"; + rl_attempted_completion_function = (CPPFunction *) lvm_completion; + + _interactive = 1; + while (1) { + input = readline("lvm> "); + + /* EOF */ + if (!input) { + printf("\n"); + break; + } + + /* empty line */ + if (!*input) + continue; + + add_history(input); + + if (split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) { + log_error("Too many arguments, sorry."); + continue; + } + + if (!argc) + continue; + + if (!strcmp(argv[0], "quit")) + break; + + run_command(argc, argv); + free(input); + } + + free(input); + return 0; +} +#endif diff --git a/tools/pvdisplay.c b/tools/pvdisplay.c new file mode 100644 index 000000000..32943f736 --- /dev/null +++ b/tools/pvdisplay.c @@ -0,0 +1,141 @@ +/* + * 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 pvdisplay_device(const char *pv_dev); + +int pvdisplay(int argc, char **argv) +{ + int opt; + + if (argc == 0) { + log_error("please enter a physical volume path"); + return LVM_EINVALID_CMD_LINE; + } + + if (arg_count(colon_ARG) && arg_count(verbose_ARG)) { + log_error("option v not allowed with option c"); + return LVM_EINVALID_CMD_LINE; + } + + for (opt = 0; opt < argc; opt++) + pvdisplay_device(argv[opt]); + + putchar('\n'); + return 0; +} + +void pvdisplay_device(const char *pv_name) +{ + struct dev_mgr *dm; + struct device *pv_dev; + + pv_t *pv = NULL; + lv_disk_t *lvs = NULL; + + dm = active_dev_mgr(); + + if (!(pv_dev = dev_by_name(dm, pv_name))) { + log_error("device \"%s\" not found", pv_name); + return; + } + + if (arg_count(short_ARG)) { + int size; + char *sz; + + /* Returns size in 512-byte units */ + if ((size = device_get_size(pv_name)) < 0) { + log_error("%s: getting size of physical volume \"%s\"", + strerror(size), pv_name); + return; + } + + sz = display_size(size / 2, SIZE_SHORT); + log_print("Device \"%s\" has a capacity of %s", + pv_name, sz); + + dbg_free(sz); + } + + if (!(pv = pv_read(dm, pv_name))) { + return; + } + +/* FIXME: Check attributes + MD_DEVICE, + log_error("\"%s\" no VALID physical volume \"%s\"", lvm_error ( ret), pv_name); + + EXPORTED + pv->vg_name[strlen(pv->vg_name)-strlen(EXPORTED)] = 0; + log_print("physical volume \"%s\" of volume group \"%s\" is exported" , pv_name, pv->vg_name); + + Valid ID + log_error("no physical volume identifier on \"%s\"" , pv_name); + + NEW + pv_check_new (pv) + log_print ( "\"%s\" is a new physical volume of %s", + pv_name, ( dummy = lvm_show_size ( size / 2, SHORT))); +*/ + +/* FIXME: Check active - no point? + log_very_verbose("checking physical volume activity" ); + pv_check_active ( pv->vg_name, pv->pv_name) + pv_status ( pv->vg_name, pv->pv_name, &pv) +*/ + +/* FIXME: Check consistency - or do this when reading metadata? + log_very_verbose("checking physical volume consistency" ); + ret = pv_check_consistency (pv) + log_error("\"%s\" checking consistency of physical volume \"%s\"", lvm_error ( ret), pv_name); +*/ + + if (arg_count(colon_ARG)) { + pv_display_colons(pv); + goto pvdisplay_device_out; + } + + pv_display_full(pv); + + 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 (!(lvs = pv_read_lvs(pv))) { + log_error("Failed to read LVs on %s", pv->pv_name); + goto pvdisplay_device_out; + } + pv_display_pe_text(pv, pv->pe, lvs); + } else + log_print ("no logical volume on physical volume %s", pv_name); + + pvdisplay_device_out: + dbg_free(pv); + dbg_free(lvs); + + return; +} + + + diff --git a/tools/stub.h b/tools/stub.h new file mode 100644 index 000000000..8ee86c3d2 --- /dev/null +++ b/tools/stub.h @@ -0,0 +1,55 @@ +/* + * 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. + * + */ + +int e2fsadm(int argc, char **argv) {return 1;} +int lvchange(int argc, char **argv) {return 1;} +int lvcreate(int argc, char **argv) {return 1;} +int lvdisplay(int argc, char **argv) {return 1;} +int lvextend(int argc, char **argv) {return 1;} +int lvmchange(int argc, char **argv) {return 1;} +int lvmdiskscan(int argc, char **argv) {return 1;} +int lvmsadc(int argc, char **argv) {return 1;} +int lvmsar(int argc, char **argv) {return 1;} +int lvreduce(int argc, char **argv) {return 1;} +int lvremove(int argc, char **argv) {return 1;} +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 pvcreate(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;} +int vgck(int argc, char **argv) {return 1;} +int vgcreate(int argc, char **argv) {return 1;} +int vgdisplay(int argc, char **argv) {return 1;} +int vgexport(int argc, char **argv) {return 1;} +int vgextend(int argc, char **argv) {return 1;} +int vgimport(int argc, char **argv) {return 1;} +int vgmerge(int argc, char **argv) {return 1;} +int vgmknodes(int argc, char **argv) {return 1;} +int vgreduce(int argc, char **argv) {return 1;} +int vgrename(int argc, char **argv) {return 1;} +int vgremove(int argc, char **argv) {return 1;} +int vgscan(int argc, char **argv) {return 1;} +int vgsplit(int argc, char **argv) {return 1;} +int init_autobackup() {return 0;} + diff --git a/tools/toollib.c b/tools/toollib.c new file mode 100644 index 000000000..059b24b57 --- /dev/null +++ b/tools/toollib.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#include "lvm_user.h" + +static int _autobackup = 1; + +int autobackup_set() +{ + return _autobackup; +} + +int init_autobackup() +{ + char *lvm_autobackup; + + 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; + } + } + } + + return 0; +} + +int do_autobackup(char *vg_name, vg_t * vg) +{ + 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; + } + + 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; + } + + return 0; +} diff --git a/tools/toollib.h b/tools/toollib.h new file mode 100644 index 000000000..219498faa --- /dev/null +++ b/tools/toollib.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This LVM library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This LVM library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this LVM library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + * + */ + +#ifndef LVM_TOOLLIB_H +#define LVM_TOOLLIB_H + +int autobackup_set (void); +int init_autobackup (void); +int do_autobackup(char *vg_name, vg_t * vg); + +#endif diff --git a/tools/tools.h b/tools/tools.h new file mode 100644 index 000000000..b05b0071e --- /dev/null +++ b/tools/tools.h @@ -0,0 +1,108 @@ +/* + * 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 GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef TOOLS_H +#define TOOLS_H + +#include +#include +#include +#include +#include +#include + +#include "metadata/metadata.h" +#include "config/config.h" +#include "dev-mgr/dev-manager.h" +#include "device/device.h" +#include "display/display.h" +#include "display/metadata.h" +#include "errors.h" +#include "log/log.h" +#include "mm/dbg_malloc.h" +#include "toollib.h" + +#define CMD_LEN 256 +#define MAX_ARGS 64 + +/* command functions */ +typedef int (*command_fn)(int argc, char **argv); + +#define xx(a, b...) int a(int argc, char **argv); +#include "commands.h" +#undef xx + +/* define the enums for the command line switches */ +enum { +#define xx(a, b, c, d) a , +#include "args.h" +#undef xx +}; + +/* a global table of possible arguments */ +struct arg { + char short_arg; + char *long_arg; + int (*fn)(struct arg *a); + int count; + char *value; + int i_value; +}; + +extern struct arg the_args[ARG_COUNT + 1]; + +void usage(const char *name); + +/* the argument verify/normalise functions */ +int yes_no_arg(struct arg *a); +int size_arg(struct arg *a); +int int_arg(struct arg *a); +int string_arg(struct arg *a); +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; +} + +static inline char *arg_value(int a) { + return the_args[a].value; +} + +static inline char *arg_str_value(int a, char *def) +{ + return arg_count(a) ? the_args[a].value : def; +} + +static inline int arg_int_value(int a, int def) +{ + return arg_count(a) ? the_args[a].i_value : def; +} + +static inline int arg_count_increment(int a) +{ + return the_args[a].count++; +} + +#endif