diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 089a5aaa8..897ae0003 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -13,8 +13,6 @@ #include #include "dev-cache.h" #include "list.h" -#include "lvm-types.h" - #define ID_LEN 32 #define NAME_LEN 128 @@ -22,26 +20,25 @@ /* Various flags */ /* Note that the bits no longer necessarily correspond to LVM1 disk format */ -#define STATUS_ACTIVE 0x01 /* PV VG LV */ +/* Status bits */ +#define ST_ACTIVE 0x01 /* PV VG LV */ +#define ST_EXPORTED_VG 0x02 /* VG */ /* And PV too perhaps? */ +#define ST_EXTENDABLE_VG 0x04 /* VG */ +#define ST_ALLOCATED_PV 0x08 /* PV */ +#define ST_SPINDOWN_LV 0x10 /* LV */ -#define STATUS_EXPORTED 0x02 /* VG */ -#define STATUS_EXTENDABLE 0x04 /* VG */ +/* Access bits */ +#define AC_READ 0x01 /* LV VG */ +#define AC_WRITE 0x02 /* LV VG */ +#define AC_CLUSTERED 0x04 /* VG */ +#define AC_SHARED 0x08 /* VG */ -#define STATUS_ALLOCATED 0x02 /* PV */ - -#define STATUS_SPINDOWN 0x02 /* LV */ -#define STATUS_BADBLOCK_ON 0x04 /* LV */ -#define STATUS_ALLOC_STRICT 0x08 /* LV */ -#define STATUS_ALLOC_CONTIGUOUS 0x10 /* LV */ - -#define ACCESS_READ 0x01 /* LV VG */ -#define ACCESS_WRITE 0x02 /* LV VG */ - -#define ACCESS_SNAPSHOT 0x04 /* LV */ -#define ACCESS_SNAPSHOT_ORG 0x08 /* LV */ - -#define ACCESS_CLUSTERED 0x04 /* VG */ -#define ACCESS_SHARED 0x08 /* VG */ +/* LV Flags */ +#define LV_ALLOC_STRICT 0x01 /* LV */ +#define LV_ALLOC_CONTIGUOUS 0x02 /* LV */ +#define LV_SNAPSHOT 0x04 /* LV */ +#define LV_SNAPSHOT_ORG 0x08 /* LV */ +#define LV_BADBLOCK_ON 0x10 /* LV */ @@ -80,8 +77,9 @@ struct logical_volume { struct id *id; char *name; - uint32_t access; uint32_t status; + uint32_t access; + uint32_t flags; uint32_t open; uint64_t size; @@ -114,9 +112,9 @@ struct volume_group { struct logical_volume **lv; }; -struct string_list { +struct name_list { struct list_head list; - char * string; + char * name; }; struct pv_list { @@ -126,20 +124,54 @@ struct pv_list { /* ownership of returned objects passes */ struct io_space { - struct string_list *(*get_vgs)(struct io_space *is); + /* Returns list of names of all vgs */ + struct name_list *(*get_vgs)(struct io_space *is); + + /* Returns list of fully-populated pv structures */ struct pv_list *(*get_pvs)(struct io_space *is); + /* Return PV with given name (may be full or relative path) */ struct physical_volume *(*pv_read)(struct io_space *is, - struct device *dev); + const char *pv_name); + + /* Write a PV structure to disk. */ + /* Fails if the PV is in a VG ie vg_name filled on the disk or in *pv */ int (*pv_write)(struct io_space *is, struct physical_volume *pv); + /* vg_name may contain slash(es) - if not, this function adds prefix */ + /* Default prefix is '/dev/' but can be changed from config file? */ + /* (via a prefix_set() ?) */ struct volume_group *(*vg_read)(struct io_space *is, const char *vg_name); + + /* Write out complete VG metadata. */ + /* Ensure (& impose?) consistency before writing anything. + * eg. PEs can't refer to PVs not part of the VG + * Order write sequence to aid recovery if process is aborted + * (eg flush entire set of changes to each disk in turn?) + * If overwriting existing VG data, needs to check for any PVs + * removed from the VG and update those PVs too. If those PVs + * are no longer in use, blank out vg_name on them. Otherwise + * set vg_name to something temporary and unique - this must be + * a vgsplit with another vg_write() about to follow (or set a new + * status flag?) + * OR Should all consistency checks on the *_write* + * functions here be handled by a wrapper around them, so that they + * *are* capable of leaving the system in an unusable state? + * OR Should vgsplit set flags to modify vg_write behaviour, + * even specifying the new vg_name to insert? + */ int (*vg_write)(struct io_space *is, struct volume_group *vg); + void (*destroy)(struct io_space *is); struct dev_filter *filter; void *private; + /* Something here to allow repair tools & --force options to */ + /* set flags to override certain consistency checks */ + /* eg. in _write functions to allow restoration of metadata */ + /* & in _read functions to allow "gaps" and specify which of */ + /* conflicting copies of metadata to use (device restriction?) */ }; /* FIXME: Move to other files */ @@ -147,21 +179,37 @@ struct io_space *create_text_format(struct dev_filter *filter, const char *text_file); struct io_space *create_lvm_v1_format(struct dev_filter *filter); +inline int write_backup(struct io_space *orig, struct io_space *text) +{ + +} + + int id_eq(struct id *op1, struct id *op2); +/* Create consistent new empty structures, populated with defaults */ struct volume_group *vg_create(); struct physical_volume *pv_create(); int vg_destroy(struct volume_group *vg); +/* Manipulate PV structures */ int pv_add(struct volume_group *vg, struct physical_volume *pv); int pv_remove(struct volume_group *vg, struct physical_volume *pv); struct physical_volume *pv_find(struct volume_group *vg, const char *pv_name); +/* Add an LV to a given VG */ int lv_add(struct volume_group *vg, struct logical_volume *lv); + +/* Remove an LV from a given VG */ int lv_remove(struct volume_group *vg, struct logical_volume *lv); -struct logical_volume *lv_find(struct volume_group *vg, - const char *lv_name); + +/* Return the VG that contains a given LV (based on path given in lv_name) */ +/* (or environment var?) */ +struct volume_group *vg_find(const char *lv_name); + +/* Find an LV within a given VG */ +struct logical_volume *lv_find(struct volume_group *vg, const char *lv_name); #endif diff --git a/tools/errors.h b/tools/errors.h index 304a775da..ea58b0800 100644 --- a/tools/errors.h +++ b/tools/errors.h @@ -18,14 +18,13 @@ * */ -#ifndef _LVM_ERROR_H_INCLUDE -#define _LVM_ERROR_H_INCLUDE +#ifndef _LVM_ERRORS_H +#define _LVM_ERRORS_H -#define LVM_EINVALID_CMD_LINE 1 -#define LVM_ENOMEM 2 -#define LVM_ENO_SUCH_CMD 3 -#define LVM_ECMD_PROCESSED 4 -#define LVM_ECMD_FAILED 5 +#define EINVALID_CMD_LINE 1 +#define ENO_SUCH_CMD 3 +#define ECMD_PROCESSED 4 +#define ECMD_FAILED 5 #endif /* #ifndef _LVM_ERROR_H_INCLUDE */ diff --git a/tools/lvactivate.c b/tools/lvactivate.c index 019add95d..e35dc007e 100644 --- a/tools/lvactivate.c +++ b/tools/lvactivate.c @@ -35,7 +35,7 @@ int lvactivate(int argc, char **argv) if (argc < 2) { log_error("please enter logical volume & physical volume(s)"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } lv_name = argv[0]; diff --git a/tools/lvremove.c b/tools/lvremove.c index 13c739441..77d75e3a6 100644 --- a/tools/lvremove.c +++ b/tools/lvremove.c @@ -30,7 +30,7 @@ int lvremove(int argc, char **argv) if (argc == 0) { log_error("please enter a logical volume path"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } for (opt = 0; opt < argc; opt++) { @@ -56,10 +56,6 @@ int lvremove_single(char *lv_name) ios = active_ios(); - if ((ret = lv_check_name(lv_name)) < 0) { - return LVM_ECMD_FAILED; - } - lv_name = lvm_check_default_vg_name(lv_name, buffer, sizeof (buffer)); /* does VG exist? */ vg_name = vg_name_of_lv(lv_name); @@ -67,32 +63,32 @@ int lvremove_single(char *lv_name) log_verbose("Finding volume group %s", vg_name); if (!(vg = ios->vg_read(ios, vg_name))) { log_error("volume group %s doesn't exist", vg_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (!(vg->status & STATUS_ACTIVE)) { log_error("volume group %s must be active before removing " "logical volume", vg_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (!(lv = lv_find(vg, lv_name))) { log_error("can't find logical volume %s in volume group %s", lv_name, vg_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (lv->access & ACCESS_SNAPSHOT_ORG) { log_error("can't remove logical volume %s under snapshot", lv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (lv->open) { log_error("can't remove open %s logical volume %s", lv->access & ACCESS_SNAPSHOT ? "snapshot" : "", lv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (!arg_count(force_ARG)) { @@ -107,7 +103,7 @@ int lvremove_single(char *lv_name) log_verbose("releasing logical volume %s", lv_name); if (lv_remove(vg, lv)) { log_error("Error releasing logical volume %s", lv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("unlinking special file %s", lv_name); @@ -116,7 +112,7 @@ int lvremove_single(char *lv_name) /* store it on disks */ if (ios->vg_write(vg)) - return LVM_ECMD_FAILED; + return ECMD_FAILED; if ((ret = do_autobackup(vg_name, vg))) return ret; diff --git a/tools/pvchange.c b/tools/pvchange.c index c13c2c9fa..e3228f01f 100644 --- a/tools/pvchange.c +++ b/tools/pvchange.c @@ -48,25 +48,25 @@ int pvchange(int argc, char **argv) if (arg_count(allocation_ARG) == 0) { log_error("Please give the x option"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } ios = active_ios(); if (!(arg_count(all_ARG)) && !argc) { log_error("Please give a physical volume path"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } if (arg_count(all_ARG) && argc) { log_error("Option a and PhysicalVolumePath are exclusive"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } if (arg_count(all_ARG)) { log_verbose("Scanning for physical volume names"); if (!(pvs_list = ios->get_pvs(ios))) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } list_for_each(pvh, &pvs_list->list) { diff --git a/tools/pvcreate.c b/tools/pvcreate.c index f606b4c8b..e538ab77c 100644 --- a/tools/pvcreate.c +++ b/tools/pvcreate.c @@ -28,12 +28,12 @@ int pvcreate(int argc, char **argv) if (!argc) { log_error("Please enter a physical volume path"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } if (arg_count(yes_ARG) && !arg_count(force_ARG)) { log_error("option y can only be given with option f"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } for (opt = 0; opt < argc; opt++) diff --git a/tools/pvdisplay.c b/tools/pvdisplay.c index e12fda87e..dc5809519 100644 --- a/tools/pvdisplay.c +++ b/tools/pvdisplay.c @@ -28,12 +28,12 @@ int pvdisplay(int argc, char **argv) if (argc == 0) { log_error("please enter a physical volume path"); - return LVM_EINVALID_CMD_LINE; + return 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; + return EINVALID_CMD_LINE; } for (opt = 0; opt < argc; opt++) diff --git a/tools/pvscan.c b/tools/pvscan.c index 98ae77861..ef4bea9ef 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -36,9 +36,9 @@ int pvscan(int argc, char **argv) struct list_head *pvh; struct physical_volume *pv; - __uint64_t size_total = 0; - __uint64_t size_new = 0; - __uint64_t size = 0; + uint64_t size_total = 0; + uint64_t size_new = 0; + uint64_t size = 0; int len = 0; pv_max_name_len = 0; @@ -46,7 +46,7 @@ int pvscan(int argc, char **argv) if (arg_count(novolumegroup_ARG) && arg_count(exported_ARG)) { log_error("options e and n incompatible"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } if (arg_count(exported_ARG) || arg_count(novolumegroup_ARG)) @@ -59,7 +59,7 @@ int pvscan(int argc, char **argv) ios = active_ios(); if (!(pvs_list = ios->get_pvs(ios))) - return LVM_ECMD_FAILED; + return ECMD_FAILED; /* eliminate exported/new if required */ list_for_each(pvh, &pvs_list->list) { diff --git a/tools/toollib.c b/tools/toollib.c index e2c6d2bc5..648ea980e 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -31,24 +31,25 @@ int init_autobackup() { char *lvm_autobackup; - if (arg_count(autobackup_ARG)) + if (arg_count(autobackup_ARG)) { _autobackup = strcmp(arg_str_value(autobackup_ARG, "y"), "n"); - else { - _autobackup = 1; /* default */ + return 0; + } - 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; - } - } + _autobackup = 1; /* default */ + + lvm_autobackup = getenv("LVM_AUTOBACKUP"); + if (!lvm_autobackup) + return 0; + + log_print("using environment variable LVM_AUTOBACKUP " + "to set option A"); + if (!strcasecmp(lvm_autobackup, "no")) + _autobackup = 0; + else if (strcasecmp(lvm_autobackup, "yes")) { + log_error("environment variable LVM_AUTOBACKUP has " + "invalid value \"%s\"!", lvm_autobackup); + return -1; } return 0; diff --git a/tools/vgcreate.c b/tools/vgcreate.c index bf7f4a63f..70cc7b9ad 100644 --- a/tools/vgcreate.c +++ b/tools/vgcreate.c @@ -70,26 +70,26 @@ int vgcreate(int argc, char **argv) SIZE_SHORT), display_size(sectors_to_k(LVM_MAX_PE_SIZE), SIZE_SHORT)); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } } if (argc == 0) { log_error ("please enter a volume group name and physical volumes"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } vg_name = argv[0]; if (argc == 1) { log_error("please enter physical volume name(s)"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } if ((vg = ios->vg_read(ios, vg_name))) { log_error ("Volume group already exists: please use a different name"); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } /***** FIXME: confirm we're now free of this restriction @@ -107,7 +107,7 @@ int vgcreate(int argc, char **argv) *****/ if (!(vg = vg_create())) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } /* read all PVs */ @@ -121,12 +121,12 @@ int vgcreate(int argc, char **argv) if (!(pv_dev = dev_cache_get(pv_name))) { log_error("Device %s not found", pv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (!(pv = ios->pv_read(ios, pv_dev))) { log_error("Physical volume %s not found", pv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("checking physical volume %s", pv_name); @@ -135,7 +135,7 @@ int vgcreate(int argc, char **argv) /* FIXME size should already be filled in pv structure?! */ if ((size = dev_get_size(pv_dev)) < 0) { log_error("Unable to get size of %s", pv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("physical volume %s is %d 512-byte sectors", @@ -154,14 +154,14 @@ int vgcreate(int argc, char **argv) log_error ("physical volume %s occurs multiple times", pv_name); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } } if ((pvp = dbg_realloc(pvp, (np + 2) * sizeof (pv *))) == NULL) { log_error("realloc error in file \"%s\" [line %d]", __FILE__, __LINE__); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } pvp[np] = pv; @@ -177,12 +177,12 @@ int vgcreate(int argc, char **argv) if (np == 0) { log_error("no valid physical volumes in command line"); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (np != count_sav) { log_error("some invalid physical volumes in command line"); - return LVM_ECMD_FAILED; /* Impossible to reach here? */ + return ECMD_FAILED; /* Impossible to reach here? */ } log_verbose("%d physical volume%s will be inserted into " @@ -197,14 +197,14 @@ int vgcreate(int argc, char **argv) log_verbose("maximum of %d physical volumes", max_pv); if (max_pv < 0 || max_pv <= np || max_pv > MAX_PV) { log_error("invalid maximum physical volumes -p %d", max_pv); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } vg->max_pv = max_pv; log_verbose("maximum of %d logical volumes", max_lv); if (max_lv < 0 || max_lv > MAX_LV) { log_error("invalid maximum logical volumes -l %d", max_lv); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } vg->max_lv = max_lv; @@ -245,7 +245,7 @@ int vgcreate(int argc, char **argv) LVM_PE_T_MAX, SHORT))); dbg_free(dummy); } - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (arg_count(physicalextentsize_ARG) == 0) { @@ -263,12 +263,12 @@ int vgcreate(int argc, char **argv) /* store vg on disk(s) */ if (ios->vg_write(ios, vg)) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("creating volume group directory %s%s", prefix, vg_name); if (vg_create_dir_and_group(&vg)) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } /* FIXME Activate it */ diff --git a/tools/vgrename.c b/tools/vgrename.c index d386b6c0b..459a75fe5 100644 --- a/tools/vgrename.c +++ b/tools/vgrename.c @@ -41,7 +41,7 @@ int vgrename(int argc, char **argv) if (argc != 2) { log_error("command line too short"); - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } ios = active_ios(); @@ -54,11 +54,11 @@ int vgrename(int argc, char **argv) if (strlen(vg_name_new = argv[1]) > NAME_LEN - length - 2) { log_error("New logical volume path exceeds maximum length " "of %d!", NAME_LEN - length - 2); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (vg_check_name(vg_name_new) < 0) { - return LVM_EINVALID_CMD_LINE; + return EINVALID_CMD_LINE; } /* FIXME Handle prefix-related logic internally within ios functions? */ @@ -73,13 +73,13 @@ int vgrename(int argc, char **argv) if (strcmp(vg_name_old, vg_name_new) == 0) { log_error("volume group names must be different"); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("Checking existing volume group %s", vg_name_old); if (!(vg_old = ios->vg_read(ios, vg_name_old))) { log_error("volume group %s doesn't exist", vg_name_old); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if (vg_old->status & STATUS_ACTIVE) { log_error("Volume group %s still active", vg_name_old); @@ -88,7 +88,7 @@ int vgrename(int argc, char **argv) log_verbose("Checking new volume group %s", vg_name_new); if ((vg_new = ios->vg_read(ios, vg_name_new))) { log_error("New volume group %s already exists", vg_name_new); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } /* change the volume name in all structures */ @@ -105,7 +105,7 @@ int vgrename(int argc, char **argv) lv_change_vgname(vg_name_new, vg_old->lv[l]->name))) { log_error("A new logical volume path exceeds " "maximum of %d!", NAME_LEN - 2); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } strcpy(vg_old->lv[l]->name, lv_name_ptr); } @@ -113,23 +113,23 @@ int vgrename(int argc, char **argv) if (vg_remove_dir_and_group_and_nodes(vg_name_old) < 0) { log_error("removing volume group nodes and directory of \"%s\"", vg_name_old); - return LVM_ECMD_FAILED; + return ECMD_FAILED; } /* store it on disks */ log_verbose("updating volume group name"); if (ios->vg_write(ios, vg_old)) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } log_verbose("creating volume group directory %s%s", prefix, vg_name_new); if (vg_create_dir_and_group_and_nodes(vg_old)) { - return LVM_ECMD_FAILED; + return ECMD_FAILED; } if ((ret = do_autobackup(vg_name_new, vg_old))) - return LVM_ECMD_FAILED; + return ECMD_FAILED; log_print("Volume group %s successfully renamed to %s", vg_name_old, vg_name_new);