diff --git a/lib/datastruct/hash.c b/lib/datastruct/hash.c index 002ff7fbb..b9c292062 100644 --- a/lib/datastruct/hash.c +++ b/lib/datastruct/hash.c @@ -181,6 +181,22 @@ void hash_iterate(struct hash_table *t, iterate_fn f) f(c->data); } +void hash_wipe(struct hash_table *t) +{ + struct hash_node **c, *old; + int i; + + for (i = 0; i < t->num_slots; i++) { + c = &t->slots[i]; + while (*c) { + old = *c; + *c = (*c)->next; + dbg_free(old); + t->num_nodes--; + } + } +} + char *hash_get_key(struct hash_table *t, struct hash_node *n) { return n->key; diff --git a/lib/datastruct/hash.h b/lib/datastruct/hash.h index bd0c4eba2..d611ca9b0 100644 --- a/lib/datastruct/hash.h +++ b/lib/datastruct/hash.h @@ -14,6 +14,7 @@ typedef void (*iterate_fn)(void *data); struct hash_table *hash_create(unsigned size_hint); void hash_destroy(struct hash_table *t); +void hash_wipe(struct hash_table *t); void *hash_lookup(struct hash_table *t, const char *key); int hash_insert(struct hash_table *t, const char *key, void *data); diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c index 4f7cef869..9750b398d 100644 --- a/lib/filters/filter-persistent.c +++ b/lib/filters/filter-persistent.c @@ -42,8 +42,8 @@ int persistent_filter_wipe(struct dev_filter *f) { struct pfilter *pf = (struct pfilter *) f->private; - hash_destroy(pf->devices); - return _init_hash(pf); + hash_wipe(pf->devices); + return 1; } static int _read_array(struct pfilter *pf, struct config_file *cf, @@ -53,8 +53,8 @@ static int _read_array(struct pfilter *pf, struct config_file *cf, struct config_value *cv; if (!(cn = find_config_node(cf->root, path, '/'))) { - log_verbose("Couldn't find 'valid_devices' array in '%s'", - pf->file); + log_very_verbose("Couldn't find %s array in '%s'", + path, pf->file); return 0; } @@ -64,7 +64,7 @@ static int _read_array(struct pfilter *pf, struct config_file *cf, */ for (cv = cn->v; cv; cv = cv->next) { if (cv->type != CFG_STRING) { - log_verbose("Valid_devices array contains a value " + log_verbose("Devices array contains a value " "which is not a string ... ignoring"); continue; } @@ -93,8 +93,10 @@ int persistent_filter_load(struct dev_filter *f) goto out; } - if (_read_array(pf, cf, "/valid_devices", PF_GOOD_DEVICE) && - _read_array(pf, cf, "/invalid_devices", PF_BAD_DEVICE)) + _read_array(pf, cf, "persistent_filter_cache/valid_devices", PF_GOOD_DEVICE); + _read_array(pf, cf, "persistent_filter_cache/invalid_devices", PF_BAD_DEVICE); + + if (hash_get_num_entries(pf->devices)) r = 1; out: @@ -109,8 +111,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path, int first = 1; struct hash_node *n; - fprintf(fp, "%s=[\n", path); - for (n = hash_get_first(pf->devices); n; + for (n = hash_get_first(pf->devices); n; n = hash_get_next(pf->devices, n)) { d = hash_get_data(pf->devices, n); @@ -119,13 +120,18 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path, if (!first) fprintf(fp, ",\n"); - else + else { + fprintf(fp, "\t%s=[\n", path); first = 0; + } - fprintf(fp, "\t\"%s\"", hash_get_key(pf->devices, n)); + fprintf(fp, "\t\t\"%s\"", hash_get_key(pf->devices, n)); } - fprintf(fp, "\n]\n"); + if (!first) + fprintf(fp, "\n\t]\n"); + + return; } int persistent_filter_dump(struct dev_filter *f) @@ -143,10 +149,12 @@ int persistent_filter_dump(struct dev_filter *f) } fprintf(fp, "# This file is automatically maintained by lvm.\n\n"); + fprintf(fp, "persistent_filter_cache {\n"); _write_array(pf, fp, "valid_devices", PF_GOOD_DEVICE); _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); + fprintf(fp, "}\n"); fclose(fp); return 1; } diff --git a/tools/lvm.c b/tools/lvm.c index fbfd0e2ac..926922d3c 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -49,6 +49,8 @@ static struct command *_commands; struct io_space *ios; static struct dev_filter *_filter; +/* Whether or not to dump persistent filter state */ +static int dump_filter; static struct config_file *_cf; static int _interactive; @@ -642,6 +644,8 @@ static struct dev_filter *filter_setup(void) struct dev_filter *f3, *f4; struct stat st; + dump_filter = 0; + if (!(f3 = filter_components_setup())) return 0; @@ -650,9 +654,13 @@ static struct dev_filter *filter_setup(void) if (!(f4 = persistent_filter_create(f3, lvm_cache))) { log_error("Failed to create persistent device filter"); - return f3; + return 0; } + /* Should we ever dump persistent filter state? */ + if (find_config_int(_cf->root, "devices/write_cache_state", '/', 1)) + dump_filter = 1; + if (!stat(lvm_cache, &st) && !persistent_filter_load(f4)) log_verbose("Failed to load existing device cache from %s", lvm_cache); @@ -728,6 +736,9 @@ static void __fin_commands(void) static void fin(void) { + if (dump_filter) + persistent_filter_dump(_filter); + ios->destroy(ios); _filter->destroy(_filter); dev_cache_exit(); diff --git a/tools/pvscan.c b/tools/pvscan.c index 6e1cb4878..7adc59f6e 100644 --- a/tools/pvscan.c +++ b/tools/pvscan.c @@ -53,8 +53,10 @@ int pvscan(int argc, char **argv) arg_count(exported_ARG) ? "of exported volume group(s)" : "in no volume group"); - log_verbose("Walking through all physical volumes"); + log_verbose("Wiping cache of LVM-capable devices"); + persistent_filter_wipe(ios->filter); + log_verbose("Walking through all physical volumes"); if (!(pvs = ios->get_pvs(ios))) return ECMD_FAILED; diff --git a/tools/vgscan.c b/tools/vgscan.c index f8cf53066..a205be71f 100644 --- a/tools/vgscan.c +++ b/tools/vgscan.c @@ -29,6 +29,9 @@ int vgscan(int argc, char **argv) return EINVALID_CMD_LINE; } + log_verbose("Wiping cache of LVM-capable devices"); + persistent_filter_wipe(ios->filter); + log_print("Reading all physical volumes (this may take a while...)"); return process_each_vg(argc, argv, &vgscan_single);