diff --git a/lib/activate/activate.c b/lib/activate/activate.c index e8dbf7e59..03be3565a 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -4,27 +4,48 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "metadata.h" #include "activate.h" #include "display.h" -#include "log.h" #include "fs.h" #include "lvm-string.h" #include "pool.h" #include "toolcontext.h" #include "dev_manager.h" -/* FIXME Temporary */ -#include "vgcache.h" - #include #include #include #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) +static int _activation = 1; + +void set_activation(int activation) +{ + if (activation == _activation) + return; + + _activation = activation; + if (_activation) + log_verbose("Activation enabled. Device-mapper kernel " + "driver will be used."); + else + log_verbose("Activation disabled. No device-mapper " + "interaction will be attempted."); +} + +int activation() +{ + return _activation; +} + int library_version(char *version, size_t size) { + if (!activation()) + return 0; + if (!dm_get_library_version(version, size)) return 0; return 1; @@ -35,6 +56,9 @@ int driver_version(char *version, size_t size) int r = 0; struct dm_task *dmt; + if (!activation()) + return 0; + log_very_verbose("Getting driver version"); if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) { stack; @@ -63,6 +87,9 @@ int lv_info(struct logical_volume *lv, struct dm_info *info) int r; struct dev_manager *dm; + if (!activation()) + return 0; + if (!(dm = dev_manager_create(lv->vg->name))) { stack; return 0; @@ -83,6 +110,9 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent) int r; struct dev_manager *dm; + if (!activation()) + return 0; + if (!(dm = dev_manager_create(lv->vg->name))) { stack; return 0; @@ -182,6 +212,9 @@ int lvs_in_vg_activated(struct volume_group *vg) struct logical_volume *lv; int count = 0; + if (!activation()) + return 0; + list_iterate(lvh, &vg->lvs) { lv = list_item(lvh, struct lv_list)->lv; count += (_lv_active(lv) == 1); @@ -196,6 +229,9 @@ int lvs_in_vg_opened(struct volume_group *vg) struct logical_volume *lv; int count = 0; + if (!activation()) + return 0; + list_iterate(lvh, &vg->lvs) { lv = list_item(lvh, struct lv_list)->lv; count += (_lv_open_count(lv) == 1); @@ -204,44 +240,21 @@ int lvs_in_vg_opened(struct volume_group *vg) return count; } -static struct logical_volume *_lv_from_lvid(struct cmd_context *cmd, - const char *lvid_s) -{ - struct lv_list *lvl; - struct volume_group *vg; - union lvid *lvid; - - lvid = (union lvid *) lvid_s; - - log_very_verbose("Finding volume group for uuid %s", lvid_s); - if (!(vg = vg_read_by_vgid(cmd, lvid->id[0].uuid))) { - log_error("Volume group for uuid not found: %s", lvid_s); - return NULL; - } - - log_verbose("Found volume group \"%s\"", vg->name); - if (vg->status & EXPORTED_VG) { - log_error("Volume group \"%s\" is exported", vg->name); - return NULL; - } - - if (!(lvl = find_lv_in_vg_by_lvid(vg, lvid))) { - log_very_verbose("Can't find logical volume id %s", lvid_s); - return NULL; - } - - return lvl->lv; -} - /* These return success if the device is not active */ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) { struct logical_volume *lv; struct dm_info info; - if (!(lv = _lv_from_lvid(cmd, lvid_s))) + if (!activation()) + return 1; + + if (!(lv = lv_from_lvid(cmd, lvid_s))) return 0; + if (!activation()) + return 1; + if (test_mode()) { _skip("Suspending '%s'.", lv->name); return 0; @@ -263,7 +276,10 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) struct logical_volume *lv; struct dm_info info; - if (!(lv = _lv_from_lvid(cmd, lvid_s))) + if (!activation()) + return 1; + + if (!(lv = lv_from_lvid(cmd, lvid_s))) return 0; if (test_mode()) { @@ -287,7 +303,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) struct logical_volume *lv; struct dm_info info; - if (!(lv = _lv_from_lvid(cmd, lvid_s))) + if (!activation()) + return 1; + + if (!(lv = lv_from_lvid(cmd, lvid_s))) return 0; if (test_mode()) { @@ -311,7 +330,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s) struct logical_volume *lv; struct dm_info info; - if (!(lv = _lv_from_lvid(cmd, lvid_s))) + if (!activation()) + return 1; + + if (!(lv = lv_from_lvid(cmd, lvid_s))) return 0; if (test_mode()) { diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 15a03c276..8256d0ea0 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -7,8 +7,12 @@ #ifndef LVM_ACTIVATE_H #define LVM_ACTIVATE_H +#include "metadata.h" #include +void set_activation(int activation); +int activation(); + int driver_version(char *version, size_t size); int library_version(char *version, size_t size); diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 09124b796..8c345d35f 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -4,10 +4,10 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "dev_manager.h" #include "pool.h" #include "hash.h" -#include "log.h" #include "lvm-string.h" #include "fs.h" @@ -162,7 +162,7 @@ static int _pre_list_add(struct pool *mem, struct list *pl, char *str) * another hyphen. The top layer of any device has no layer * name. eg, vg0-lvol0. */ -static void _count_hyphens(const char *str, size_t * len, int *hyphens) +static void _count_hyphens(const char *str, size_t *len, int *hyphens) { const char *ptr; @@ -577,7 +577,7 @@ static int _resume(struct dev_layer *dl) * Emit a target for a given segment. * FIXME: tidy this function. */ -static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg) +static int _emit_target(struct dm_task *dmt, struct lv_segment *seg) { char params[1024]; uint64_t esize = seg->lv->vg->extent_size; @@ -638,11 +638,11 @@ static int _populate_vanilla(struct dev_manager *dm, struct dm_task *dmt, struct dev_layer *dl) { struct list *segh; - struct stripe_segment *seg; + struct lv_segment *seg; struct logical_volume *lv = dl->lv; list_iterate(segh, &lv->segments) { - seg = list_item(segh, struct stripe_segment); + seg = list_item(segh, struct lv_segment); if (!_emit_target(dmt, seg)) { log_error("Unable to build table for '%s'", lv->name); return 0; diff --git a/lib/activate/fs.c b/lib/activate/fs.c index c981c2098..5f26f5f1d 100644 --- a/lib/activate/fs.c +++ b/lib/activate/fs.c @@ -4,20 +4,16 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "fs.h" -#include "log.h" #include "toolcontext.h" #include "lvm-string.h" #include "lvm-file.h" -#include #include #include #include #include -#include -#include - #include static int _mk_dir(struct volume_group *vg) diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c new file mode 100644 index 000000000..8c10945e6 --- /dev/null +++ b/lib/commands/toolcontext.c @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + * + */ + +#include "lib.h" +#include "toolcontext.h" +#include "pool.h" +#include "metadata.h" +#include "defaults.h" +#include "lvm-string.h" +#include "activate.h" +#include "filter.h" +#include "filter-composite.h" +#include "filter-persistent.h" +#include "filter-regex.h" +#include "label.h" +#include "lvm-file.h" +#include "format-text.h" +#include "sharedlib.h" + +#ifdef LVM1_INTERNAL +#include "format1.h" +#endif + +#include +#include +#include +#include +#include + +static FILE *_log; + +static int _get_env_vars(struct cmd_context *cmd) +{ + const char *e; + + /* Set to "" to avoid using any system directory */ + if ((e = getenv("LVM_SYSTEM_DIR"))) { + if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir), + "%s", e) < 0) { + log_error("LVM_SYSTEM_DIR environment variable " + "is too long."); + return 0; + } + } + + return 1; +} + +static void _init_logging(struct cmd_context *cmd) +{ + char *open_mode = "a"; + time_t t; + + const char *log_file; + + /* Syslog */ + cmd->default_settings.syslog = + find_config_int(cmd->cf->root, "log/syslog", '/', DEFAULT_SYSLOG); + if (cmd->default_settings.syslog != 1) + fin_syslog(); + + if (cmd->default_settings.syslog > 1) + init_syslog(cmd->default_settings.syslog); + + /* Debug level for log file output */ + cmd->default_settings.debug = + find_config_int(cmd->cf->root, "log/level", '/', DEFAULT_LOGLEVEL); + init_debug(cmd->default_settings.debug); + + /* Verbose level for tty output */ + cmd->default_settings.verbose = + find_config_int(cmd->cf->root, "log/verbose", '/', DEFAULT_VERBOSE); + init_verbose(cmd->default_settings.verbose); + + /* Log message formatting */ + init_indent(find_config_int(cmd->cf->root, "log/indent", '/', + DEFAULT_INDENT)); + + cmd->default_settings.msg_prefix = find_config_str(cmd->cf->root, + "log/prefix", '/', + DEFAULT_MSG_PREFIX); + init_msg_prefix(cmd->default_settings.msg_prefix); + + cmd->default_settings.cmd_name = find_config_int(cmd->cf->root, + "log/command_names", + '/', DEFAULT_CMD_NAME); + init_cmd_name(cmd->default_settings.cmd_name); + + /* Test mode */ + cmd->default_settings.test = + find_config_int(cmd->cf->root, "global/test", '/', 0); + + /* Settings for logging to file */ + if (find_config_int(cmd->cf->root, "log/overwrite", '/', + DEFAULT_OVERWRITE)) + open_mode = "w"; + + log_file = find_config_str(cmd->cf->root, "log/file", '/', 0); + if (log_file) { + /* set up the logging */ + if (!(_log = fopen(log_file, open_mode))) + log_error("Couldn't open log file %s", log_file); + else + init_log(_log); + } + + t = time(NULL); + log_verbose("Logging initialised at %s", ctime(&t)); + + /* Tell device-mapper about our logging */ + dm_log_init(print_log); +} + +static int _process_config(struct cmd_context *cmd) +{ + mode_t old_umask; + + /* umask */ + cmd->default_settings.umask = find_config_int(cmd->cf->root, + "global/umask", '/', + DEFAULT_UMASK); + + if ((old_umask = umask((mode_t) cmd->default_settings.umask)) != + (mode_t) cmd->default_settings.umask) + log_verbose("Set umask to %04o", cmd->default_settings.umask); + + /* dev dir */ + if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/", + find_config_str(cmd->cf->root, "devices/dir", + '/', DEFAULT_DEV_DIR)) < 0) { + log_error("Device directory given in config file too long"); + return 0; + } + + dm_set_dev_dir(cmd->dev_dir); + + /* proc dir */ + if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s", + find_config_str(cmd->cf->root, "global/proc", + '/', DEFAULT_PROC_DIR)) < 0) { + log_error("Device directory given in config file too long"); + return 0; + } + + /* activation? */ + cmd->default_settings.activation = find_config_int(cmd->cf->root, + "global/activation", + '/', + DEFAULT_ACTIVATION); + set_activation(cmd->default_settings.activation); + + return 1; +} + +/* Find and read config file */ +static int _init_config(struct cmd_context *cmd) +{ + struct stat info; + char config_file[PATH_MAX] = ""; + + if (!(cmd->cf = create_config_tree())) { + stack; + return 0; + } + + /* No config file if LVM_SYSTEM_DIR is empty */ + if (!*cmd->sys_dir) + return 1; + + if (lvm_snprintf(config_file, sizeof(config_file), + "%s/lvm.conf", cmd->sys_dir) < 0) { + log_error("LVM_SYSTEM_DIR was too long"); + destroy_config_tree(cmd->cf); + return 0; + } + + /* Is there a config file? */ + if (stat(config_file, &info) == -1) { + if (errno == ENOENT) + return 1; + log_sys_error("stat", config_file); + destroy_config_tree(cmd->cf); + return 0; + } + + if (!read_config_file(cmd->cf, config_file)) { + log_error("Failed to load config file %s", config_file); + destroy_config_tree(cmd->cf); + return 0; + } + + return 1; +} + +static int _init_dev_cache(struct cmd_context *cmd) +{ + struct config_node *cn; + struct config_value *cv; + + if (!dev_cache_init()) { + stack; + return 0; + } + + if (!(cn = find_config_node(cmd->cf->root, "devices/scan", '/'))) { + if (!dev_cache_add_dir("/dev")) { + log_error("Failed to add /dev to internal " + "device cache"); + return 0; + } + log_verbose("device/scan not in config file: " + "Defaulting to /dev"); + return 1; + } + + for (cv = cn->v; cv; cv = cv->next) { + if (cv->type != CFG_STRING) { + log_error("Invalid string in config file: " + "devices/scan"); + return 0; + } + + if (!dev_cache_add_dir(cv->v.str)) { + log_error("Failed to add %s to internal device cache", + cv->v.str); + return 0; + } + } + + return 1; +} + +static struct dev_filter *_init_filter_components(struct cmd_context *cmd) +{ + struct config_node *cn; + struct dev_filter *f1, *f2, *f3; + + if (!(f2 = lvm_type_filter_create(cmd->proc_dir))) + return NULL; + + if (!(cn = find_config_node(cmd->cf->root, "devices/filter", '/'))) { + log_debug("devices/filter not found in config file: no regex " + "filter installed"); + return f2; + } + + if (!(f1 = regex_filter_create(cn->v))) { + log_error("Failed to create regex device filter"); + return f2; + } + + if (!(f3 = composite_filter_create(2, f1, f2))) { + log_error("Failed to create composite device filter"); + return f2; + } + + return f3; +} + +static int _init_filters(struct cmd_context *cmd) +{ + const char *lvm_cache; + struct dev_filter *f3, *f4; + struct stat st; + char cache_file[PATH_MAX]; + + cmd->dump_filter = 0; + + if (!(f3 = _init_filter_components(cmd))) + return 0; + + if (lvm_snprintf(cache_file, sizeof(cache_file), + "%s/.cache", cmd->sys_dir) < 0) { + log_error("Persistent cache filename too long ('%s/.cache').", + cmd->sys_dir); + return 0; + } + + lvm_cache = + find_config_str(cmd->cf->root, "devices/cache", '/', cache_file); + if (!(f4 = persistent_filter_create(f3, lvm_cache))) { + log_error("Failed to create persistent device filter"); + return 0; + } + + /* Should we ever dump persistent filter state? */ + if (find_config_int(cmd->cf->root, "devices/write_cache_state", '/', 1)) + cmd->dump_filter = 1; + + if (!*cmd->sys_dir) + cmd->dump_filter = 0; + + if (!stat(lvm_cache, &st) && !persistent_filter_load(f4)) + log_verbose("Failed to load existing device cache from %s", + lvm_cache); + + cmd->filter = f4; + + return 1; +} + +static int _init_formats(struct cmd_context *cmd) +{ + const char *format; + + struct format_type *fmt; + struct list *fmth; + struct config_node *cn; + struct config_value *cv; + + struct format_type *(*init_format_fn) (struct cmd_context * cmd); + + void *lib; + + label_init(); + +#ifdef LVM1_INTERNAL + if (!(fmt = init_lvm1_format(cmd))) + return 0; + fmt->library = NULL; + list_add(&cmd->formats, &fmt->list); +#endif + + /* Load any formats in shared libs */ + if ((cn = find_config_node(cmd->cf->root, "global/format_libraries", + '/'))) { + for (cv = cn->v; cv; cv = cv->next) { + if (cv->type != CFG_STRING) { + log_error("Invalid string in config file: " + "global/format_libraries"); + return 0; + } + if (!(lib = load_shared_library(cmd->cf, cv->v.str, + "format"))) { + stack; + return 0; + } + + if (!(init_format_fn = dlsym(lib, "init_format"))) { + log_error("Shared library %s does not contain " + "format functions", cv->v.str); + dlclose(lib); + return 0; + } + + if (!(fmt = init_format_fn(cmd))) + return 0; + fmt->library = lib; + list_add(&cmd->formats, &fmt->list); + } + } + + if (!(fmt = create_text_format(cmd))) + return 0; + fmt->library = NULL; + list_add(&cmd->formats, &fmt->list); + + cmd->fmt_backup = fmt; + + format = find_config_str(cmd->cf->root, "global/format", '/', + DEFAULT_FORMAT); + + list_iterate(fmth, &cmd->formats) { + fmt = list_item(fmth, struct format_type); + if (!strcasecmp(fmt->name, format) || + (fmt->alias && !strcasecmp(fmt->alias, format))) { + cmd->default_settings.fmt = fmt; + return 1; + } + } + + log_error("_init_formats: Default format (%s) not found", format); + return 0; +} + +/* Entry point */ +struct cmd_context *create_toolcontext(struct arg *the_args) +{ + struct cmd_context *cmd; + + if (!setlocale(LC_ALL, "")) + log_error("setlocale failed"); + + init_syslog(DEFAULT_LOG_FACILITY); + + if (!(cmd = dbg_malloc(sizeof(*cmd)))) { + log_error("Failed to allocate command context"); + return NULL; + } + memset(cmd, 0, sizeof(*cmd)); + cmd->args = the_args; + list_init(&cmd->formats); + + strcpy(cmd->sys_dir, DEFAULT_SYS_DIR); + + if (!_get_env_vars(cmd)) + goto error; + + /* Create system directory if it doesn't already exist */ + if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) + goto error; + + if (!_init_config(cmd)) + goto error; + + _init_logging(cmd); + + if (!_process_config(cmd)) + goto error; + + if (!_init_dev_cache(cmd)) + goto error; + + if (!_init_filters(cmd)) + goto error; + + if (!(cmd->mem = pool_create(4 * 1024))) { + log_error("Command memory pool creation failed"); + return 0; + } + + if (!_init_formats(cmd)) + goto error; + + cmd->current_settings = cmd->default_settings; + + return cmd; + + error: + dbg_free(cmd); + return NULL; +} + +void destroy_formats(struct list *formats) +{ + struct list *fmtl, *tmp; + struct format_type *fmt; + void *lib; + + list_iterate_safe(fmtl, tmp, formats) { + fmt = list_item(fmtl, struct format_type); + list_del(&fmt->list); + lib = fmt->library; + fmt->ops->destroy(fmt); + if (lib) + dlclose(lib); + } +} + +void destroy_toolcontext(struct cmd_context *cmd) +{ + if (cmd->dump_filter) + persistent_filter_dump(cmd->filter); + + cache_destroy(); + label_exit(); + destroy_formats(&cmd->formats); + cmd->filter->destroy(cmd->filter); + pool_destroy(cmd->mem); + dev_cache_exit(); + destroy_config_tree(cmd->cf); + dbg_free(cmd); + + dump_memory(); + fin_log(); + fin_syslog(); + + if (_log) + fclose(_log); + +} diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 30894e64f..396cea7cb 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -13,25 +13,57 @@ #include "pool.h" #include "metadata.h" +#include +#include + +/* + * Config options that can be changed while commands are processed + */ +struct config_info { + int debug; + int verbose; + int test; + int syslog; + int activation; + const char *msg_prefix; + int cmd_name; /* Show command name? */ + + int archive; /* should we archive ? */ + int backup; /* should we backup ? */ + + struct format_type *fmt; + + mode_t umask; +}; + +/* FIXME Split into tool & library contexts */ /* command-instance-related variables needed by library */ struct cmd_context { /* format handler allocates all objects from here */ struct pool *mem; struct format_type *fmt; /* Current format to use by default */ + struct format_type *fmt_backup; /* Format to use for backups */ - /* FIXME Move into dynamic list */ - struct format_type *fmt1; /* Format1 */ - struct format_type *fmtt; /* Format_text */ + struct list formats; /* Available formats */ char *cmd_line; - char *dev_dir; - struct dev_filter *filter; - struct config_file *cf; - struct command *command; - struct uuid_map *um; struct arg *args; + + struct dev_filter *filter; + int dump_filter; /* Dump filter when exiting? */ + + struct config_tree *cf; + struct config_info default_settings; + struct config_info current_settings; + + char sys_dir[PATH_MAX]; + char dev_dir[PATH_MAX]; + char proc_dir[PATH_MAX]; }; +struct cmd_context *create_toolcontext(struct arg *the_args); +void destroy_toolcontext(struct cmd_context *cmd); + #endif diff --git a/lib/config/config.c b/lib/config/config.c index 39cfa8793..b8149b6b1 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -4,18 +4,18 @@ * This file is released under the LGPL. */ -#include +#include "lib.h" +#include "config.h" +#include "crc.h" +#include "pool.h" +#include "device.h" + #include #include #include #include #include -#include -#include - -#include "config.h" -#include "pool.h" -#include "log.h" +#include enum { TOK_INT, @@ -32,10 +32,10 @@ enum { }; struct parser { - const char *fb, *fe; /* file limits */ + char *fb, *fe; /* file limits */ int t; /* token limits and type */ - const char *tb, *te; + char *tb, *te; int fd; /* descriptor for file being parsed */ int line; /* line number we are on */ @@ -44,8 +44,10 @@ struct parser { }; struct cs { - struct config_file cf; + struct config_tree cf; struct pool *mem; + time_t timestamp; + char *filename; }; static void _get_token(struct parser *p); @@ -81,7 +83,7 @@ static int _tok_match(const char *str, const char *b, const char *e) /* * public interface */ -struct config_file *create_config_file(void) +struct config_tree *create_config_tree(void) { struct cs *c; struct pool *mem = pool_create(10 * 1024); @@ -99,20 +101,24 @@ struct config_file *create_config_file(void) c->mem = mem; c->cf.root = (struct config_node *) NULL; + c->timestamp = 0; + c->filename = NULL; return &c->cf; } -void destroy_config_file(struct config_file *cf) +void destroy_config_tree(struct config_tree *cf) { pool_destroy(((struct cs *) cf)->mem); } -int read_config(struct config_file *cf, const char *file) +int read_config_fd(struct config_tree *cf, int fd, const char *file, + off_t offset, uint32_t size, off_t offset2, uint32_t size2, + checksum_fn_t checksum_fn, uint32_t checksum) { struct cs *c = (struct cs *) cf; struct parser *p; - struct stat info; - int r = 1, fd; + off_t mmap_offset; + int r = 0; if (!(p = pool_alloc(c->mem, sizeof(*p)))) { stack; @@ -120,12 +126,93 @@ int read_config(struct config_file *cf, const char *file) } p->mem = c->mem; - /* memory map the file */ - if (stat(file, &info) || S_ISDIR(info.st_mode)) { + if (size2) { + /* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space + * one PAGE_SIZE larger than required... + */ + if (!(p->fb = dbg_malloc(size + size2))) { + stack; + return 0; + } + if (lseek(fd, offset, SEEK_SET) < 0) { + log_sys_error("lseek", file); + goto out; + } + if (raw_read(fd, p->fb, size) != size) { + log_error("Circular read from %s failed", file); + goto out; + } + if (lseek(fd, offset2, SEEK_SET) < 0) { + log_sys_error("lseek", file); + goto out; + } + if (raw_read(fd, p->fb + size, size2) != size2) { + log_error("Circular read from %s failed", file); + goto out; + } + } else { + mmap_offset = offset % PAGE_SIZE; + /* memory map the file */ + p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, + MAP_PRIVATE, fd, offset - mmap_offset); + if (p->fb == (caddr_t) (-1)) { + log_sys_error("mmap", file); + goto out; + } + + p->fb = p->fb + mmap_offset; + } + + if (checksum_fn && checksum != + (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size), + p->fb + size, size2))) { + log_error("%s: Checksum error", file); + goto out; + } + + p->fe = p->fb + size + size2; + + /* parse */ + p->tb = p->te = p->fb; + p->line = 1; + _get_token(p); + if (!(cf->root = _file(p))) { + stack; + goto out; + } + + r = 1; + + out: + if (size2) + dbg_free(p->fb); + else { + /* unmap the file */ + if (munmap((char *) (p->fb - mmap_offset), size)) { + log_sys_error("munmap", file); + r = 0; + } + } + + return r; +} + +int read_config_file(struct config_tree *cf, const char *file) +{ + struct cs *c = (struct cs *) cf; + struct stat info; + int r = 1, fd; + + if (stat(file, &info)) { log_sys_error("stat", file); return 0; } + if (!S_ISREG(info.st_mode)) { + log_error("%s is not a regular file", file); + return 0; + } + if (info.st_size == 0) { log_verbose("%s is empty", file); return 1; @@ -136,34 +223,79 @@ int read_config(struct config_file *cf, const char *file) return 0; } - p->fb = mmap((caddr_t) 0, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (p->fb == (caddr_t) (-1)) { - log_sys_error("mmap", file); - close(fd); - return 0; - } - p->fe = p->fb + info.st_size; - - /* parse */ - p->tb = p->te = p->fb; - p->line = 1; - _get_token(p); - if (!(cf->root = _file(p))) { - stack; - r = 0; - } - - /* unmap the file */ - if (munmap((char *) p->fb, info.st_size)) { - log_sys_error("munmap", file); - r = 0; - } + r = read_config_fd(cf, fd, file, 0, info.st_size, 0, 0, + (checksum_fn_t) NULL, 0); close(fd); + + c->timestamp = info.st_mtime; + c->filename = pool_strdup(c->mem, file); + return r; } -static void _write_value(FILE * fp, struct config_value *v) +/* + * Returns 1 if config file reloaded + */ +int reload_config_file(struct config_tree **cf) +{ + struct config_tree *new_cf; + struct cs *c = (struct cs *) *cf; + struct cs *new_cs; + struct stat info; + int r, fd; + + if (stat(c->filename, &info) == -1) { + if (errno == ENOENT) + return 1; + log_sys_error("stat", c->filename); + log_error("Failed to reload configuration file"); + return 0; + } + + if (!S_ISREG(info.st_mode)) { + log_error("Configuration file %s is not a regular file", + c->filename); + return 0; + } + + /* Unchanged? */ + if (c->timestamp == info.st_mtime) + return 0; + + log_verbose("Detected config file change: Reloading %s", c->filename); + + if (info.st_size == 0) { + log_verbose("Config file reload: %s is empty", c->filename); + return 0; + } + + if ((fd = open(c->filename, O_RDONLY)) < 0) { + log_sys_error("open", c->filename); + return 0; + } + + if (!(new_cf = create_config_tree())) { + log_error("Allocation of new config_tree failed"); + return 0; + } + + r = read_config_fd(new_cf, fd, c->filename, 0, info.st_size, 0, 0, + (checksum_fn_t) NULL, 0); + close(fd); + + if (r) { + new_cs = (struct cs *) new_cf; + new_cs->filename = pool_strdup(new_cs->mem, c->filename); + new_cs->timestamp = info.st_mtime; + destroy_config_tree(*cf); + *cf = new_cf; + } + + return r; +} + +static void _write_value(FILE *fp, struct config_value *v) { switch (v->type) { case CFG_STRING: @@ -183,11 +315,12 @@ static void _write_value(FILE * fp, struct config_value *v) break; default: - log_err("Unknown value type"); + log_error("_write_value: Unknown value type: %d", v->type); + } } -static int _write_config(struct config_node *n, FILE * fp, int level) +static int _write_config(struct config_node *n, FILE *fp, int level) { char space[MAX_INDENT + 1]; int l = (level < MAX_INDENT) ? level : MAX_INDENT; @@ -230,7 +363,7 @@ static int _write_config(struct config_node *n, FILE * fp, int level) return 1; } -int write_config(struct config_file *cf, const char *file) +int write_config_file(struct config_tree *cf, const char *file) { int r = 1; FILE *fp = fopen(file, "w"); @@ -332,9 +465,8 @@ static struct config_value *_value(struct parser *p) match(TOK_COMMA); } match(TOK_ARRAY_E); - /* - * Special case an empty array. + * Special case for an empty array. */ if (!h) { if (!(h = _create_value(p))) @@ -342,6 +474,7 @@ static struct config_value *_value(struct parser *p) h->type = CFG_EMPTY_ARRAY; } + } else h = _type(p); @@ -352,6 +485,7 @@ static struct config_value *_type(struct parser *p) { /* [0-9]+ | [0-9]*\.[0-9]* | ".*" */ struct config_value *v = _create_value(p); + if (!v) return NULL; @@ -403,7 +537,7 @@ static void _get_token(struct parser *p) { p->tb = p->te; _eat_space(p); - if (p->tb == p->fe) { + if (p->tb == p->fe || !*p->tb) { p->t = TOK_EOF; return; } @@ -444,13 +578,14 @@ static void _get_token(struct parser *p) case '"': p->t = TOK_STRING; p->te++; - while ((p->te != p->fe) && (*p->te != '"')) { - if ((*p->te == '\\') && (p->te + 1 != p->fe)) + while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) { + if ((*p->te == '\\') && (p->te + 1 != p->fe) && + *(p->te + 1)) p->te++; p->te++; } - if (p->te != p->fe) + if ((p->te != p->fe) && (*p->te)) p->te++; break; @@ -467,7 +602,7 @@ static void _get_token(struct parser *p) case '8': case '9': p->te++; - while (p->te != p->fe) { + while ((p->te != p->fe) && (*p->te)) { if (*p->te == '.') { if (p->t == TOK_FLOAT) break; @@ -480,7 +615,7 @@ static void _get_token(struct parser *p) default: p->t = TOK_IDENTIFIER; - while ((p->te != p->fe) && !isspace(*p->te) && + while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) && (*p->te != '#') && (*p->te != '=')) p->te++; break; @@ -489,15 +624,15 @@ static void _get_token(struct parser *p) static void _eat_space(struct parser *p) { - while (p->tb != p->fe) { + while ((p->tb != p->fe) && (*p->tb)) { if (*p->te == '#') { - while ((p->te != p->fe) && (*p->te != '\n')) + while ((p->te != p->fe) && (*p->te) && (*p->te != '\n')) p->te++; p->line++; } else if (isspace(*p->te)) { - while ((p->te != p->fe) && isspace(*p->te)) { + while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) { if (*p->te == '\n') p->line++; p->te++; @@ -674,7 +809,7 @@ int find_config_bool(struct config_node *cn, const char *path, } int get_config_uint32(struct config_node *cn, const char *path, - char sep, uint32_t * result) + char sep, uint32_t *result) { struct config_node *n; @@ -688,7 +823,7 @@ int get_config_uint32(struct config_node *cn, const char *path, } int get_config_uint64(struct config_node *cn, const char *path, - char sep, uint64_t * result) + char sep, uint64_t *result) { struct config_node *n; @@ -715,4 +850,3 @@ int get_config_str(struct config_node *cn, const char *path, *result = n->v->v.str; return 1; } - diff --git a/lib/config/config.h b/lib/config/config.h index c8d70463e..f1ceda0ad 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -8,39 +8,47 @@ #define _LVM_CONFIG_H #include +#include enum { - CFG_STRING, - CFG_FLOAT, - CFG_INT, + CFG_STRING, + CFG_FLOAT, + CFG_INT, CFG_EMPTY_ARRAY }; struct config_value { - int type; - union { - int i; - float r; - char *str; - } v; - struct config_value *next; /* for arrays */ + int type; + union { + int i; + float r; + char *str; + } v; + struct config_value *next; /* for arrays */ }; struct config_node { - char *key; - struct config_node *sib, *child; - struct config_value *v; + char *key; + struct config_node *sib, *child; + struct config_value *v; }; -struct config_file { - struct config_node *root; +struct config_tree { + struct config_node *root; }; -struct config_file *create_config_file(void); -void destroy_config_file(struct config_file *cf); +struct config_tree *create_config_tree(void); +void destroy_config_tree(struct config_tree *cf); -int read_config(struct config_file *cf, const char *file); -int write_config(struct config_file *cf, const char *file); +typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size); + +int read_config_fd(struct config_tree *cf, int fd, const char *file, + off_t offset, uint32_t size, off_t offset2, uint32_t size2, + checksum_fn_t checksum_fn, uint32_t checksum); + +int read_config_file(struct config_tree *cf, const char *file); +int write_config_file(struct config_tree *cf, const char *file); +int reload_config_file(struct config_tree **cf); struct config_node *find_config_node(struct config_node *cn, const char *path, char seperator); @@ -59,9 +67,7 @@ float find_config_float(struct config_node *cn, const char *path, * off), (true, false). */ int find_config_bool(struct config_node *cn, const char *path, - char sep, int fail); - - + char sep, int fail); int get_config_uint32(struct config_node *cn, const char *path, char sep, uint32_t *result); @@ -73,4 +79,3 @@ int get_config_str(struct config_node *cn, const char *path, char sep, char **result); #endif - diff --git a/lib/config/defaults.h b/lib/config/defaults.h index b12b5c651..eeaf647a5 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -7,9 +7,6 @@ #ifndef _LVM_DEFAULTS_H #define _LVM_DEFAULTS_H - -#define DEFAULT_SYS_DIR "/etc/lvm" - #define DEFAULT_ARCHIVE_ENABLED 1 #define DEFAULT_BACKUP_ENABLED 1 @@ -19,22 +16,42 @@ #define DEFAULT_ARCHIVE_DAYS 30 #define DEFAULT_ARCHIVE_NUMBER 10 +#define DEFAULT_SYS_DIR "/etc/lvm" #define DEFAULT_DEV_DIR "/dev" #define DEFAULT_PROC_DIR "/proc" #define DEFAULT_LOCK_DIR "/var/lock/lvm" +#define DEFAULT_LOCKING_LIB "lvm2_locking.so" #define DEFAULT_UMASK 0077 -#define DEFAULT_FORMAT "lvm1" +#ifdef LVM1_SUPPORT + #define DEFAULT_FORMAT "lvm1" +#else + #define DEFAULT_FORMAT "lvm2" +#endif + +#define DEFAULT_PVMETADATASIZE 255 +#define DEFAULT_PVMETADATACOPIES 1 +#define DEFAULT_LABELSECTOR 1 #define DEFAULT_MSG_PREFIX " " - #define DEFAULT_CMD_NAME 0 +#define DEFAULT_OVERWRITE 0 + +#ifndef DEFAULT_LOG_FACILITY + #define DEFAULT_LOG_FACILITY LOG_USER +#endif + +#define DEFAULT_SYSLOG 1 +#define DEFAULT_VERBOSE 0 +#define DEFAULT_LOGLEVEL 0 +#define DEFAULT_INDENT 1 + +#define DEFAULT_ACTIVATION 1 #ifdef READLINE_SUPPORT #define DEFAULT_MAX_HISTORY 100 #endif - -#endif /* _LVM_DEFAULTS_H */ +#endif /* _LVM_DEFAULTS_H */ diff --git a/lib/datastruct/bitset.c b/lib/datastruct/bitset.c index 3d1a28755..050eb78a3 100644 --- a/lib/datastruct/bitset.c +++ b/lib/datastruct/bitset.c @@ -4,15 +4,13 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "bitset.h" -#include "dbg_malloc.h" - -#include /* FIXME: calculate this. */ #define INT_SHIFT 5 -bitset_t bitset_create(struct pool * mem, unsigned num_bits) +bitset_t bitset_create(struct pool *mem, unsigned num_bits) { int n = (num_bits / BITS_PER_INT) + 2; int size = sizeof(int) * n; diff --git a/lib/datastruct/bitset.h b/lib/datastruct/bitset.h index 93f1c130b..8d31ad2b6 100644 --- a/lib/datastruct/bitset.h +++ b/lib/datastruct/bitset.h @@ -11,8 +11,6 @@ #include "pool.h" #include -#include - typedef uint32_t *bitset_t; diff --git a/lib/datastruct/btree.c b/lib/datastruct/btree.c index 8e880628c..dda010c30 100644 --- a/lib/datastruct/btree.c +++ b/lib/datastruct/btree.c @@ -4,8 +4,8 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "btree.h" -#include "log.h" struct node { uint32_t key; diff --git a/lib/datastruct/hash.c b/lib/datastruct/hash.c index 3277f1578..a50305a21 100644 --- a/lib/datastruct/hash.c +++ b/lib/datastruct/hash.c @@ -4,9 +4,8 @@ * This file is released under the LGPL. */ -#include "dbg_malloc.h" +#include "lib.h" #include "hash.h" -#include "log.h" struct hash_node { struct hash_node *next; @@ -26,26 +25,26 @@ static unsigned char _nums[] = { 87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65, 49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28, 12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172, - 144, + 144, 176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254, 178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54, - 221, + 221, 102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93, 166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189, 121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185, - 194, + 194, 193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232, - 139, + 139, 6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112, 84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196, - 43, + 43, 249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231, - 71, + 71, 230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47, - 109, + 109, 44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184, 163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120, - 209 + 209 }; static struct hash_node *_create_node(const char *str) @@ -60,10 +59,10 @@ static struct hash_node *_create_node(const char *str) return n; } -static unsigned _hash(const char *str) +static unsigned _hash(const char *str, int len) { unsigned long int h = 0, g; - while (*str) { + while (*str && len--) { h <<= 4; h += _nums[(int) *str++]; g = h & ((unsigned long) 0xf << 16u); @@ -126,18 +125,30 @@ void hash_destroy(struct hash_table *t) dbg_free(t); } -static inline struct hash_node **_find(struct hash_table *t, const char *key) +static inline struct hash_node **_find_fixed(struct hash_table *t, + const char *key, uint32_t len) { - unsigned h = _hash(key) & (t->num_slots - 1); + unsigned h = _hash(key, len) & (t->num_slots - 1); struct hash_node **c; for (c = &t->slots[h]; *c; c = &((*c)->next)) - if (!strcmp(key, (*c)->key)) + if (!strncmp(key, (*c)->key, len)) break; return c; } +static inline struct hash_node **_find(struct hash_table *t, const char *key) +{ + return _find_fixed(t, key, strlen(key)); +} + +void *hash_lookup_fixed(struct hash_table *t, const char *key, uint32_t len) +{ + struct hash_node **c = _find_fixed(t, key, len); + return *c ? (*c)->data : 0; +} + void *hash_lookup(struct hash_table *t, const char *key) { struct hash_node **c = _find(t, key); @@ -227,6 +238,6 @@ struct hash_node *hash_get_first(struct hash_table *t) struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n) { - unsigned int h = _hash(n->key) & (t->num_slots - 1); + unsigned int h = _hash(n->key, strlen(n->key)) & (t->num_slots - 1); return n->next ? n->next : _next_slot(t, h + 1); } diff --git a/lib/datastruct/hash.h b/lib/datastruct/hash.h index 01de96ba5..c26e581de 100644 --- a/lib/datastruct/hash.h +++ b/lib/datastruct/hash.h @@ -7,6 +7,8 @@ #ifndef _LVM_HASH_H #define _LVM_HASH_H +#include "lvm-types.h" + struct hash_table; struct hash_node; @@ -17,6 +19,7 @@ void hash_destroy(struct hash_table *t); void hash_wipe(struct hash_table *t); void *hash_lookup(struct hash_table *t, const char *key); +void *hash_lookup_fixed(struct hash_table *t, const char *key, uint32_t len); int hash_insert(struct hash_table *t, const char *key, void *data); void hash_remove(struct hash_table *t, const char *key); diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index fcc428051..e6d87ef7e 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -4,17 +4,14 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "dev-cache.h" -#include "log.h" #include "pool.h" #include "hash.h" #include "list.h" #include "lvm-types.h" #include "btree.h" -#include "dbg_malloc.h" -#include -#include #include #include #include @@ -63,6 +60,8 @@ static struct device *_create_dev(dev_t d) list_init(&dev->aliases); dev->dev = d; dev->fd = -1; + dev->flags = 0; + memset(dev->pvid, 0, sizeof(dev->pvid)); return dev; } @@ -229,6 +228,21 @@ static void _full_scan(void) _cache.has_scanned = 1; } +int dev_cache_has_scanned(void) +{ + return _cache.has_scanned; +} + +void dev_cache_scan(int do_scan) +{ + if (!do_scan) + _cache.has_scanned = 1; + else { + _cache.has_scanned = 0; + _full_scan(); + } +} + int dev_cache_init(void) { _cache.names = NULL; diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h index d28479b7e..15aaf88ba 100644 --- a/lib/device/dev-cache.h +++ b/lib/device/dev-cache.h @@ -27,6 +27,10 @@ struct dev_filter { int dev_cache_init(void); void dev_cache_exit(void); +/* Trigger(1) or avoid(0) a scan */ +void dev_cache_scan(int do_scan); +int dev_cache_has_scanned(void); + int dev_cache_add_dir(const char *path); struct device *dev_cache_get(const char *name, struct dev_filter *f); diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c index 4be596fb6..babf86217 100644 --- a/lib/device/dev-io.c +++ b/lib/device/dev-io.c @@ -4,18 +4,18 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "device.h" #include "lvm-types.h" -#include "log.h" +#include "metadata.h" -#include #include #include #include #include #include // UGH!!! for BLKSSZGET -int dev_get_size(struct device *dev, uint64_t * size) +int dev_get_size(struct device *dev, uint64_t *size) { int fd; long s; @@ -39,7 +39,7 @@ int dev_get_size(struct device *dev, uint64_t * size) return 1; } -int dev_get_sectsize(struct device *dev, uint32_t * size) +int dev_get_sectsize(struct device *dev, uint32_t *size) { int fd; int s; @@ -62,7 +62,6 @@ int dev_get_sectsize(struct device *dev, uint32_t * size) return 1; } - static void _flush(int fd) { ioctl(fd, BLKFLSBUF, 0); @@ -96,6 +95,7 @@ int dev_open(struct device *dev, int flags) if ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev)) { log_error("%s: fstat failed: Has device name changed?", name); dev_close(dev); + dev->fd = -1; return 0; } _flush(dev->fd); @@ -126,7 +126,7 @@ int dev_close(struct device *dev) /* * FIXME: factor common code out. */ -int _read(int fd, void *buf, size_t count) +int raw_read(int fd, void *buf, size_t count) { size_t n = 0; int tot = 0; @@ -162,12 +162,12 @@ int64_t dev_read(struct device * dev, uint64_t offset, return 0; } - return _read(fd, buffer, len); + return raw_read(fd, buffer, len); } int _write(int fd, const void *buf, size_t count) { - size_t n = 0; + ssize_t n = 0; int tot = 0; /* Skip all writes */ @@ -214,24 +214,34 @@ int dev_zero(struct device *dev, uint64_t offset, int64_t len) { int64_t r, s; char buffer[4096]; - const char *name = dev_name(dev); - int fd = dev->fd; + int already_open; - if (fd < 0) { - log_error("Attempt to zero part of an unopened device %s", - name); + already_open = dev_is_open(dev); + + if (!already_open && !dev_open(dev, O_RDWR)) { + stack; return 0; } - if (lseek(fd, offset, SEEK_SET) < 0) { - log_sys_error("lseek", name); + if (lseek(dev->fd, offset, SEEK_SET) < 0) { + log_sys_error("lseek", dev_name(dev)); + if (!already_open && !dev_close(dev)) + stack; return 0; } + if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE)) + log_debug("Wiping %s at %" PRIu64 " length %" PRId64, + dev_name(dev), offset, len); + else + log_debug("Wiping %s at sector %" PRIu64 " length %" PRId64 + " sectors", dev_name(dev), offset >> SECTOR_SHIFT, + len >> SECTOR_SHIFT); + memset(buffer, 0, sizeof(buffer)); while (1) { s = len > sizeof(buffer) ? sizeof(buffer) : len; - r = _write(fd, buffer, s); + r = _write(dev->fd, buffer, s); if (r <= 0) break; @@ -245,6 +255,9 @@ int dev_zero(struct device *dev, uint64_t offset, int64_t len) dev->flags |= DEV_ACCESSED_W; + if (!already_open && !dev_close(dev)) + stack; + /* FIXME: Always display error */ return (len == 0); } diff --git a/lib/device/device.c b/lib/device/device.c index 12c5e2264..938974c8b 100644 --- a/lib/device/device.c +++ b/lib/device/device.c @@ -17,6 +17,7 @@ * MA 02111-1307, USA */ +#if 0 #include #include #include @@ -24,9 +25,12 @@ #include #include #include -#include + #include #include +#include +#include +#include #include "dbg_malloc.h" #include "log.h" @@ -34,11 +38,6 @@ #include "metadata.h" #include "device.h" -#include -#include -#include - -#if 0 int _get_partition_type(struct dev_filter *filter, struct device *d); #define MINOR_PART(dm, d) (MINOR((d)->dev) % dev_max_partitions(dm, (d)->dev)) diff --git a/lib/device/device.h b/lib/device/device.h index 66846bc3e..060bc6500 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -9,6 +9,7 @@ #include "lvm-types.h" #include "list.h" +#include "uuid.h" #define DEV_ACCESSED_W 0x00000001 /* Device written to? */ @@ -17,12 +18,14 @@ * pointer comparisons are valid. */ struct device { - struct list aliases; /* struct str_list from lvm-types.h */ + struct list aliases; /* struct str_list from lvm-types.h */ dev_t dev; /* private */ int fd; uint32_t flags; + + char pvid[ID_LEN + 1]; }; struct device_list { @@ -30,6 +33,12 @@ struct device_list { struct device *dev; }; +struct device_area { + struct device *dev; + uint64_t start; /* Bytes */ + uint64_t size; /* Bytes */ +}; + /* * All io should use these routines. */ @@ -39,24 +48,36 @@ int dev_get_sectsize(struct device *dev, uint32_t *size); int dev_open(struct device *dev, int flags); int dev_close(struct device *dev); +static inline int dev_fd(struct device *dev) +{ + return dev->fd; +} + +int raw_read(int fd, void *buf, size_t count); + int64_t dev_read(struct device *dev, uint64_t offset, int64_t len, void *buffer); int64_t dev_write(struct device *dev, uint64_t offset, int64_t len, void *buffer); int dev_zero(struct device *dev, uint64_t offset, int64_t len); - -static inline const char *dev_name(struct device *dev) { +static inline const char *dev_name(struct device *dev) +{ return (dev) ? list_item(dev->aliases.n, struct str_list)->str : - "unknown device"; + "unknown device"; } /* Return a valid device name from the alias list; NULL otherwise */ const char *dev_name_confirmed(struct device *dev); -static inline int is_lvm_partition(const char *name) { +static inline int is_lvm_partition(const char *name) +{ return 1; } -#endif +static inline int dev_is_open(struct device *dev) +{ + return dev->fd >= 0 ? 1 : 0; +} +#endif diff --git a/lib/display/display.c b/lib/display/display.c index 67d5495b0..bb39510f3 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -18,19 +18,83 @@ * */ +#include "lib.h" #include "metadata.h" -#include "dbg_malloc.h" -#include "log.h" #include "display.h" #include "activate.h" -#include "uuid.h" #include "toolcontext.h" -#include -#include - #define SIZE_BUF 128 +static struct { + alloc_policy_t alloc; + const char *str; +} _policies[] = { + { + ALLOC_NEXT_FREE, "next free"}, { + ALLOC_CONTIGUOUS, "contiguous"}, { + ALLOC_DEFAULT, "next free (default)"} +}; + +static struct { + segment_type_t segtype; + const char *str; +} _segtypes[] = { + { + SEG_STRIPED, "striped"}, { + SEG_MIRROR, "mirror"}, { + SEG_SNAPSHOT, "snapshot"} +}; + +static int _num_policies = sizeof(_policies) / sizeof(*_policies); +static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes); + +const char *get_alloc_string(alloc_policy_t alloc) +{ + int i; + + for (i = 0; i < _num_policies; i++) + if (_policies[i].alloc == alloc) + return _policies[i].str; + + return NULL; +} + +const char *get_segtype_string(segment_type_t segtype) +{ + int i; + + for (i = 0; i < _num_segtypes; i++) + if (_segtypes[i].segtype == segtype) + return _segtypes[i].str; + + return NULL; +} + +alloc_policy_t get_alloc_from_string(const char *str) +{ + int i; + + for (i = 0; i < _num_policies; i++) + if (!strcmp(_policies[i].str, str)) + return _policies[i].alloc; + + log_error("Unrecognised allocation policy - using default"); + return ALLOC_DEFAULT; +} + +segment_type_t get_segtype_from_string(const char *str) +{ + int i; + + for (i = 0; i < _num_segtypes; i++) + if (!strcmp(_segtypes[i].str, str)) + return _segtypes[i].segtype; + + log_error("Unrecognised segment type - using default (striped)"); + return SEG_STRIPED; +} + char *display_size(uint64_t size, size_len_t sl) { int s; @@ -89,7 +153,8 @@ void pvdisplay_colons(struct physical_volume *pv) return; } -void pvdisplay_full(struct physical_volume *pv) +/* FIXME Include label fields */ +void pvdisplay_full(struct physical_volume *pv, void *handle) { char uuid[64]; char *size, *size1; /*, *size2; */ @@ -104,18 +169,6 @@ void pvdisplay_full(struct physical_volume *pv) return; } - /* Compat */ - if(!pv->pe_size) { - size = display_size((uint64_t) pv->size / 2, SIZE_SHORT); - log_print("\"%s\" is a new physical volume of %s", dev_name(pv->dev), size); - dbg_free(size); - return; - } - - set_cmd_name(""); - init_msg_prefix(""); - -/****** FIXME Do we really need this conditional here? */ log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW "); log_print("PV Name %s", dev_name(pv->dev)); log_print("VG Name %s%s", pv->vg_name, @@ -126,14 +179,12 @@ void pvdisplay_full(struct physical_volume *pv) size1 = display_size((pv->size - pv->pe_count * pv->pe_size) / 2, SIZE_SHORT); -/******** FIXME display LVM on-disk data size - static for now... +/******** FIXME display LVM on-disk data size size2 = display_size(pv->size / 2, SIZE_SHORT); ********/ - log_print("PV Size %s [%llu secs]" " / not " - "usable %s [LVM: %s]", - size, (uint64_t) pv->size, size1, "151 KB"); - /* , size2); */ + log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */ + size, size1); /* , size2); */ dbg_free(size1); /* dbg_free(size2); */ @@ -141,12 +192,9 @@ void pvdisplay_full(struct physical_volume *pv) log_print("PV Size %s", size); dbg_free(size); -/******** FIXME anytime this *isn't* available? */ - log_print("PV Status available"); - -/*********FIXME Anything use this? - log_print("PV# %u", pv->pv_number); -**********/ + /* PV number not part of LVM2 design + log_print("PV# %u", pv->pv_number); + */ pe_free = pv->pe_count - pv->pe_alloc_count; if (pv->pe_count && (pv->status & ALLOCATABLE_PV)) @@ -155,18 +203,13 @@ void pvdisplay_full(struct physical_volume *pv) else log_print("Allocatable NO"); -/*********FIXME Erm...where is this stored? - log_print("Cur LV %u", vg->lv_count); -*/ + /* LV count is no longer available when displaying PV + log_print("Cur LV %u", vg->lv_count); + */ log_print("PE Size (KByte) %" PRIu64, pv->pe_size / 2); log_print("Total PE %u", pv->pe_count); log_print("Free PE %" PRIu64, pe_free); log_print("Allocated PE %u", pv->pe_alloc_count); - -#ifdef LVM_FUTURE - printf("Stale PE %u", pv->pe_stale); -#endif - log_print("PV UUID %s", *uuid ? uuid : "none"); log_print(" "); @@ -174,7 +217,7 @@ void pvdisplay_full(struct physical_volume *pv) } int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, - struct physical_volume *pv) + struct physical_volume *pv, void *handle) { if (!pv) return 0; @@ -190,8 +233,6 @@ int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, return 0; } - - void lvdisplay_colons(struct logical_volume *lv) { int inkernel; @@ -207,59 +248,21 @@ void lvdisplay_colons(struct logical_volume *lv) /* FIXME lv->lv_number, */ inkernel ? info.open_count : 0, lv->size, lv->le_count, /* FIXME Add num allocated to struct! lv->lv_allocated_le, */ - ((lv->alloc == ALLOC_STRICT) + - (lv->alloc == ALLOC_CONTIGUOUS) * 2), lv->read_ahead, + (lv->alloc == ALLOC_CONTIGUOUS ? 2 : 0), lv->read_ahead, inkernel ? info.major : -1, inkernel ? info.minor : -1); return; } - -static struct { - alloc_policy_t alloc; - const char *str; -} _policies[] = { - {ALLOC_NEXT_FREE, "next free"}, - {ALLOC_STRICT, "strict"}, - {ALLOC_CONTIGUOUS, "contiguous"} -}; - -static int _num_policies = sizeof(_policies) / sizeof(*_policies); - -const char *get_alloc_string(alloc_policy_t alloc) -{ - int i; - - for (i = 0; i < _num_policies; i++) - if (_policies[i].alloc == alloc) - return _policies[i].str; - - return NULL; -} - -alloc_policy_t get_alloc_from_string(const char *str) -{ - int i; - - for (i = 0; i < _num_policies; i++) - if (!strcmp(_policies[i].str, str)) - return _policies[i].alloc; - - log_warn("Unknown allocation policy, defaulting to next free"); - return ALLOC_NEXT_FREE; -} - -int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv) +int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv, + void *handle) { char *size; struct dm_info info; - int inkernel; + int inkernel, snap_active; char uuid[64]; - struct snapshot *snap; - struct stripe_segment *seg; - struct list *lvseg; - struct logical_volume *origin; - float snap_percent; - int snap_active; + struct snapshot *snap = NULL; + struct list *slh, *snaplist; + float snap_percent; /* fused, fsize; */ if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) { stack; @@ -268,145 +271,93 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv) inkernel = lv_info(lv, &info) && info.exists; - set_cmd_name(""); - init_msg_prefix(""); - log_print("--- Logical volume ---"); log_print("LV Name %s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name); log_print("VG Name %s", lv->vg->name); -/* Not in LVM1 format log_print("LV UUID %s", uuid); -**/ + log_print("LV Write Access %s", (lv->status & LVM_WRITE) ? "read/write" : "read only"); - /* see if this LV is an origin for a snapshot */ - if ((snap = find_origin(lv))) { - struct list *slh, *snaplist = find_snapshots(lv); - + if (lv_is_origin(lv)) { log_print("LV snapshot status source of"); + + snaplist = find_snapshots(lv); list_iterate(slh, snaplist) { snap = list_item(slh, struct snapshot_list)->snapshot; snap_active = lv_snapshot_percent(snap->cow, &snap_percent); log_print(" %s%s/%s [%s]", - lv->vg->cmd->dev_dir, lv->vg->name, - snap->cow->name, - (snap_active > 0) ? "active" : "INACTIVE"); + lv->vg->cmd->dev_dir, lv->vg->name, + snap->cow->name, + (snap_active > 0) ? "active" : "INACTIVE"); } - /* reset so we don't try to use this to display other snapshot - * related information. */ - snap = NULL; - snap_active = 0; - } - /* Check to see if this LV is a COW target for a snapshot */ - else if ((snap = find_cow(lv))) { + } else if ((snap = find_cow(lv))) { snap_active = lv_snapshot_percent(lv, &snap_percent); log_print("LV snapshot status %s destination for %s%s/%s", - (snap_active > 0) ? "active" : "INACTIVE", + (snap_active > 0) ? "active" : "INACTIVE", lv->vg->cmd->dev_dir, lv->vg->name, snap->origin->name); } - if (inkernel && info.suspended) log_print("LV Status suspended"); else log_print("LV Status %savailable", - !inkernel || (snap && (snap_active < 1)) - ? "NOT " : ""); + inkernel ? "" : "NOT "); -/********* FIXME lv_number - not sure that we're going to bother with this +/********* FIXME lv_number log_print("LV # %u", lv->lv_number + 1); ************/ -/* LVM1 lists the number of LVs open in this field, therefore, so do we. */ - log_print("# open %u", lvs_in_vg_opened(lv->vg)); - -/* We're not going to use this count ATM, 'cause it's not what LVM1 does if (inkernel) log_print("# open %u", info.open_count); -*/ -/******** -#ifdef LVM_FUTURE - printf("Mirror copies %u\n", lv->lv_mirror_copies); - printf("Consistency recovery "); - if (lv->lv_recovery | LV_BADBLOCK_ON) - printf("bad blocks\n"); - else - printf("none\n"); - printf("Schedule %u\n", lv->lv_schedule); -#endif -********/ - if(snap) - origin = snap->origin; - else - origin = lv; - - size = display_size(origin->size / 2, SIZE_SHORT); + size = display_size(snap ? snap->origin->size / 2 : lv->size / 2, + SIZE_SHORT); log_print("LV Size %s", size); dbg_free(size); - log_print("Current LE %u", origin->le_count); + log_print("Current LE %u", + snap ? snap->origin->le_count : lv->le_count); -/********** FIXME allocation - is there anytime the allocated LEs will not - * equal the current LEs? */ - log_print("Allocated LE %u", origin->le_count); -/**********/ +/********** FIXME allocation + log_print("Allocated LE %u", lv->allocated_le); +**********/ - - list_iterate(lvseg, &lv->segments) { - seg = list_item(lvseg, struct stripe_segment); - if(seg->stripes > 1) { - log_print("Stripes %u", seg->stripes); - log_print("Stripe size (KByte) %u", - seg->stripe_size/2); - } - /* only want the first segment for LVM1 format output */ - break; - } - - if(snap) { - float fused, fsize; - if(snap_percent == -1) - snap_percent=100; - - size = display_size(snap->chunk_size / 2, SIZE_SHORT); - log_print("snapshot chunk size %s", size); - dbg_free(size); - - size = display_size(lv->size / 2, SIZE_SHORT); - sscanf(size, "%f", &fsize); - fused = fsize * ( snap_percent / 100 ); - log_print("Allocated to snapshot %2.2f%% [%2.2f/%s]", - snap_percent, fused, size); - dbg_free(size); - - /* FIXME: Think this'll make them wonder?? */ - log_print("Allocated to COW-table %s", "00.01 KB"); - } - -/** Not in LVM1 format output ** log_print("Segments %u", list_size(&lv->segments)); -***/ /********* FIXME Stripes & stripesize for each segment log_print("Stripe size (KByte) %u", lv->stripesize / 2); ***********/ -/************** -#ifdef LVM_FUTURE - printf("Bad block "); - if (lv->lv_badblock == LV_BADBLOCK_ON) - printf("on\n"); - else - printf("off\n"); -#endif -***************/ + if (snap) { + if (snap_percent == -1) + snap_percent = 100; + + size = display_size(snap->chunk_size / 2, SIZE_SHORT); + log_print("Snapshot chunk size %s", size); + dbg_free(size); + +/* + size = display_size(lv->size / 2, SIZE_SHORT); + sscanf(size, "%f", &fsize); + fused = fsize * snap_percent / 100; +*/ + log_print("Allocated to snapshot %.2f%% ", /* [%.2f/%s]", */ + snap_percent); /*, fused, size); */ + /* dbg_free(size); */ + } + +/********** FIXME Snapshot + size = ??? + log_print("Allocated to COW-table %s", size); + dbg_free(size); + } +******************/ log_print("Allocation %s", get_alloc_string(lv->alloc)); log_print("Read ahead sectors %u", lv->read_ahead); @@ -414,16 +365,6 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv) if (lv->status & FIXED_MINOR) log_print("Persistent minor %d", lv->minor); -/**************** -#ifdef LVM_FUTURE - printf("IO Timeout (seconds) "); - if (lv->lv_io_timeout == 0) - printf("default\n\n"); - else - printf("%lu\n\n", lv->lv_io_timeout); -#endif -*************/ - if (inkernel) log_print("Block device %d:%d", info.major, info.minor); @@ -433,15 +374,15 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv) return 0; } -void _display_stripe(struct stripe_segment *seg, int s, const char *pre) +void _display_stripe(struct lv_segment *seg, int s, const char *pre) { uint32_t len = seg->len / seg->stripes; - log_print("%sphysical volume\t%s", pre, + log_print("%sPhysical volume\t%s", pre, seg->area[s].pv ? dev_name(seg->area[s].pv->dev) : "Missing"); if (seg->area[s].pv) - log_print("%sphysical extents\t%d to %d", pre, + log_print("%sPhysical extents\t%d to %d", pre, seg->area[s].pe, seg->area[s].pe + len - 1); } @@ -449,29 +390,38 @@ int lvdisplay_segments(struct logical_volume *lv) { int s; struct list *segh; - struct stripe_segment *seg; + struct lv_segment *seg; log_print("--- Segments ---"); list_iterate(segh, &lv->segments) { - seg = list_item(segh, struct stripe_segment); + seg = list_item(segh, struct lv_segment); - log_print("logical extent %d to %d:", + log_print("Logical extent %d to %d:", seg->le, seg->le + seg->len - 1); - if (seg->stripes == 1) - _display_stripe(seg, 0, " "); + log_print(" Type\t\t%s", get_segtype_string(seg->type)); - else { - log_print(" stripes\t\t%d", seg->stripes); - log_print(" stripe size\t\t%d", seg->stripe_size); + switch (seg->type) { + case SEG_STRIPED: + if (seg->stripes == 1) + _display_stripe(seg, 0, " "); + else { + log_print(" Stripes\t\t%d", seg->stripes); + log_print(" Stripe size\t\t%d", + seg->stripe_size); - for (s = 0; s < seg->stripes; s++) { - log_print(" stripe %d:", s); - _display_stripe(seg, s, " "); + for (s = 0; s < seg->stripes; s++) { + log_print(" Stripe %d:", s); + _display_stripe(seg, s, " "); + } } + log_print(" "); + break; + case SEG_SNAPSHOT: + case SEG_MIRROR: + ; } - log_print(" "); } log_print(" "); @@ -486,29 +436,24 @@ void vgdisplay_extents(struct volume_group *vg) void vgdisplay_full(struct volume_group *vg) { uint32_t access; + uint32_t active_pvs; char *s1; char uuid[64]; - uint32_t active_pvs; - struct list *pvlist; - set_cmd_name(""); - init_msg_prefix(""); - - /* get the number of active PVs */ - if(vg->status & PARTIAL_VG) { - active_pvs=0; - list_iterate(pvlist, &(vg->pvs)) { - active_pvs++; - } - } + if (vg->status & PARTIAL_VG) + active_pvs = list_size(&vg->pvs); else - active_pvs=vg->pv_count; + active_pvs = vg->pv_count; log_print("--- Volume group ---"); log_print("VG Name %s", vg->name); -/****** Not in LVM1 output, so we aren't outputing it here: log_print("System ID %s", vg->system_id); -*******/ + log_print("Format %s", vg->fid->fmt->name); + if (vg->fid->fmt->features & FMT_MDAS) { + log_print("Metadata Areas %d", + list_size(&vg->fid->metadata_areas)); + log_print("Metadata Sequence No %d", vg->seqno); + } access = vg->status & (LVM_READ | LVM_WRITE); log_print("VG Access %s%s%s%s", access == (LVM_READ | LVM_WRITE) ? "read/write" : "", @@ -516,28 +461,30 @@ void vgdisplay_full(struct volume_group *vg) access == LVM_WRITE ? "write" : "", access == 0 ? "error" : ""); log_print("VG Status %s%sresizable", - vg->status & EXPORTED_VG ? "exported/" : "available/", + vg->status & EXPORTED_VG ? "exported/" : "", vg->status & RESIZEABLE_VG ? "" : "NOT "); + /* vg number not part of LVM2 design + log_print ("VG # %u\n", vg->vg_number); + */ if (vg->status & CLUSTERED) { log_print("Clustered yes"); log_print("Shared %s", vg->status & SHARED ? "yes" : "no"); } -/****** FIXME VG # - we aren't implementing this because people should - * use the UUID for this anyway - log_print("VG # %u", vg->vg_number); -*******/ log_print("MAX LV %u", vg->max_lv); log_print("Cur LV %u", vg->lv_count); - log_print("Open LV %u", lvs_in_vg_opened(vg)); - log_print("MAX LV Size 256 TB"); + log_print("Open LV %u", lvs_in_vg_opened(vg)); +/****** FIXME Max LV Size + log_print ( "MAX LV Size %s", + ( s1 = display_size ( LVM_LV_SIZE_MAX(vg) / 2, SIZE_SHORT))); + free ( s1); +*********/ log_print("Max PV %u", vg->max_pv); log_print("Cur PV %u", vg->pv_count); - log_print("Act PV %u", active_pvs); + log_print("Act PV %u", active_pvs); - s1 = - display_size((uint64_t) vg->extent_count * (vg->extent_size / 2), - SIZE_SHORT); + s1 = display_size((uint64_t) vg->extent_count * (vg->extent_size / 2), + SIZE_SHORT); log_print("VG Size %s", s1); dbg_free(s1); @@ -554,9 +501,8 @@ void vgdisplay_full(struct volume_group *vg) vg->extent_count - vg->free_count, s1); dbg_free(s1); - s1 = - display_size((uint64_t) vg->free_count * (vg->extent_size / 2), - SIZE_SHORT); + s1 = display_size((uint64_t) vg->free_count * (vg->extent_size / 2), + SIZE_SHORT); log_print("Free PE / Size %u / %s", vg->free_count, s1); dbg_free(s1); @@ -580,9 +526,8 @@ void vgdisplay_short(struct volume_group *vg) { char *s1, *s2, *s3; s1 = display_size(vg->extent_count * vg->extent_size / 2, SIZE_SHORT); - s2 = - display_size((vg->extent_count - vg->free_count) * vg->extent_size / - 2, SIZE_SHORT); + s2 = display_size((vg->extent_count - + vg->free_count) * vg->extent_size / 2, SIZE_SHORT); s3 = display_size(vg->free_count * vg->extent_size / 2, SIZE_SHORT); log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name, /********* FIXME if "open" print "/used" else print "/idle"??? ******/ diff --git a/lib/display/display.h b/lib/display/display.h index 871dbbaba..3b59a5ee6 100644 --- a/lib/display/display.h +++ b/lib/display/display.h @@ -25,19 +25,21 @@ #include -typedef enum {SIZE_LONG=0, SIZE_SHORT=1} size_len_t; +typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1 } size_len_t; /* Specify size in KB */ char *display_size(uint64_t size, size_len_t sl); char *display_uuid(char *uuidstr); void pvdisplay_colons(struct physical_volume *pv); -void pvdisplay_full(struct physical_volume *pv); -int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv); +void pvdisplay_full(struct physical_volume *pv, void *handle); +int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, + struct physical_volume *pv, void *handle); void lvdisplay_colons(struct logical_volume *lv); int lvdisplay_segments(struct logical_volume *lv); -int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv); +int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv, + void *handle); void vgdisplay_extents(struct volume_group *vg); void vgdisplay_full(struct volume_group *vg); @@ -45,14 +47,15 @@ void vgdisplay_colons(struct volume_group *vg); void vgdisplay_short(struct volume_group *vg); /* - * Retrieve a text description of the allocation policy. Only - * extern because it's used by lvscan. + * Allocation policy display conversion routines. */ const char *get_alloc_string(alloc_policy_t alloc); - -/* - * FIXME: put this somewhere more sensible. - */ alloc_policy_t get_alloc_from_string(const char *str); +/* + * Segment type display conversion routines. + */ +segment_type_t get_segtype_from_string(const char *str); +const char *get_segtype_string(segment_type_t segtype); + #endif diff --git a/lib/filters/filter-composite.c b/lib/filters/filter-composite.c index b388c1690..8c96ba8d3 100644 --- a/lib/filters/filter-composite.c +++ b/lib/filters/filter-composite.c @@ -4,9 +4,8 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "filter-composite.h" -#include "dbg_malloc.h" -#include "log.h" #include diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c index acc1a295d..b5f7ca89d 100644 --- a/lib/filters/filter-persistent.c +++ b/lib/filters/filter-persistent.c @@ -4,14 +4,12 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "config.h" #include "dev-cache.h" #include "hash.h" -#include "dbg_malloc.h" -#include "log.h" #include "filter-persistent.h" -#include #include #include #include @@ -43,10 +41,13 @@ int persistent_filter_wipe(struct dev_filter *f) struct pfilter *pf = (struct pfilter *) f->private; hash_wipe(pf->devices); + /* Trigger complete device scan */ + dev_cache_scan(1); + return 1; } -static int _read_array(struct pfilter *pf, struct config_file *cf, +static int _read_array(struct pfilter *pf, struct config_tree *cf, const char *path, void *data) { struct config_node *cn; @@ -72,6 +73,8 @@ static int _read_array(struct pfilter *pf, struct config_file *cf, if (!hash_insert(pf->devices, cv->v.str, data)) log_verbose("Couldn't add '%s' to filter ... ignoring", cv->v.str); + /* Populate dev_cache ourselves */ + dev_cache_get(cv->v.str, NULL); } return 1; } @@ -81,32 +84,37 @@ int persistent_filter_load(struct dev_filter *f) struct pfilter *pf = (struct pfilter *) f->private; int r = 0; - struct config_file *cf; + struct config_tree *cf; - if (!(cf = create_config_file())) { + if (!(cf = create_config_tree())) { stack; return 0; } - if (!read_config(cf, pf->file)) { + if (!read_config_file(cf, pf->file)) { stack; goto out; } _read_array(pf, cf, "persistent_filter_cache/valid_devices", PF_GOOD_DEVICE); - _read_array(pf, cf, "persistent_filter_cache/invalid_devices", - PF_BAD_DEVICE); + /* We don't gain anything by holding invalid devices */ + /* _read_array(pf, cf, "persistent_filter_cache/invalid_devices", + PF_BAD_DEVICE); */ - if (hash_get_num_entries(pf->devices)) + /* Did we find anything? */ + if (hash_get_num_entries(pf->devices)) { + /* We populated dev_cache ourselves */ + dev_cache_scan(0); r = 1; + } out: - destroy_config_file(cf); + destroy_config_tree(cf); return r; } -static void _write_array(struct pfilter *pf, FILE * fp, const char *path, +static void _write_array(struct pfilter *pf, FILE *fp, const char *path, void *data) { void *d; @@ -147,6 +155,12 @@ int persistent_filter_dump(struct dev_filter *f) "- not writing to %s", pf->file); return 0; } + if (!dev_cache_has_scanned()) { + log_very_verbose("Device cache incomplete - not writing " + "to %s", pf->file); + return 0; + } + log_very_verbose("Dumping persistent device cache to %s", pf->file); fp = fopen(pf->file, "w"); @@ -160,7 +174,8 @@ int persistent_filter_dump(struct dev_filter *f) fprintf(fp, "persistent_filter_cache {\n"); _write_array(pf, fp, "valid_devices", PF_GOOD_DEVICE); - _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); + /* We don't gain anything by remembering invalid devices */ + /* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */ fprintf(fp, "}\n"); fclose(fp); diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c index ae79451d7..235deb5e7 100644 --- a/lib/filters/filter-regex.c +++ b/lib/filters/filter-regex.c @@ -4,12 +4,12 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "pool.h" #include "filter-regex.h" #include "matcher.h" #include "device.h" #include "bitset.h" -#include "log.h" #include "list.h" struct rfilter { @@ -137,7 +137,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val) * build the matcher. */ if (!(rf->engine = matcher_create(rf->mem, (const char **) regex, - count))) + count))) stack; r = 1; diff --git a/lib/filters/filter.c b/lib/filters/filter.c index e6f2e3fc5..3e89e4eeb 100644 --- a/lib/filters/filter.c +++ b/lib/filters/filter.c @@ -18,18 +18,14 @@ * */ -#include "dbg_malloc.h" -#include "log.h" +#include "lib.h" #include "dev-cache.h" #include "filter.h" #include "lvm-string.h" -#include #include -#include #include #include -#include #include #include #include @@ -43,6 +39,7 @@ typedef struct { static int _md_major = -1; +/* FIXME Move list into config file */ static device_info_t device_info[] = { {"ide", 16}, /* IDE disk */ {"sd", 16}, /* SCSI disk */ diff --git a/lib/format1/.export.sym b/lib/format1/.export.sym new file mode 100644 index 000000000..a7b408bcd --- /dev/null +++ b/lib/format1/.export.sym @@ -0,0 +1,7 @@ +{ + global: + init_format; + local: + *; +}; + diff --git a/lib/format1/Makefile.in b/lib/format1/Makefile.in new file mode 100644 index 000000000..5e52ffba8 --- /dev/null +++ b/lib/format1/Makefile.in @@ -0,0 +1,31 @@ +# +# Copyright (C) 2002 Sistina Software (UK) Limited. +# +# This file is released under the LGPL. +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +SOURCES=\ + disk-rep.c \ + format1.c \ + import-export.c \ + import-extents.c \ + layout.c \ + lvm1-label.c \ + vg_number.c + +TARGETS=liblvm2format1.so + +include ../../make.tmpl + + +install: libformat1.so + $(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \ + $(libdir)/liblvm2format1.so.$(LIB_VERSION) + $(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so + +.PHONY: install + diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c index d0005b6fd..6c368a036 100644 --- a/lib/format1/disk-rep.c +++ b/lib/format1/disk-rep.c @@ -4,15 +4,13 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "disk-rep.h" -#include "dbg_malloc.h" #include "pool.h" #include "xlate.h" -#include "log.h" -#include "vgcache.h" #include "filter.h" +#include "cache.h" -#include #include #include #include @@ -116,12 +114,12 @@ static int _munge_formats(struct pv_disk *pvd) switch (pvd->version) { case 1: pvd->pe_start = ((pvd->pe_on_disk.base + - pvd->pe_on_disk.size) / SECTOR_SIZE); + pvd->pe_on_disk.size) >> SECTOR_SHIFT); break; case 2: pvd->version = 1; - pe_start = pvd->pe_start * SECTOR_SIZE; + pe_start = pvd->pe_start << SECTOR_SHIFT; pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base; break; @@ -132,7 +130,7 @@ static int _munge_formats(struct pv_disk *pvd) return 1; } -int read_pvd(struct device *dev, struct pv_disk *pvd) +static int _read_pvd(struct device *dev, struct pv_disk *pvd) { if (dev_read(dev, 0, sizeof(*pvd), pvd) != sizeof(*pvd)) { log_very_verbose("Failed to read PV data from %s", @@ -143,14 +141,14 @@ int read_pvd(struct device *dev, struct pv_disk *pvd) _xlate_pvd(pvd); if (pvd->id[0] != 'H' || pvd->id[1] != 'M') { - log_very_verbose("%s does not have a valid PV identifier", + log_very_verbose("%s does not have a valid LVM1 PV identifier", dev_name(dev)); return 0; } if (!_munge_formats(pvd)) { - log_very_verbose("Unknown metadata version %d found on %s", - pvd->version, dev_name(dev)); + log_very_verbose("format1: Unknown metadata version %d " + "found on %s", pvd->version, dev_name(dev)); return 0; } @@ -282,6 +280,7 @@ static struct disk_list *__read_disk(struct format_type *fmt, { struct disk_list *dl = pool_alloc(mem, sizeof(*dl)); const char *name = dev_name(dev); + struct cache_info *info; if (!dl) { stack; @@ -293,11 +292,20 @@ static struct disk_list *__read_disk(struct format_type *fmt, list_init(&dl->uuids); list_init(&dl->lvds); - if (!read_pvd(dev, &dl->pvd)) { + if (!_read_pvd(dev, &dl->pvd)) { stack; goto bad; } + if (!(info = cache_add(fmt->labeller, dl->pvd.pv_uuid, dev, + dl->pvd.vg_name, NULL))) + stack; + else { + info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT; + list_init(&info->mdas); + info->status &= ~CACHE_INVALID; + } + /* * is it an orphan ? */ @@ -305,7 +313,7 @@ static struct disk_list *__read_disk(struct format_type *fmt, log_very_verbose("%s is not a member of any format1 VG", name); /* Update VG cache */ - vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); + /* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */ return (vg_name) ? NULL : dl; } @@ -319,7 +327,7 @@ static struct disk_list *__read_disk(struct format_type *fmt, _munge_exported_vg(dl); /* Update VG cache with what we found */ - vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); + /* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */ if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) { log_very_verbose("%s is not a member of the VG %s", @@ -407,14 +415,15 @@ int read_pvs_in_vg(struct format_type *fmt, const char *vg_name, struct dev_iter *iter; struct device *dev; struct disk_list *data = NULL; - - struct list *pvdh, *pvdh2; + struct list *vgih; + struct cache_vginfo *vginfo; /* Fast path if we already saw this VG and cached the list of PVs */ - if ((pvdh = vgcache_find(vg_name))) { - list_iterate(pvdh2, pvdh) { - dev = list_item(pvdh2, struct pvdev_list)->dev; - if (!(data = read_disk(fmt, dev, mem, vg_name))) + if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) && + vginfo->infos.n) { + list_iterate(vgih, &vginfo->infos) { + dev = list_item(vgih, struct cache_info)->dev; + if (dev && !(data = read_disk(fmt, dev, mem, vg_name))) break; _add_pv_to_list(head, data); } @@ -422,11 +431,12 @@ int read_pvs_in_vg(struct format_type *fmt, const char *vg_name, /* Did we find the whole VG? */ if (!vg_name || !*vg_name || (data && *data->pvd.vg_name && - list_size(head) == data->vgd.pv_cur)) return 1; + list_size(head) == data->vgd.pv_cur)) + return 1; - /* Something changed. Remove the hints. */ + /* Failed */ list_init(head); - vgcache_del(vg_name); + /* vgcache_del(vg_name); */ } if (!(iter = dev_iter_create(filter))) { @@ -514,8 +524,7 @@ static int _write_lvs(struct disk_list *data) struct lvd_list *ll = list_item(lvh, struct lvd_list); offset = sizeof(struct lv_disk) * ll->lvd.lv_number; - if (offset + sizeof(struct lv_disk) > - data->pvd.lv_on_disk.size) { + if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) { log_error("lv_number %d too large", ll->lvd.lv_number); return 0; } @@ -587,19 +596,19 @@ static int __write_all_pvd(struct format_type *fmt, struct disk_list *data) return 0; } - vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); + /* vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt); */ /* * Stop here for orphan pv's. */ if (data->pvd.vg_name[0] == '\0') { - if (!test_mode()) - vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); + /* if (!test_mode()) + vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt); */ return 1; } - if (!test_mode()) - vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, - fmt); + /* if (!test_mode()) + vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, + fmt); */ if (!_write_vgd(data)) { log_error("Failed to write VG data to %s", pv_name); diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h index dbd8ac586..852aa1c00 100644 --- a/lib/format1/disk-rep.h +++ b/lib/format1/disk-rep.h @@ -11,21 +11,17 @@ #include "metadata.h" #include "pool.h" - -#define SECTOR_SIZE 512 - #define MAX_PV 256 #define MAX_LV 256 #define MAX_VG 99 -#define MAX_PV_SIZE ((uint32_t) -1) /* 2TB in sectors - 1 */ -#define MIN_PE_SIZE (8192L / SECTOR_SIZE) /* 8 KB in sectors */ -#define MAX_PE_SIZE (16L * 1024L * 1024L / SECTOR_SIZE * 1024) -#define PE_SIZE_PV_SIZE_REL 5 /* PV size must be at least 5 times PE size */ -#define MAX_LE_TOTAL 65534 /* 2^16 - 2 */ +#define MAX_PV_SIZE ((uint32_t) -1) /* 2TB in sectors - 1 */ +#define MIN_PE_SIZE (8192L >> SECTOR_SHIFT) /* 8 KB in sectors */ +#define MAX_PE_SIZE (16L * 1024L * (1024L >> SECTOR_SHIFT) * 1024L) +#define PE_SIZE_PV_SIZE_REL 5 /* PV size must be at least 5 times PE size */ +#define MAX_LE_TOTAL 65534 /* 2^16 - 2 */ #define MAX_PE_TOTAL ((uint32_t) -2) - #define UNMAPPED_EXTENT 0 /* volume group */ @@ -60,86 +56,84 @@ #define EXPORTED_TAG "PV_EXP" /* Identifier for exported PV */ #define IMPORTED_TAG "PV_IMP" /* Identifier for imported PV */ - struct data_area { uint32_t base; uint32_t size; -}; +} __attribute__ ((packed)); struct pv_disk { - uint8_t id[2]; - uint16_t version; /* lvm version */ - struct data_area pv_on_disk; - struct data_area vg_on_disk; - struct data_area pv_uuidlist_on_disk; - struct data_area lv_on_disk; - struct data_area pe_on_disk; - uint8_t pv_uuid[NAME_LEN]; - uint8_t vg_name[NAME_LEN]; - 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; + uint8_t id[2]; + uint16_t version; /* lvm version */ + struct data_area pv_on_disk; + struct data_area vg_on_disk; + struct data_area pv_uuidlist_on_disk; + struct data_area lv_on_disk; + struct data_area pe_on_disk; + uint8_t pv_uuid[NAME_LEN]; + uint8_t vg_name[NAME_LEN]; + 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; /* only present on version == 2 pv's */ uint32_t pe_start; -}; +} __attribute__ ((packed)); struct lv_disk { - 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 original */ - 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; -}; + 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 original */ + 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; +} __attribute__ ((packed)); struct vg_disk { - uint8_t vg_uuid[ID_LEN]; /* volume group UUID */ - uint8_t vg_name_dummy[NAME_LEN - ID_LEN]; /* rest of v1 VG name */ - 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 */ -}; + uint8_t vg_uuid[ID_LEN]; /* volume group UUID */ + uint8_t vg_name_dummy[NAME_LEN - ID_LEN]; /* rest of v1 VG name */ + 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 */ +} __attribute__ ((packed)); struct pe_disk { uint16_t lv_num; uint16_t le_num; -}; - +} __attribute__ ((packed)); struct uuid_list { struct list list; @@ -163,7 +157,6 @@ struct disk_list { struct pe_disk *extents; }; - /* * Layout constants. */ @@ -173,19 +166,17 @@ struct disk_list { #define PV_SIZE 1024UL #define VG_SIZE 4096UL - /* * Functions to calculate layout info. */ int calculate_layout(struct disk_list *dl); -int calculate_extent_count(struct physical_volume *pv); - +int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size, + uint32_t max_extent_count); /* * Low level io routines which read/write * disk_lists. */ -int read_pvd(struct device *dev, struct pv_disk *pvd); struct disk_list *read_disk(struct format_type *fmt, struct device *dev, struct pool *mem, const char *vg_name); @@ -196,7 +187,6 @@ int read_pvs_in_vg(struct format_type *fmt, const char *vg_name, int write_disks(struct format_type *fmt, struct list *pvds); - /* * Functions to translate to between disk and in * core structures. @@ -208,27 +198,21 @@ int export_pv(struct pool *mem, struct volume_group *vg, struct pv_disk *pvd, struct physical_volume *pv); int import_vg(struct pool *mem, - struct volume_group *vg, struct disk_list *dl, - int partial); + struct volume_group *vg, struct disk_list *dl, int partial); int export_vg(struct vg_disk *vgd, struct volume_group *vg); -int import_lv(struct pool *mem, struct logical_volume *lv, - struct lv_disk *lvd); -void export_lv(struct lv_disk *lvd, struct volume_group *vg, - struct logical_volume *lv, const char *dev_dir); +int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd); int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds); int export_extents(struct disk_list *dl, int lv_num, - struct logical_volume *lv, - struct physical_volume *pv); + struct logical_volume *lv, struct physical_volume *pv); -int import_pvs(struct format_instance *fid, struct pool *mem, +int import_pvs(struct format_type *fmt, struct pool *mem, struct volume_group *vg, struct list *pvds, struct list *results, int *count); -int import_lvs(struct pool *mem, struct volume_group *vg, - struct list *pvds); +int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds); int export_lvs(struct disk_list *dl, struct volume_group *vg, struct physical_volume *pv, const char *dev_dir); @@ -247,5 +231,4 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter, int export_vg_number(struct format_instance *fid, struct list *pvds, const char *vg_name, struct dev_filter *filter); - #endif diff --git a/lib/format1/format1.c b/lib/format1/format1.c index b09daa029..01b2dbebc 100644 --- a/lib/format1/format1.c +++ b/lib/format1/format1.c @@ -4,15 +4,17 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "disk-rep.h" -#include "dbg_malloc.h" #include "pool.h" #include "hash.h" #include "limits.h" #include "list.h" -#include "log.h" #include "display.h" #include "toolcontext.h" +#include "cache.h" +#include "lvm1-label.h" +#include "format1.h" /* VG consistency checks */ static int _check_vgs(struct list *pvs, int *partial) @@ -113,7 +115,7 @@ static struct volume_group *_build_vg(struct format_instance *fid, if (!import_vg(mem, vg, dl, partial)) goto bad; - if (!import_pvs(fid, mem, vg, pvs, &vg->pvs, &vg->pv_count)) + if (!import_pvs(fid->fmt, mem, vg, pvs, &vg->pvs, &vg->pv_count)) goto bad; if (!import_lvs(mem, vg, pvs)) @@ -134,7 +136,8 @@ static struct volume_group *_build_vg(struct format_instance *fid, } static struct volume_group *_vg_read(struct format_instance *fid, - const char *vg_name, void *mda) + const char *vg_name, + struct metadata_area *mda) { struct pool *mem = pool_create(1024 * 10); struct list pvs; @@ -185,8 +188,7 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg, if (!export_pv(mem, vg, &dl->pvd, pv) || !export_vg(&dl->vgd, vg) || !export_uuids(dl, vg) || - !export_lvs(dl, vg, pv, dev_dir) || - !calculate_layout(dl)) { + !export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) { stack; pool_free(mem, dl); return NULL; @@ -227,7 +229,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem, } static int _vg_write(struct format_instance *fid, struct volume_group *vg, - void *mdl) + struct metadata_area *mda) { struct pool *mem = pool_create(1024 * 10); struct list pvds; @@ -243,26 +245,28 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg, r = (_flatten_vg(fid, mem, vg, &pvds, fid->fmt->cmd->dev_dir, fid->fmt->cmd->filter) && write_disks(fid->fmt, &pvds)); + + cache_update_vg(vg); pool_destroy(mem); return r; } -int _pv_read(struct format_type *fmt, const char *name, - struct physical_volume *pv) +int _pv_read(struct format_type *fmt, const char *pv_name, + struct physical_volume *pv, struct list *mdas) { struct pool *mem = pool_create(1024); struct disk_list *dl; struct device *dev; int r = 0; - log_very_verbose("Reading physical volume data %s from disk", name); + log_very_verbose("Reading physical volume data %s from disk", pv_name); if (!mem) { stack; return 0; } - if (!(dev = dev_cache_get(name, fmt->cmd->filter))) { + if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) { stack; goto out; } @@ -277,7 +281,7 @@ int _pv_read(struct format_type *fmt, const char *name, goto out; } - pv->fid = fmt->ops->create_instance(fmt, NULL, NULL); + pv->fmt = fmt; r = 1; @@ -286,123 +290,45 @@ int _pv_read(struct format_type *fmt, const char *name, return r; } -static struct list *_get_pvs(struct format_type *fmt, struct list *results) +static int _pv_setup(struct format_type *fmt, + uint64_t pe_start, uint32_t extent_count, + uint32_t extent_size, + int pvmetadatacopies, + uint64_t pvmetadatasize, struct list *mdas, + struct physical_volume *pv, struct volume_group *vg) { - struct pool *mem = pool_create(1024 * 10); - struct list pvs; - uint32_t count; + char *sz; - if (!mem) { - stack; - return NULL; - } - - list_init(&pvs); - - if (!read_pvs_in_vg(fmt, NULL, fmt->cmd->filter, mem, &pvs)) { - stack; - goto bad; - } - - if (!import_pvs(NULL, fmt->cmd->mem, NULL, &pvs, results, &count)) { - stack; - goto bad; - } - - pool_destroy(mem); - return results; - - bad: - pool_destroy(mem); - return NULL; -} - -static int _find_vg_name(struct list *names, const char *vg) -{ - struct list *nh; - struct name_list *nl; - - list_iterate(nh, names) { - nl = list_item(nh, struct name_list); - if (!strcmp(nl->name, vg)) - return 1; - } - - return 0; -} - -static struct list *_get_vgs(struct format_type *fmt, struct list *names) -{ - struct list *pvh; - struct list *pvs; - struct name_list *nl; - - if (!(pvs = pool_alloc(fmt->cmd->mem, sizeof(*pvs)))) { - log_error("PV list allocation failed"); - goto err; - } - - list_init(pvs); - - if (!_get_pvs(fmt, pvs)) { - stack; - goto err; - } - - list_iterate(pvh, pvs) { - struct pv_list *pvl = list_item(pvh, struct pv_list); - - if (!(*pvl->pv->vg_name) || - _find_vg_name(names, pvl->pv->vg_name)) - continue; - - if (!(nl = pool_alloc(fmt->cmd->mem, sizeof(*nl)))) { - stack; - goto err; - } - - if (!(nl->name = pool_strdup(fmt->cmd->mem, pvl->pv->vg_name))) { - stack; - goto err; - } - - list_add(names, &nl->list); - } - - if (list_empty(names)) - pool_free(fmt->cmd->mem, pvs); - - return names; - - err: - pool_free(fmt->cmd->mem, pvs); - return NULL; -} - -static int _pv_setup(struct format_instance *fid, struct physical_volume *pv, - struct volume_group *vg) -{ - /* setup operations for the PV structure */ if (pv->size > MAX_PV_SIZE) pv->size--; if (pv->size > MAX_PV_SIZE) { - /* FIXME Limit hardcoded */ - log_error("Physical volumes cannot be bigger than 2TB"); + log_error("Physical volumes cannot be bigger than %s", + sz = display_size(MAX_PV_SIZE / 2, SIZE_SHORT)); + dbg_free(sz); return 0; } - /* Nothing more to do if pe_size isn't known */ - if (!vg) + /* Nothing more to do if extent size isn't provided */ + if (!extent_size) return 1; /* * This works out pe_start and pe_count. */ - if (!calculate_extent_count(pv)) { + if (!calculate_extent_count(pv, extent_size, extent_count)) { stack; return 0; } + /* Retain existing extent locations exactly */ + /* FIXME Relax this so a non-overlapping existing pe_start can also + * be used in place of the calculated one */ + if (((pe_start || extent_count) && (pe_start != pv->pe_start)) || + (extent_count && (extent_count != pv->pe_count))) { + log_error("Metadata would overwrite physical extents"); + return 0; + } + return 1; } @@ -448,20 +374,27 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv) return 1; } -static int _pv_write(struct format_instance *fid, struct physical_volume *pv, - void *mdl) +static int _pv_write(struct format_type *fmt, struct physical_volume *pv, + struct list *mdas, int64_t sector) { struct pool *mem; struct disk_list *dl; struct list pvs; + struct label *label; + struct cache_info *info; - list_init(&pvs); - - if (*pv->vg_name || pv->pe_alloc_count) { - log_error("Assertion failed: can't _pv_write non-orphan PV " - "(in VG %s)", pv->vg_name); + if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev, + pv->vg_name, NULL))) { + stack; return 0; } + label = info->label; + info->device_size = pv->size << SECTOR_SHIFT; + info->fmt = fmt; + + list_init(&info->mdas); + + list_init(&pvs); /* Ensure any residual PE structure is gone */ pv->pe_size = pv->pe_count = 0; @@ -488,10 +421,10 @@ static int _pv_write(struct format_instance *fid, struct physical_volume *pv, dev_write in order to make other disk tools happy */ dl->pvd.pv_on_disk.base = METADATA_BASE; dl->pvd.pv_on_disk.size = PV_SIZE; - dl->pvd.pe_on_disk.base = PE_ALIGN * SECTOR_SIZE; + dl->pvd.pe_on_disk.base = PE_ALIGN << SECTOR_SHIFT; list_add(&pvs, &dl->list); - if (!write_disks(fid->fmt, &pvs)) { + if (!write_disks(fmt, &pvs)) { stack; goto bad; } @@ -542,6 +475,11 @@ int _vg_setup(struct format_instance *fid, struct volume_group *vg) return 1; } +static struct metadata_area_ops _metadata_format1_ops = { + vg_read:_vg_read, + vg_write:_vg_write, +}; + struct format_instance *_create_instance(struct format_type *fmt, const char *vgname, void *private) { @@ -563,6 +501,7 @@ struct format_instance *_create_instance(struct format_type *fmt, return NULL; } + mda->ops = &_metadata_format1_ops; mda->metadata_locn = NULL; list_add(&fid->metadata_areas, &mda->list); @@ -580,21 +519,21 @@ void _destroy(struct format_type *fmt) } static struct format_handler _format1_ops = { - get_vgs: _get_vgs, - get_pvs: _get_pvs, - pv_read: _pv_read, - pv_setup: _pv_setup, - pv_write: _pv_write, - lv_setup: _lv_setup, - vg_read: _vg_read, - vg_setup: _vg_setup, - vg_write: _vg_write, + pv_read:_pv_read, + pv_setup:_pv_setup, + pv_write:_pv_write, + lv_setup:_lv_setup, + vg_setup:_vg_setup, create_instance:_create_instance, destroy_instance:_destroy_instance, - destroy: _destroy, + destroy:_destroy, }; -struct format_type *create_lvm1_format(struct cmd_context *cmd) +#ifdef LVM1_INTERNAL +struct format_type *init_lvm1_format(struct cmd_context *cmd) +#else /* Shared */ +struct format_type *init_format(struct cmd_context *cmd) +#endif { struct format_type *fmt = dbg_malloc(sizeof(*fmt)); @@ -606,8 +545,19 @@ struct format_type *create_lvm1_format(struct cmd_context *cmd) fmt->cmd = cmd; fmt->ops = &_format1_ops; fmt->name = FMT_LVM1_NAME; + fmt->alias = NULL; fmt->features = 0; fmt->private = NULL; + if (!(fmt->labeller = lvm1_labeller_create(fmt))) { + log_error("Couldn't create lvm1 label handler."); + return NULL; + } + + if (!(label_register_handler(FMT_LVM1_NAME, fmt->labeller))) { + log_error("Couldn't register lvm1 label handler."); + return NULL; + } + return fmt; } diff --git a/lib/format1/format1.h b/lib/format1/format1.h index 6412e4bf4..26be50757 100644 --- a/lib/format1/format1.h +++ b/lib/format1/format1.h @@ -9,6 +9,10 @@ #include "metadata.h" -struct format_type *create_lvm1_format(struct cmd_context *cmd); +#define FMT_LVM1_NAME "lvm1" + +#ifdef LVM1_INTERNAL +struct format_type *init_lvm1_format(struct cmd_context *cmd); +#endif #endif diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c index 08df47912..4dfbf5467 100644 --- a/lib/format1/import-export.c +++ b/lib/format1/import-export.c @@ -6,12 +6,11 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "disk-rep.h" -#include "dbg_malloc.h" #include "pool.h" #include "hash.h" #include "list.h" -#include "log.h" #include "lvm-string.h" #include @@ -57,9 +56,9 @@ int import_pv(struct pool *mem, struct device *dev, if (vg && strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))) - log_very_verbose("System ID %s on %s differs from %s for " - "volume group", pvd->system_id, - dev_name(pv->dev), vg->system_id); + log_very_verbose("System ID %s on %s differs from %s for " + "volume group", pvd->system_id, + dev_name(pv->dev), vg->system_id); /* * If exported, we still need to flag in pv->status too because @@ -163,7 +162,7 @@ int export_pv(struct pool *mem, struct volume_group *vg, if (vg && (!*vg->system_id || strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))) - strncpy(vg->system_id, pvd->system_id, NAME_LEN); + strncpy(vg->system_id, pvd->system_id, NAME_LEN); //pvd->pv_major = MAJOR(pv->dev); @@ -172,7 +171,10 @@ int export_pv(struct pool *mem, struct volume_group *vg, pvd->pv_size = pv->size; pvd->lv_cur = 0; /* this is set when exporting the lv list */ - pvd->pe_size = pv->pe_size; + if (vg) + pvd->pe_size = vg->extent_size; + else + pvd->pe_size = pv->pe_size; pvd->pe_total = pv->pe_count; pvd->pe_allocated = pv->pe_alloc_count; pvd->pe_start = pv->pe_start; @@ -278,6 +280,8 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd) return 0; } + lv->status |= VISIBLE_LV; + if (lvd->lv_status & LV_SPINDOWN) lv->status |= SPINDOWN_LV; @@ -296,13 +300,11 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd) if (lvd->lv_badblock) lv->status |= BADBLOCK_ON; - if (lvd->lv_allocation & LV_STRICT) - lv->alloc = ALLOC_STRICT; - + /* Drop the unused LV_STRICT here */ if (lvd->lv_allocation & LV_CONTIGUOUS) lv->alloc = ALLOC_CONTIGUOUS; else - lv->alloc |= ALLOC_NEXT_FREE; + lv->alloc = ALLOC_NEXT_FREE; lv->read_ahead = lvd->lv_read_ahead; lv->size = lvd->lv_size; @@ -313,15 +315,13 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd) return 1; } -void export_lv(struct lv_disk *lvd, struct volume_group *vg, - struct logical_volume *lv, const char *dev_dir) +static void _export_lv(struct lv_disk *lvd, struct volume_group *vg, + struct logical_volume *lv, const char *dev_dir) { memset(lvd, 0, sizeof(*lvd)); snprintf(lvd->lv_name, sizeof(lvd->lv_name), "%s%s/%s", dev_dir, vg->name, lv->name); - /* FIXME: Add 'if' test */ - _check_vg_name(vg->name); strcpy(lvd->vg_name, vg->name); if (lv->status & LVM_READ) @@ -339,10 +339,9 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg, } lvd->lv_read_ahead = lv->read_ahead; - lvd->lv_stripes = list_item(lv->segments.n, - struct stripe_segment)->stripes; + lvd->lv_stripes = list_item(lv->segments.n, struct lv_segment)->stripes; lvd->lv_stripesize = list_item(lv->segments.n, - struct stripe_segment)->stripe_size; + struct lv_segment)->stripe_size; lvd->lv_size = lv->size; lvd->lv_allocated_le = lv->le_count; @@ -350,9 +349,6 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg, if (lv->status & BADBLOCK_ON) lvd->lv_badblock = LV_BADBLOCK_ON; - if (lv->alloc == ALLOC_STRICT) - lvd->lv_allocation |= LV_STRICT; - if (lv->alloc == ALLOC_CONTIGUOUS) lvd->lv_allocation |= LV_CONTIGUOUS; } @@ -362,11 +358,11 @@ int export_extents(struct disk_list *dl, int lv_num, { struct list *segh; struct pe_disk *ped; - struct stripe_segment *seg; + struct lv_segment *seg; uint32_t pe, s; list_iterate(segh, &lv->segments) { - seg = list_item(segh, struct stripe_segment); + seg = list_item(segh, struct lv_segment); for (s = 0; s < seg->stripes; s++) { if (seg->area[s].pv != pv) @@ -384,7 +380,7 @@ int export_extents(struct disk_list *dl, int lv_num, return 1; } -int import_pvs(struct format_instance *fid, struct pool *mem, +int import_pvs(struct format_type *fmt, struct pool *mem, struct volume_group *vg, struct list *pvds, struct list *results, int *count) { @@ -408,7 +404,7 @@ int import_pvs(struct format_instance *fid, struct pool *mem, return 0; } - pvl->pv->fid = fid; + pvl->pv->fmt = fmt; list_add(results, &pvl->list); (*count)++; } @@ -477,6 +473,11 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg, int lv_num, len; struct hash_table *lvd_hash; + if (!_check_vg_name(vg->name)) { + stack; + return 0; + } + if (!(lvd_hash = hash_create(32))) { stack; return 0; @@ -499,7 +500,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg, goto out; } - export_lv(&lvdl->lvd, vg, ll->lv, dev_dir); + _export_lv(&lvdl->lvd, vg, ll->lv, dev_dir); lv_num = lvnum_from_lvid(&ll->lv->lvid); @@ -616,7 +617,8 @@ int import_snapshots(struct pool *mem, struct volume_group *vg, continue; /* insert the snapshot */ - if (!vg_add_snapshot(org, cow, 1, lvd->lv_chunk_size)) { + if (!vg_add_snapshot(org, cow, 1, NULL, + lvd->lv_chunk_size)) { log_err("Couldn't add snapshot."); return 0; } diff --git a/lib/format1/import-extents.c b/lib/format1/import-extents.c index 13f5d9304..c63ea434a 100644 --- a/lib/format1/import-extents.c +++ b/lib/format1/import-extents.c @@ -4,10 +4,9 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "metadata.h" #include "hash.h" -#include "dbg_malloc.h" -#include "log.h" #include "pool.h" #include "disk-rep.h" @@ -192,9 +191,9 @@ static int _check_maps_are_complete(struct hash_table *maps) return 1; } -static struct stripe_segment *_alloc_seg(struct pool *mem, uint32_t stripes) +static struct lv_segment *_alloc_seg(struct pool *mem, uint32_t stripes) { - struct stripe_segment *seg; + struct lv_segment *seg; uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0])); if (!(seg = pool_zalloc(mem, len))) { @@ -208,12 +207,13 @@ static struct stripe_segment *_alloc_seg(struct pool *mem, uint32_t stripes) static int _read_linear(struct pool *mem, struct lv_map *lvm) { uint32_t le = 0; - struct stripe_segment *seg; + struct lv_segment *seg; while (le < lvm->lv->le_count) { seg = _alloc_seg(mem, 1); seg->lv = lvm->lv; + seg->type = SEG_STRIPED; seg->le = le; seg->len = 0; seg->stripe_size = 0; @@ -238,7 +238,7 @@ static int _read_linear(struct pool *mem, struct lv_map *lvm) return 1; } -static int _check_stripe(struct lv_map *lvm, struct stripe_segment *seg, +static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg, uint32_t base_le, uint32_t len) { uint32_t le, st; @@ -260,7 +260,7 @@ static int _check_stripe(struct lv_map *lvm, struct stripe_segment *seg, static int _read_stripes(struct pool *mem, struct lv_map *lvm) { uint32_t st, le = 0, len; - struct stripe_segment *seg; + struct lv_segment *seg; /* * Work out overall striped length @@ -279,6 +279,7 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm) } seg->lv = lvm->lv; + seg->type = SEG_STRIPED; seg->stripe_size = lvm->stripe_size; seg->stripes = lvm->stripes; seg->le = seg->stripes * le; diff --git a/lib/format1/layout.c b/lib/format1/layout.c index c94082422..d0055ede8 100644 --- a/lib/format1/layout.c +++ b/lib/format1/layout.c @@ -4,9 +4,8 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "disk-rep.h" -#include "log.h" -#include "dbg_malloc.h" /* * Only works with powers of 2. @@ -36,7 +35,7 @@ static uint32_t _next_base(struct data_area *area) */ static int _adjust_pe_on_disk(struct pv_disk *pvd) { - uint32_t pe_start = pvd->pe_start * SECTOR_SIZE; + uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT; if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size) return 0; @@ -103,11 +102,10 @@ int calculate_layout(struct disk_list *dl) } /* - * It may seem strange to have a struct physical_volume in here, - * but the number of extents that can fit on a disk *is* metadata - * format dependant. + * The number of extents that can fit on a disk is metadata format dependant. */ -int calculate_extent_count(struct physical_volume *pv) +int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size, + uint32_t max_extent_count) { struct pv_disk *pvd = dbg_malloc(sizeof(*pvd)); uint32_t end; @@ -122,10 +120,13 @@ int calculate_extent_count(struct physical_volume *pv) * one is going to be knocked off at the start of the * next loop. */ - pvd->pe_total = (pv->size / pv->pe_size); + if (max_extent_count) + pvd->pe_total = max_extent_count + 1; + else + pvd->pe_total = (pv->size / extent_size); if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) { - log_error("Insufficient space for extents on %s", + log_error("Too few extents on %s. Try smaller extent size.", dev_name(pv->dev)); dbg_free(pvd); return 0; @@ -135,11 +136,12 @@ int calculate_extent_count(struct physical_volume *pv) pvd->pe_total--; _calc_simple_layout(pvd); end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size + - SECTOR_SIZE - 1) / SECTOR_SIZE); + SECTOR_SIZE - 1) >> SECTOR_SHIFT); pvd->pe_start = _round_up(end, PE_ALIGN); - } while ((pvd->pe_start + (pvd->pe_total * pv->pe_size)) > pv->size); + } while ((pvd->pe_start + (pvd->pe_total * extent_size)) + > pv->size); if (pvd->pe_total > MAX_PE_TOTAL) { log_error("Metadata extent limit (%u) exceeded for %s - " @@ -151,6 +153,7 @@ int calculate_extent_count(struct physical_volume *pv) pv->pe_count = pvd->pe_total; pv->pe_start = pvd->pe_start; + /* We can't set pe_size here without breaking LVM1 compatibility */ dbg_free(pvd); return 1; } diff --git a/lib/format1/lvm1-label.c b/lib/format1/lvm1-label.c new file mode 100644 index 000000000..ae2b2e162 --- /dev/null +++ b/lib/format1/lvm1-label.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2002 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#include "lib.h" +#include "lvm1-label.h" +#include "disk-rep.h" +#include "label.h" +#include "metadata.h" +#include "xlate.h" +#include "cache.h" + +#include +#include + +static void _not_supported(const char *op) +{ + log_err("The '%s' operation is not supported for the lvm1 labeller.", + op); +} + +static int _can_handle(struct labeller *l, char *buf, uint64_t sector) +{ + struct pv_disk *pvd = (struct pv_disk *) buf; + uint32_t version; + + /* LVM1 label must always be in first sector */ + if (sector) + return 0; + + version = xlate16(pvd->version); + + if (pvd->id[0] == 'H' && pvd->id[1] == 'M' && + (version == 1 || version == 2)) + return 1; + + return 0; +} + +static int _write(struct label *label, char *buf) +{ + _not_supported("write"); + return 0; +} + +static int _read(struct labeller *l, struct device *dev, char *buf, + struct label **label) +{ + struct pv_disk *pvd = (struct pv_disk *) buf; + struct cache_info *info; + + if (!(info = cache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) + return 0; + *label = info->label; + + info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT; + list_init(&info->mdas); + + info->status &= ~CACHE_INVALID; + + return 1; +} + +static int _initialise_label(struct labeller *l, struct label *label) +{ + strcpy(label->type, "LVM1"); + + return 1; +} + +static void _destroy_label(struct labeller *l, struct label *label) +{ + return; +} + +static void _destroy(struct labeller *l) +{ + dbg_free(l); +} + +struct label_ops _lvm1_ops = { + can_handle:_can_handle, + write:_write, + read:_read, + verify:_can_handle, + initialise_label:_initialise_label, + destroy_label:_destroy_label, + destroy:_destroy +}; + +struct labeller *lvm1_labeller_create(struct format_type *fmt) +{ + struct labeller *l; + + if (!(l = dbg_malloc(sizeof(*l)))) { + log_err("Couldn't allocate labeller object."); + return NULL; + } + + l->ops = &_lvm1_ops; + l->private = (void *) fmt; + + return l; +} diff --git a/lib/format1/lvm1-label.h b/lib/format1/lvm1-label.h new file mode 100644 index 000000000..f563b795c --- /dev/null +++ b/lib/format1/lvm1-label.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2002 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#ifndef _LVM_LVM1_LABEL_H +#define _LVM_LVM1_LABEL_H + +#include "metadata.h" + +struct labeller *lvm1_labeller_create(struct format_type *fmt); + +#endif diff --git a/lib/format1/lvm1_label.c b/lib/format1/lvm1_label.c deleted file mode 100644 index 3f2e9b08e..000000000 --- a/lib/format1/lvm1_label.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2002 Sistina Software (UK) Limited. - * - * This file is released under the LGPL. - */ - -#include "lvm1_label.h" -#include "dbg_malloc.h" -#include "disk-rep.h" -#include "log.h" -#include "label.h" - -#include -#include -#include - -static void _not_supported(const char *op) -{ - log_err("The '%s' operation is not supported for the lvm1 labeller.", - op); -} - -static int _can_handle(struct labeller *l, struct device *dev) -{ - struct pv_disk pvd; - int r; - - if (!dev_open(dev, O_RDONLY)) { - stack; - return 0; - } - - r = read_pvd(dev, &pvd); - - if (!dev_close(dev)) - stack; - - return r; -} - -static int _write(struct labeller *l, struct device *dev, struct label *label) -{ - _not_supported("write"); - return 0; -} - -static int _remove(struct labeller *l, struct device *dev) -{ - _not_supported("remove"); - return 0; -} - -static struct label *_to_label(struct pv_disk *pvd) -{ - struct label *l; - struct lvm_label_info *info; - - if (!(l = dbg_malloc(sizeof(*l)))) { - log_err("Couldn't allocate label."); - return NULL; - } - - if (!(info = (struct lvm_label_info *) dbg_strdup(pvd->vg_name))) { - dbg_free(l); - return NULL; - } - - memcpy(&l->id, &pvd->pv_uuid, sizeof(l->id)); - strcpy(l->volume_type, "lvm"); - l->version[0] = 1; - l->version[0] = 0; - l->version[0] = 0; - l->extra_info = info; - - return l; -} - -static int _read(struct labeller *l, struct device *dev, struct label **label) -{ - struct pv_disk pvd; - int r = 0; - - if (!dev_open(dev, O_RDONLY)) { - stack; - return 0; - } - - r = read_pvd(dev, &pvd); - - if (!dev_close(dev)) - stack; - - if (!r) { - stack; - return 0; - } - - /* - * Convert the disk_list into a label structure. - */ - if (!(*label = _to_label(&pvd))) { - stack; - return 0; - } - - return 1; -} - -static void _destroy_label(struct labeller *l, struct label *label) -{ - dbg_free(label->extra_info); - dbg_free(label); -} - -static void _destroy(struct labeller *l) -{ - dbg_free(l); -} - -struct label_ops _lvm1_ops = { - can_handle: _can_handle, - write: _write, - remove: _remove, - read: _read, - verify: _can_handle, - destroy_label: _destroy_label, - destroy: _destroy -}; - -struct labeller *lvm1_labeller_create(void) -{ - struct labeller *l; - - if (!(l = dbg_malloc(sizeof(*l)))) { - log_err("Couldn't allocate labeller object."); - return NULL; - } - - l->ops = &_lvm1_ops; - l->private = NULL; - - return l; -} diff --git a/lib/format1/lvm1_label.h b/lib/format1/lvm1_label.h deleted file mode 100644 index 602f6a2cd..000000000 --- a/lib/format1/lvm1_label.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2002 Sistina Software (UK) Limited. - * - * This file is released under the LGPL. - */ - -#ifndef _LVM_LVM1_LABEL_H -#define _LVM_LVM1_LABEL_H - -/* - * This is what the 'extra_info' field of the label will point to - * if the label type is lvm1. - */ -struct lvm_label_info { - char volume_group[0]; -}; - - -struct labeller *lvm1_labeller_create(void); - -#endif diff --git a/lib/format1/vg_number.c b/lib/format1/vg_number.c index e1d278997..794e16cec 100644 --- a/lib/format1/vg_number.c +++ b/lib/format1/vg_number.c @@ -4,7 +4,7 @@ * This file is released under the LGPL. */ -#include "log.h" +#include "lib.h" #include "pool.h" #include "disk-rep.h" diff --git a/lib/locking/external_locking.c b/lib/locking/external_locking.c index 8d33f12c1..0dcc84069 100644 --- a/lib/locking/external_locking.c +++ b/lib/locking/external_locking.c @@ -5,111 +5,72 @@ * */ -#include "log.h" -#include "locking.h" +#include "lib.h" #include "locking_types.h" -#include "activate.h" -#include "config.h" #include "defaults.h" -#include "lvm-file.h" -#include "lvm-string.h" -#include "dbg_malloc.h" +#include "sharedlib.h" -#include -#include -#include -#include -#include -#include #include -#include -static void *locking_module = NULL; -static void (*end_fn) (void) = NULL; -static int (*lock_fn) (struct cmd_context * cmd, const char *resource, - int flags) = NULL; -static int (*init_fn) (int type, struct config_file * cf) = NULL; +static void *_locking_lib = NULL; +static void (*_end_fn) (void) = NULL; +static int (*_lock_fn) (struct cmd_context * cmd, const char *resource, + int flags) = NULL; +static int (*_init_fn) (int type, struct config_tree * cf) = NULL; -static int lock_resource(struct cmd_context *cmd, const char *resource, - int flags) +static int _lock_resource(struct cmd_context *cmd, const char *resource, + int flags) { - if (lock_fn) - return lock_fn(cmd, resource, flags); + if (_lock_fn) + return _lock_fn(cmd, resource, flags); else return 0; } -static void fin_external_locking(void) +static void _fin_external_locking(void) { - if (end_fn) - end_fn(); + if (_end_fn) + _end_fn(); - dlclose(locking_module); + dlclose(_locking_lib); - locking_module = NULL; - end_fn = NULL; - lock_fn = NULL; + _locking_lib = NULL; + _init_fn = NULL; + _end_fn = NULL; + _lock_fn = NULL; } -int init_external_locking(struct locking_type *locking, struct config_file *cf) +int init_external_locking(struct locking_type *locking, struct config_tree *cf) { - char _lock_lib[PATH_MAX]; + const char *libname; - if (locking_module) { + if (_locking_lib) { log_error("External locking already initialised"); return 1; } - locking->lock_resource = lock_resource; - locking->fin_locking = fin_external_locking; - /* Get locking module name from config file */ - strncpy(_lock_lib, find_config_str(cf->root, "global/locking_library", - '/', "lvm2_locking.so"), - sizeof(_lock_lib)); + locking->lock_resource = _lock_resource; + locking->fin_locking = _fin_external_locking; - /* If there is a module_dir in the config file then - look for the locking module in there first and then - using the normal dlopen(3) mechanism of looking - down LD_LIBRARY_PATH and /lib, /usr/lib. - If course, if the library name starts with a slash then - just use the name... */ - if (_lock_lib[0] != '/') { - struct stat st; - char _lock_lib1[PATH_MAX]; + libname = find_config_str(cf->root, "global/locking_library", '/', + DEFAULT_LOCKING_LIB); - lvm_snprintf(_lock_lib1, sizeof(_lock_lib1), - "%s/%s", - find_config_str(cf->root, "global/module_dir", - '/', "RUBBISH"), _lock_lib); - - /* Does it exist ? */ - if (stat(_lock_lib1, &st) == 0) { - strcpy(_lock_lib, _lock_lib1); - } - } - - log_very_verbose("Opening locking library %s", _lock_lib); - - locking_module = dlopen(_lock_lib, RTLD_LAZY); - if (!locking_module) { - log_error("Unable to open external locking module %s", - _lock_lib); + if (!(_locking_lib = load_shared_library(cf, libname, "locking"))) { + stack; return 0; } /* Get the functions we need */ - init_fn = dlsym(locking_module, "init_locking"); - lock_fn = dlsym(locking_module, "lock_resource"); - end_fn = dlsym(locking_module, "end_locking"); - - /* Are they all there ? */ - if (!end_fn || !init_fn || !lock_fn) { - log_error ("Shared library %s does not contain locking " - "functions", _lock_lib); - dlclose(locking_module); + if (!(_init_fn = dlsym(_locking_lib, "init_locking")) || + !(_lock_fn = dlsym(_locking_lib, "lock_resource")) || + !(_end_fn = dlsym(_locking_lib, "end_locking"))) { + log_error("Shared library %s does not contain locking " + "functions", libname); + dlclose(_locking_lib); + _locking_lib = NULL; return 0; } - log_verbose("Opened external locking module %s", _lock_lib); - return init_fn(2, cf); + log_verbose("Loaded external locking library %s", libname); + return _init_fn(2, cf); } diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c index bac54125c..ab429078b 100644 --- a/lib/locking/file_locking.c +++ b/lib/locking/file_locking.c @@ -5,7 +5,7 @@ * */ -#include "log.h" +#include "lib.h" #include "locking.h" #include "locking_types.h" #include "activate.h" @@ -13,11 +13,9 @@ #include "defaults.h" #include "lvm-file.h" #include "lvm-string.h" -#include "dbg_malloc.h" #include #include -#include #include #include #include @@ -117,13 +115,16 @@ static int _lock_file(const char *file, int flags) struct lock_list *ll; struct stat buf1, buf2; + char state; switch (flags & LCK_TYPE_MASK) { case LCK_READ: operation = LOCK_SH; + state = 'R'; break; case LCK_WRITE: operation = LOCK_EX; + state = 'W'; break; case LCK_UNLOCK: return _release_lock(file); @@ -142,7 +143,8 @@ static int _lock_file(const char *file, int flags) ll->lf = -1; - log_very_verbose("Locking %s", ll->res); + log_very_verbose("Locking %s %c%c", ll->res, state, + flags & LCK_NONBLOCK ? ' ' : 'B'); do { if (ll->lf > -1) close(ll->lf); @@ -197,10 +199,6 @@ int file_lock_resource(struct cmd_context *cmd, const char *resource, int flags) return 0; break; case LCK_LV: - /* Skip if driver isn't loaded */ - /* FIXME Use /proc/misc instead? */ - if (!driver_version(NULL, 0)) - return 1; switch (flags & LCK_TYPE_MASK) { case LCK_UNLOCK: if (!lv_resume_if_active(cmd, resource)) @@ -231,7 +229,7 @@ int file_lock_resource(struct cmd_context *cmd, const char *resource, int flags) return 1; } -int init_file_locking(struct locking_type *locking, struct config_file *cf) +int init_file_locking(struct locking_type *locking, struct config_tree *cf) { locking->lock_resource = file_lock_resource; locking->fin_locking = fin_file_locking; diff --git a/lib/locking/locking.c b/lib/locking/locking.c index e80f6af73..ff00dd2b1 100644 --- a/lib/locking/locking.c +++ b/lib/locking/locking.c @@ -5,13 +5,12 @@ * */ -#include "log.h" +#include "lib.h" #include "locking.h" #include "locking_types.h" #include "lvm-string.h" #include "activate.h" #include "toolcontext.h" -#include "defaults.h" #include #include @@ -72,7 +71,7 @@ static inline void _update_lock_count(int flags) /* * Select a locking type */ -int init_locking(int type, struct config_file *cf) +int init_locking(int type, struct config_tree *cf) { switch (type) { case 0: @@ -122,9 +121,12 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname) struct stat info; char path[PATH_MAX]; - if (lvm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", - find_config_str(cmd->cf->root, "global/proc", '/', - DEFAULT_PROC_DIR), vgname) < 0) { + /* We'll allow operations on orphans */ + if (!*vgname) + return 1; + + if (lvm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir, + vgname) < 0) { log_error("LVM1 proc VG pathname too long for %s", vgname); return 0; } diff --git a/lib/locking/locking.h b/lib/locking/locking.h index 43ba00230..92a44f3ed 100644 --- a/lib/locking/locking.h +++ b/lib/locking/locking.h @@ -9,7 +9,7 @@ #include "uuid.h" #include "config.h" -int init_locking(int type, struct config_file *cf); +int init_locking(int type, struct config_tree *cf); void fin_locking(void); /* diff --git a/lib/locking/locking_types.h b/lib/locking/locking_types.h index a8a94ad1d..6ecec001d 100644 --- a/lib/locking/locking_types.h +++ b/lib/locking/locking_types.h @@ -24,9 +24,9 @@ struct locking_type { /* * Locking types */ -int init_no_locking(struct locking_type *locking, struct config_file *cf); +int init_no_locking(struct locking_type *locking, struct config_tree *cf); -int init_file_locking(struct locking_type *locking, struct config_file *cf); +int init_file_locking(struct locking_type *locking, struct config_tree *cf); -int init_external_locking(struct locking_type *locking, struct config_file *cf); +int init_external_locking(struct locking_type *locking, struct config_tree *cf); diff --git a/lib/locking/no_locking.c b/lib/locking/no_locking.c index b4af79664..1fd8f8dbc 100644 --- a/lib/locking/no_locking.c +++ b/lib/locking/no_locking.c @@ -5,7 +5,7 @@ * */ -#include "log.h" +#include "lib.h" #include "locking.h" #include "locking_types.h" #include "lvm-string.h" @@ -51,7 +51,7 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource, return 1; } -int init_no_locking(struct locking_type *locking, struct config_file *cf) +int init_no_locking(struct locking_type *locking, struct config_tree *cf) { locking->lock_resource = _no_lock_resource; locking->fin_locking = _no_fin_locking; diff --git a/lib/log/log.c b/lib/log/log.c index ce576fcf5..9ee63e652 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -4,7 +4,8 @@ * This file is released under the LGPL. */ -#include "log.h" +#include "lib.h" + #include #include @@ -22,7 +23,7 @@ static int _ignorelockingfailure = 0; static char _cmd_name[30] = ""; static char _msg_prefix[30] = " "; -void init_log(FILE * fp) +void init_log(FILE *fp) { _log = fp; } @@ -57,9 +58,9 @@ void init_verbose(int level) void init_test(int level) { + if (!_test && level) + log_print("Test mode: Metadata will NOT be updated."); _test = level; - if (_test) - log_print("Test mode. Metadata will NOT be updated."); } void init_partial(int level) diff --git a/lib/log/log.h b/lib/log/log.h index 112e2df56..6ed54016a 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -28,8 +28,8 @@ * */ -#include -#include +#include /* FILE */ +#include /* strerror() */ #include #define _LOG_DEBUG 7 @@ -91,8 +91,3 @@ void print_log(int level, const char *file, int line, const char *format, ...) #endif -/* - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/lib/misc/crc.c b/lib/misc/crc.c new file mode 100644 index 000000000..6b0514472 --- /dev/null +++ b/lib/misc/crc.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#include "lib.h" +#include "lvm-types.h" + +/* Calculate an endian-independent CRC of supplied buffer */ +uint32_t calc_crc(uint32_t initial, void *buf, uint32_t size) +{ + static const uint32_t crctab[] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + uint32_t i, crc = initial; + uint8_t *data = (uint8_t *) buf; + + for (i = 0; i < size; i++) { + crc ^= *data++; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + } + return crc; +} diff --git a/lib/misc/crc.h b/lib/misc/crc.h new file mode 100644 index 000000000..fcef90824 --- /dev/null +++ b/lib/misc/crc.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#ifndef _LVM_CRC_H +#define _LVM_CRC_H + +#include "lvm-types.h" + +#define INITIAL_CRC 0xf597a6cf + +uint32_t calc_crc(uint32_t initial, void *buf, uint32_t size); + +#endif diff --git a/lib/misc/lib.h b/lib/misc/lib.h new file mode 100644 index 000000000..415ca2c36 --- /dev/null +++ b/lib/misc/lib.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +/* + * This file must be included first by every source file. + */ +#ifndef _LVM_LIB_H +#define _LVM_LIB_H + +#define _REENTRANT + +#include "log.h" +#include "dbg_malloc.h" + +#endif diff --git a/lib/misc/lvm-file.c b/lib/misc/lvm-file.c index 0f6c3b5c9..cde9e9e42 100644 --- a/lib/misc/lvm-file.c +++ b/lib/misc/lvm-file.c @@ -4,14 +4,11 @@ * This file is released under the LGPL. */ -#include "log.h" +#include "lib.h" #include "lvm-file.h" #include "lvm-string.h" -#include "dbg_malloc.h" -#include #include -#include #include #include #include diff --git a/lib/misc/sharedlib.c b/lib/misc/sharedlib.c new file mode 100644 index 000000000..b07e3133a --- /dev/null +++ b/lib/misc/sharedlib.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2002 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + * + */ + +#include "lib.h" +#include "config.h" +#include "lvm-string.h" + +#include +#include +#include + +void *load_shared_library(struct config_tree *cf, const char *libname, + const char *desc) +{ + char path[PATH_MAX]; + struct stat info; + const char *lib_dir; + void *library; + + /* If libname doesn't begin with '/' then use lib_dir/libname, + * if present */ + if (libname[0] == '/' || + !(lib_dir = find_config_str(cf->root, "global/library_dir", + '/', 0)) || + (lvm_snprintf(path, sizeof(path), "%s/%s", lib_dir, + libname) == -1) || stat(path, &info) == -1) + strncpy(path, libname, sizeof(path)); + + log_very_verbose("Opening shared %s library %s", desc, path); + + if (!(library = dlopen(path, RTLD_LAZY))) + log_error("Unable to open external %s library %s", desc, path); + + return library; +} diff --git a/lib/misc/sharedlib.h b/lib/misc/sharedlib.h new file mode 100644 index 000000000..407527564 --- /dev/null +++ b/lib/misc/sharedlib.h @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2002 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + * + */ + +#include "config.h" + +void *load_shared_library(struct config_tree *cf, const char *libname, + const char *what); diff --git a/lib/mm/dbg_malloc.c b/lib/mm/dbg_malloc.c index 157da0c07..7b142488c 100644 --- a/lib/mm/dbg_malloc.c +++ b/lib/mm/dbg_malloc.c @@ -4,14 +4,11 @@ * This file is released under the LGPL. */ +#include "lib.h" +#include "lvm-types.h" + #include #include -#include -#include -#include - -#include "dbg_malloc.h" -#include "log.h" struct memblock { struct memblock *prev, *next; /* All allocated blocks are linked */ diff --git a/lib/mm/pool-debug.c b/lib/mm/pool-debug.c index 4cc942312..3660defcf 100644 --- a/lib/mm/pool-debug.c +++ b/lib/mm/pool-debug.c @@ -4,9 +4,8 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "pool.h" -#include "dbg_malloc.h" -#include "log.h" #include diff --git a/lib/mm/pool-fast.c b/lib/mm/pool-fast.c index 73b477f31..a8825054d 100644 --- a/lib/mm/pool-fast.c +++ b/lib/mm/pool-fast.c @@ -4,13 +4,9 @@ * This file is released under the LGPL. */ -#include -#include -#include - +#include "lib.h" #include "pool.h" -#include "dbg_malloc.h" -#include "log.h" +#include "lvm-types.h" struct chunk { char *begin, *end; diff --git a/lib/mm/xlate.h b/lib/mm/xlate.h index a72e6fe98..4af5c59f3 100644 --- a/lib/mm/xlate.h +++ b/lib/mm/xlate.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2001 Sistina Software (UK) Limited. * - * This file is released under the LGPL. + * This file is released under the GPL. * */ @@ -10,8 +10,8 @@ #include -#define xlate16(x) __cpu_to_le16((x)); -#define xlate32(x) __cpu_to_le32((x)); -#define xlate64(x) __cpu_to_le64((x)); +#define xlate16(x) __cpu_to_le16((x)) +#define xlate32(x) __cpu_to_le32((x)) +#define xlate64(x) __cpu_to_le64((x)) #endif diff --git a/lib/regex/matcher.c b/lib/regex/matcher.c index 8e247447c..054fb2fcc 100644 --- a/lib/regex/matcher.c +++ b/lib/regex/matcher.c @@ -4,14 +4,12 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "matcher.h" #include "parse_rx.h" -#include "log.h" #include "ttree.h" #include "bitset.h" -#include -#include #include struct dfa_state { @@ -330,8 +328,8 @@ struct matcher *matcher_create(struct pool *mem, const char **patterns, int num) return NULL; } -static inline struct dfa_state * -_step_matcher(unsigned char c, struct dfa_state *cs, int *r) +static inline struct dfa_state *_step_matcher(unsigned char c, + struct dfa_state *cs, int *r) { if (!(cs = cs->lookup[c])) return NULL; @@ -356,7 +354,7 @@ int matcher_run(struct matcher *m, const char *b) _step_matcher(DOLLAR_CHAR, cs, &r); - out: + out: /* subtract 1 to get back to zero index */ return r - 1; } diff --git a/lib/regex/parse_rx.c b/lib/regex/parse_rx.c index 108ec4178..713acb505 100644 --- a/lib/regex/parse_rx.c +++ b/lib/regex/parse_rx.c @@ -4,13 +4,9 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "parse_rx.h" #include "bitset.h" -#include "log.h" - -#include -#include -#include struct parse_sp { /* scratch pad for the parsing process */ struct pool *mem; diff --git a/lib/regex/ttree.c b/lib/regex/ttree.c index 32f070a65..2e8da1fc1 100644 --- a/lib/regex/ttree.c +++ b/lib/regex/ttree.c @@ -4,9 +4,9 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "ttree.h" #include "pool.h" -#include "log.h" struct node { unsigned k; diff --git a/lib/uuid/uuid.c b/lib/uuid/uuid.c index bff912dec..7c6f5a116 100644 --- a/lib/uuid/uuid.c +++ b/lib/uuid/uuid.c @@ -4,10 +4,9 @@ * This file is released under the LGPL. */ +#include "lib.h" #include "uuid.h" -#include "log.h" -#include #include #include #include