mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-31 09:49:29 +03:00
dev-cache: radix_tree for names
This commit is contained in:
@ -48,7 +48,7 @@ struct dir_list {
|
|||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct dm_pool *mem;
|
struct dm_pool *mem;
|
||||||
struct dm_hash_table *names;
|
struct radix_tree *names;
|
||||||
struct dm_hash_table *vgid_index;
|
struct dm_hash_table *vgid_index;
|
||||||
struct dm_hash_table *lvid_index;
|
struct dm_hash_table *lvid_index;
|
||||||
struct radix_tree *sysfs_only_devices; /* see comments in _get_device_for_sysfs_dev_name_using_devno */
|
struct radix_tree *sysfs_only_devices; /* see comments in _get_device_for_sysfs_dev_name_using_devno */
|
||||||
@ -345,9 +345,10 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
|
|||||||
struct dm_str_list *strl;
|
struct dm_str_list *strl;
|
||||||
const char *oldpath;
|
const char *oldpath;
|
||||||
int prefer_old = 1;
|
int prefer_old = 1;
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
|
||||||
if (hash == REHASH)
|
if (hash == REHASH)
|
||||||
dm_hash_remove(_cache.names, path);
|
radix_tree_remove(_cache.names, path, path_len);
|
||||||
|
|
||||||
/* Is name already there? */
|
/* Is name already there? */
|
||||||
dm_list_iterate_items(strl, &dev->aliases)
|
dm_list_iterate_items(strl, &dev->aliases)
|
||||||
@ -378,7 +379,7 @@ static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
|
|||||||
dm_list_add_h(&dev->aliases, &sl->list);
|
dm_list_add_h(&dev->aliases, &sl->list);
|
||||||
out:
|
out:
|
||||||
if ((hash != NO_HASH) &&
|
if ((hash != NO_HASH) &&
|
||||||
!dm_hash_insert(_cache.names, path, dev)) {
|
!radix_tree_insert_ptr(_cache.names, path, path_len, dev)) {
|
||||||
log_error("Couldn't add name to hash in dev cache.");
|
log_error("Couldn't add name to hash in dev cache.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -656,7 +657,7 @@ static int _index_dev_by_vgid_and_lvid(struct cmd_context *cmd, struct device *d
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(holder_dev = (struct device *) dm_hash_lookup(_cache.names, devpath))) {
|
if (!(holder_dev = dev_hash_get(devpath))) {
|
||||||
/*
|
/*
|
||||||
* Cope with situation where canonical /<dev_dir>/<dirent->d_name>
|
* Cope with situation where canonical /<dev_dir>/<dirent->d_name>
|
||||||
* does not exist, but some other node name or symlink exists in
|
* does not exist, but some other node name or symlink exists in
|
||||||
@ -750,8 +751,7 @@ void dev_cache_failed_path(struct device *dev, const char *path)
|
|||||||
{
|
{
|
||||||
struct dm_str_list *strl;
|
struct dm_str_list *strl;
|
||||||
|
|
||||||
if (dm_hash_lookup(_cache.names, path))
|
radix_tree_remove(_cache.names, path, strlen(path));
|
||||||
dm_hash_remove(_cache.names, path);
|
|
||||||
|
|
||||||
dm_list_iterate_items(strl, &dev->aliases) {
|
dm_list_iterate_items(strl, &dev->aliases) {
|
||||||
if (!strcmp(strl->str, path)) {
|
if (!strcmp(strl->str, path)) {
|
||||||
@ -772,7 +772,7 @@ static int _insert_dev(const char *path, dev_t d)
|
|||||||
struct device *dev_by_path;
|
struct device *dev_by_path;
|
||||||
|
|
||||||
dev_by_devt = _dev_cache_lookup_devno(_cache.devices, d);
|
dev_by_devt = _dev_cache_lookup_devno(_cache.devices, d);
|
||||||
dev_by_path = (struct device *) dm_hash_lookup(_cache.names, path);
|
dev_by_path = dev_hash_get(path);
|
||||||
dev = dev_by_devt;
|
dev = dev_by_devt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1262,7 +1262,7 @@ static void _drop_all_aliases(struct device *dev)
|
|||||||
|
|
||||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||||
log_debug("Drop alias for %u:%u %s.", MAJOR(dev->dev), MINOR(dev->dev), strl->str);
|
log_debug("Drop alias for %u:%u %s.", MAJOR(dev->dev), MINOR(dev->dev), strl->str);
|
||||||
dm_hash_remove(_cache.names, strl->str);
|
radix_tree_remove(_cache.names, strl->str, strlen(strl->str));
|
||||||
dm_list_del(&strl->list);
|
dm_list_del(&strl->list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1353,7 +1353,7 @@ int dev_cache_init(struct cmd_context *cmd)
|
|||||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!(_cache.names = dm_hash_create(8190)) ||
|
if (!(_cache.names = radix_tree_create(NULL, NULL)) ||
|
||||||
!(_cache.vgid_index = dm_hash_create(30)) ||
|
!(_cache.vgid_index = dm_hash_create(30)) ||
|
||||||
!(_cache.lvid_index = dm_hash_create(29))) {
|
!(_cache.lvid_index = dm_hash_create(29))) {
|
||||||
dm_pool_destroy(_cache.mem);
|
dm_pool_destroy(_cache.mem);
|
||||||
@ -1389,27 +1389,36 @@ int dev_cache_init(struct cmd_context *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dev_visitor {
|
||||||
|
struct radix_tree_iterator it;
|
||||||
|
int close_immediate;
|
||||||
|
int free;
|
||||||
|
unsigned num_open;
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* Returns number of devices still open.
|
* Returns number of devices still open.
|
||||||
*/
|
*/
|
||||||
static int _check_for_open_devices(int close_immediate)
|
static bool _visit_check_for_open_devices(struct radix_tree_iterator *it,
|
||||||
|
const void *key, size_t keylen,
|
||||||
|
union radix_value v)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct dev_visitor *vt = container_of(it, struct dev_visitor, it);
|
||||||
struct dm_hash_node *n;
|
struct device *dev = v.ptr;
|
||||||
int num_open = 0;
|
|
||||||
|
|
||||||
dm_hash_iterate(n, _cache.names) {
|
if (dev->fd >= 0) {
|
||||||
dev = (struct device *) dm_hash_get_data(_cache.names, n);
|
log_error("Device '%s' has been left open (%d remaining references).",
|
||||||
if (dev->fd >= 0) {
|
dev_name(dev), dev->open_count);
|
||||||
log_error("Device '%s' has been left open (%d remaining references).",
|
vt->num_open++;
|
||||||
dev_name(dev), dev->open_count);
|
if (vt->close_immediate && !dev_close_immediate(dev))
|
||||||
num_open++;
|
stack;
|
||||||
if (close_immediate && !dev_close_immediate(dev))
|
|
||||||
stack;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_open;
|
if (vt->free) {
|
||||||
|
free_dids(&dev->ids);
|
||||||
|
free_wwids(&dev->wwids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1417,31 +1426,37 @@ static int _check_for_open_devices(int close_immediate)
|
|||||||
*/
|
*/
|
||||||
int dev_cache_check_for_open_devices(void)
|
int dev_cache_check_for_open_devices(void)
|
||||||
{
|
{
|
||||||
return _check_for_open_devices(0);
|
struct dev_visitor vt = {
|
||||||
|
.it.visit = _visit_check_for_open_devices,
|
||||||
|
};
|
||||||
|
|
||||||
|
radix_tree_iterate(_cache.names, NULL, 0, &vt.it);
|
||||||
|
|
||||||
|
return vt.num_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_exit(void)
|
int dev_cache_exit(void)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct dev_visitor vt = {
|
||||||
struct dm_hash_node *n;
|
.it.visit = _visit_check_for_open_devices,
|
||||||
int num_open = 0;
|
.close_immediate = 1, /* close open devices */
|
||||||
|
.free = 1, /* free dids, wwids */
|
||||||
|
};
|
||||||
|
|
||||||
if (_cache.names) {
|
if (_cache.names) {
|
||||||
if ((num_open = _check_for_open_devices(1)) > 0)
|
/* check for open devices */
|
||||||
log_error(INTERNAL_ERROR "%d device(s) were left open and have been closed.", num_open);
|
radix_tree_iterate(_cache.names, NULL, 0, &vt.it);
|
||||||
|
|
||||||
dm_hash_iterate(n, _cache.names) {
|
if (vt.num_open)
|
||||||
dev = (struct device *) dm_hash_get_data(_cache.names, n);
|
log_error(INTERNAL_ERROR "%d device(s) were left open and have been closed.",
|
||||||
free_dids(&dev->ids);
|
vt.num_open);
|
||||||
free_wwids(&dev->wwids);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cache.mem)
|
if (_cache.mem)
|
||||||
dm_pool_destroy(_cache.mem);
|
dm_pool_destroy(_cache.mem);
|
||||||
|
|
||||||
if (_cache.names)
|
if (_cache.names)
|
||||||
dm_hash_destroy(_cache.names);
|
radix_tree_destroy(_cache.names);
|
||||||
|
|
||||||
if (_cache.vgid_index)
|
if (_cache.vgid_index)
|
||||||
dm_hash_destroy(_cache.vgid_index);
|
dm_hash_destroy(_cache.vgid_index);
|
||||||
@ -1457,7 +1472,7 @@ int dev_cache_exit(void)
|
|||||||
|
|
||||||
memset(&_cache, 0, sizeof(_cache));
|
memset(&_cache, 0, sizeof(_cache));
|
||||||
|
|
||||||
return (!num_open);
|
return (!vt.num_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_add_dir(const char *path)
|
int dev_cache_add_dir(const char *path)
|
||||||
@ -1490,7 +1505,7 @@ int dev_cache_add_dir(const char *path)
|
|||||||
|
|
||||||
struct device *dev_hash_get(const char *name)
|
struct device *dev_hash_get(const char *name)
|
||||||
{
|
{
|
||||||
return (struct device *) dm_hash_lookup(_cache.names, name);
|
return radix_tree_lookup_ptr(_cache.names, name, strlen(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _remove_alias(struct device *dev, const char *name)
|
static void _remove_alias(struct device *dev, const char *name)
|
||||||
@ -1526,7 +1541,7 @@ void dev_cache_verify_aliases(struct device *dev)
|
|||||||
log_debug("Drop alias for %u:%u invalid path %s %u:%u.",
|
log_debug("Drop alias for %u:%u invalid path %s %u:%u.",
|
||||||
MAJOR(dev->dev), MINOR(dev->dev), strl->str,
|
MAJOR(dev->dev), MINOR(dev->dev), strl->str,
|
||||||
MAJOR(st.st_rdev), MINOR(st.st_rdev));
|
MAJOR(st.st_rdev), MINOR(st.st_rdev));
|
||||||
dm_hash_remove(_cache.names, strl->str);
|
radix_tree_remove(_cache.names, strl->str, strlen(strl->str));
|
||||||
dm_list_del(&strl->list);
|
dm_list_del(&strl->list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1534,7 +1549,7 @@ void dev_cache_verify_aliases(struct device *dev)
|
|||||||
|
|
||||||
static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f, int existing)
|
static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f, int existing)
|
||||||
{
|
{
|
||||||
struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
struct device *dev = dev_hash_get(name);
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -1560,7 +1575,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
|||||||
log_debug("Device path %s is invalid for %u:%u %s.",
|
log_debug("Device path %s is invalid for %u:%u %s.",
|
||||||
name, MAJOR(dev->dev), MINOR(dev->dev), dev_name(dev));
|
name, MAJOR(dev->dev), MINOR(dev->dev), dev_name(dev));
|
||||||
|
|
||||||
dm_hash_remove(_cache.names, name);
|
radix_tree_remove(_cache.names, name, strlen(name));
|
||||||
|
|
||||||
_remove_alias(dev, name);
|
_remove_alias(dev, name);
|
||||||
|
|
||||||
@ -1625,7 +1640,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
|||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
/* Get the struct dev that was just added. */
|
/* Get the struct dev that was just added. */
|
||||||
dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
dev = dev_hash_get(name);
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
log_error("Failed to get device %s", name);
|
log_error("Failed to get device %s", name);
|
||||||
@ -1695,7 +1710,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
|||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
/* Get the struct dev that was just added. */
|
/* Get the struct dev that was just added. */
|
||||||
dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
dev = dev_hash_get(name);
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
log_error("Failed to get device %s", name);
|
log_error("Failed to get device %s", name);
|
||||||
@ -2245,7 +2260,7 @@ int setup_device(struct cmd_context *cmd, const char *devname)
|
|||||||
if (!_insert_dev(devname, buf.st_rdev))
|
if (!_insert_dev(devname, buf.st_rdev))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
|
if (!(dev = dev_hash_get(devname)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
/* Match this device to an entry in devices_file so it will not
|
/* Match this device to an entry in devices_file so it will not
|
||||||
@ -2432,7 +2447,7 @@ int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname)
|
|||||||
if (!_insert_dev(devname, buf.st_rdev))
|
if (!_insert_dev(devname, buf.st_rdev))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
if (!dm_hash_lookup(_cache.names, devname))
|
if (!dev_hash_get(devname))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2493,7 +2508,7 @@ struct device *setup_dev_in_dev_cache(struct cmd_context *cmd, dev_t devno, cons
|
|||||||
if (!_insert_dev(devname, buf.st_rdev))
|
if (!_insert_dev(devname, buf.st_rdev))
|
||||||
return_NULL;
|
return_NULL;
|
||||||
|
|
||||||
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname))) {
|
if (!(dev = dev_hash_get(devname))) {
|
||||||
log_error("Device lookup failed for %u:%u %s", major, minor, devname);
|
log_error("Device lookup failed for %u:%u %s", major, minor, devname);
|
||||||
return_NULL;
|
return_NULL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user