1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-05-14 22:50:47 +03:00

filters: remove cache file in persistent filter

It creates problems because it's not always correct,
and it doesn't actually help much.
This commit is contained in:
David Teigland 2018-06-13 14:00:47 -05:00
parent 17f5572bc9
commit 22c5467add
6 changed files with 8 additions and 299 deletions

View File

@ -1195,20 +1195,15 @@ bad:
*/
int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
struct dev_filter *filter = NULL, *filter_components[2] = {0};
int nr_filt;
struct stat st;
const struct dm_config_node *cn;
struct timespec ts, cts;
if (!cmd->initialized.connections) {
log_error(INTERNAL_ERROR "connections must be initialized before filters");
return 0;
}
cmd->dump_filter = 0;
cmd->lvmetad_filter = _init_lvmetad_filter_chain(cmd);
if (!cmd->lvmetad_filter)
goto_bad;
@ -1246,10 +1241,7 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
cmd->lvmetad_filter = NULL;
}
if (!(dev_cache = find_config_tree_str(cmd, devices_cache_CFG, NULL)))
goto_bad;
if (!(filter = persistent_filter_create(cmd->dev_types, filter, dev_cache))) {
if (!(filter = persistent_filter_create(cmd->dev_types, filter))) {
log_verbose("Failed to create persistent device filter.");
goto bad;
}
@ -1267,29 +1259,6 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
} else
cmd->full_filter = filter;
/* Should we ever dump persistent filter state? */
if (find_config_tree_bool(cmd, devices_write_cache_state_CFG, NULL))
cmd->dump_filter = 1;
if (!*cmd->system_dir)
cmd->dump_filter = 0;
/*
* Only load persistent filter device cache on startup if it is newer
* than the config file and this is not a long-lived process. Also avoid
* it when lvmetad is enabled.
*/
if (!find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL) &&
load_persistent_cache && !cmd->is_long_lived &&
!stat(dev_cache, &st)) {
lvm_stat_ctim(&ts, &st);
cts = config_file_timestamp(cmd->cft);
if (timespeccmp(&ts, &cts, >) &&
!persistent_filter_load(cmd->filter, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
}
cmd->initialized.filters = 1;
return 1;
bad:
@ -2166,10 +2135,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
struct dm_config_tree *cft_cmdline;
int flags;
if (cmd->dump_filter && cmd->filter && cmd->filter->dump &&
!cmd->filter->dump(cmd->filter, 1))
stack;
archive_exit(cmd);
backup_exit(cmd);
lvmcache_destroy(cmd, 0, 0);

View File

@ -179,7 +179,6 @@ struct cmd_context {
struct dev_filter *lvmetad_filter; /* pre-lvmetad filter chain */
struct dev_filter *filter; /* post-lvmetad filter chain */
struct dev_filter *full_filter; /* lvmetad_filter + filter */
int dump_filter; /* Dump filter when exiting? */
/*
* Configuration.

View File

@ -312,24 +312,17 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D
"The syntax is the same as devices/filter. Devices rejected by\n"
"global_filter are not opened by LVM.\n")
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19),
"This has been replaced by the devices/cache_dir setting.\n",
"Cache file path.\n")
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL,
"This setting is no longer used.\n")
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), 0, NULL,
"Directory in which to store the device cache file.\n"
"The results of filtering are cached on disk to avoid rescanning dud\n"
"devices (which can take a very long time). By default this cache is\n"
"stored in a file named .cache. It is safe to delete this file; the\n"
"tools regenerate it. If obtain_device_list_from_udev is enabled, the\n"
"list of devices is obtained from udev and any existing .cache file\n"
"is removed.\n")
"This setting is no longer used.\n")
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, 0, NULL,
"A prefix used before the .cache file name. See devices/cache_dir.\n")
"This setting is no longer used.\n")
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, 0, NULL,
"Enable/disable writing the cache file. See devices/cache_dir.\n")
"This setting is no longer used.\n")
cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"List of additional acceptable block device types.\n"

View File

@ -58,18 +58,6 @@ static void _composite_destroy(struct dev_filter *f)
free(f);
}
static int _dump(struct dev_filter *f, int merge_existing)
{
struct dev_filter **filters;
for (filters = (struct dev_filter **) f->private; *filters; ++filters)
if ((*filters)->dump &&
!(*filters)->dump(*filters, merge_existing))
return_0;
return 1;
}
static void _wipe(struct dev_filter *f)
{
struct dev_filter **filters;
@ -102,7 +90,6 @@ struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct d
cft->passes_filter = use_dev_ext_info ? _and_p_with_dev_ext_info : _and_p;
cft->destroy = _composite_destroy;
cft->dump = _dump;
cft->wipe = _wipe;
cft->use_count = 0;
cft->private = filters_copy;

View File

@ -17,13 +17,10 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/config/config.h"
#include "lib/misc/lvm-file.h"
struct pfilter {
char *file;
struct dm_hash_table *devices;
struct dev_filter *real;
struct timespec ctime;
struct dev_types *dt;
};
@ -44,11 +41,6 @@ struct pfilter {
* times. A device should be checked against the filter once, and then not
* need to be checked again. With scanning now controlled, we could probably
* do this.
*
* FIXME: "persistent" isn't a great name for this caching filter. This filter
* at one time saved its cache results to a file, which is how it got the name.
* That .cache file does not work well, causes problems, and is no longer used
* by default. The old code for it should be removed.
*/
/*
@ -76,214 +68,6 @@ static void _persistent_filter_wipe(struct dev_filter *f)
dm_hash_wipe(pf->devices);
}
static int _read_array(struct pfilter *pf, struct dm_config_tree *cft,
const char *path, void *data)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
if (!(cn = dm_config_find_node(cft->root, path))) {
log_very_verbose("Couldn't find %s array in '%s'",
path, pf->file);
return 0;
}
/*
* iterate through the array, adding
* devices as we go.
*/
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING) {
log_verbose("Devices array contains a value "
"which is not a string ... ignoring");
continue;
}
if (!dm_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;
}
int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out)
{
struct pfilter *pf = (struct pfilter *) f->private;
struct dm_config_tree *cft;
struct stat info;
int r = 0;
if (obtain_device_list_from_udev()) {
if (!stat(pf->file, &info)) {
log_very_verbose("Obtaining device list from udev. "
"Removing obsolete %s.",
pf->file);
if (unlink(pf->file) < 0 && errno != EROFS)
log_sys_error("unlink", pf->file);
}
return 1;
}
if (!stat(pf->file, &info))
lvm_stat_ctim(&pf->ctime, &info);
else {
log_very_verbose("%s: stat failed: %s", pf->file,
strerror(errno));
return_0;
}
if (!(cft = config_open(CONFIG_FILE_SPECIAL, pf->file, 1)))
return_0;
if (!config_file_read(cft))
goto_out;
log_debug_devs("Loading persistent filter cache from %s", pf->file);
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
PF_GOOD_DEVICE);
/* We don't gain anything by holding invalid devices */
/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
PF_BAD_DEVICE); */
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
out:
if (r && cft_out)
*cft_out = cft;
else
config_destroy(cft);
return r;
}
static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
void *data)
{
void *d;
int first = 1;
char buf[2 * PATH_MAX];
struct dm_hash_node *n;
for (n = dm_hash_get_first(pf->devices); n;
n = dm_hash_get_next(pf->devices, n)) {
d = dm_hash_get_data(pf->devices, n);
if (d != data)
continue;
if (!first)
fprintf(fp, ",\n");
else {
fprintf(fp, "\t%s=[\n", path);
first = 0;
}
dm_escape_double_quotes(buf, dm_hash_get_key(pf->devices, n));
fprintf(fp, "\t\t\"%s\"", buf);
}
if (!first)
fprintf(fp, "\n\t]\n");
}
static int _persistent_filter_dump(struct dev_filter *f, int merge_existing)
{
struct pfilter *pf;
char *tmp_file;
struct stat info, info2;
struct timespec ts;
struct dm_config_tree *cft = NULL;
FILE *fp;
int lockfd;
int r = 0;
if (obtain_device_list_from_udev())
return 1;
if (!f)
return_0;
pf = (struct pfilter *) f->private;
if (!dm_hash_get_num_entries(pf->devices)) {
log_very_verbose("Internal persistent device cache empty "
"- not writing to %s", pf->file);
return 1;
}
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);
while (1) {
if ((lockfd = fcntl_lock_file(pf->file, F_WRLCK, 0)) < 0)
return_0;
/*
* Ensure we locked the file we expected
*/
if (fstat(lockfd, &info)) {
log_sys_error("fstat", pf->file);
goto out;
}
if (stat(pf->file, &info2)) {
log_sys_error("stat", pf->file);
goto out;
}
if (is_same_inode(info, info2))
break;
fcntl_unlock_file(lockfd);
}
/*
* If file contents changed since we loaded it, merge new contents
*/
lvm_stat_ctim(&ts, &info);
if (merge_existing && timespeccmp(&ts, &pf->ctime, !=))
/* Keep cft open to avoid losing lock */
persistent_filter_load(f, &cft);
tmp_file = alloca(strlen(pf->file) + 5);
sprintf(tmp_file, "%s.tmp", pf->file);
if (!(fp = fopen(tmp_file, "w"))) {
/* EACCES has been reported over NFS */
if (errno != EROFS && errno != EACCES)
log_sys_error("fopen", tmp_file);
goto out;
}
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);
/* We don't gain anything by remembering invalid devices */
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
if (lvm_fclose(fp, tmp_file))
goto_out;
if (rename(tmp_file, pf->file))
log_error("%s: rename to %s failed: %s", tmp_file, pf->file,
strerror(errno));
r = 1;
out:
fcntl_unlock_file(lockfd);
if (cft)
config_destroy(cft);
return r;
}
static int _lookup_p(struct dev_filter *f, struct device *dev)
{
struct pfilter *pf = (struct pfilter *) f->private;
@ -361,19 +145,15 @@ static void _persistent_destroy(struct dev_filter *f)
log_error(INTERNAL_ERROR "Destroying persistent filter while in use %u times.", f->use_count);
dm_hash_destroy(pf->devices);
free(pf->file);
pf->real->destroy(pf->real);
free(pf);
free(f);
}
struct dev_filter *persistent_filter_create(struct dev_types *dt,
struct dev_filter *real,
const char *file)
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *real)
{
struct pfilter *pf;
struct dev_filter *f = NULL;
struct stat info;
if (!(pf = zalloc(sizeof(*pf)))) {
log_error("Allocation of persistent filter failed.");
@ -382,11 +162,6 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
pf->dt = dt;
if (!(pf->file = strdup(file))) {
log_error("Filename duplication for persistent filter failed.");
goto bad;
}
pf->real = real;
if (!(_init_hash(pf))) {
@ -399,23 +174,17 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
goto bad;
}
/* Only merge cache file before dumping it if it changed externally. */
if (!stat(pf->file, &info))
lvm_stat_ctim(&pf->ctime, &info);
f->passes_filter = _lookup_p;
f->destroy = _persistent_destroy;
f->use_count = 0;
f->private = pf;
f->wipe = _persistent_filter_wipe;
f->dump = _persistent_filter_dump;
log_debug_devs("Persistent filter initialised.");
return f;
bad:
free(pf->file);
if (pf->devices)
dm_hash_destroy(pf->devices);
free(pf);

View File

@ -27,9 +27,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
struct dev_filter *mpath_filter_create(struct dev_types *dt);
struct dev_filter *partitioned_filter_create(struct dev_types *dt);
struct dev_filter *persistent_filter_create(struct dev_types *dt,
struct dev_filter *f,
const char *file);
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *f);
struct dev_filter *sysfs_filter_create(void);
struct dev_filter *signature_filter_create(struct dev_types *dt);
@ -54,6 +52,4 @@ typedef enum {
} filter_mode_t;
struct dev_filter *usable_filter_create(struct dev_types *dt, filter_mode_t mode);
int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out);
#endif /* _LVM_FILTER_H */