{
const struct config_node *cn;
const struct config_value *cv;
+ size_t udev_dir_len, len;
+ int device_list_from_udev;
+ const char *udev_dir;
init_dev_disable_after_error_count(
find_config_tree_int(cmd, "devices/disable_after_error_count",
if (!dev_cache_init(cmd))
return_0;
+ if ((device_list_from_udev = udev_is_running() ?
+ find_config_tree_bool(cmd, "devices/obtain_device_list_from_udev",
+ DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV) : 0)) {
+ udev_dir = udev_get_dev_dir();
+ udev_dir_len = strlen(udev_dir);
+ }
+ init_obtain_device_list_from_udev(device_list_from_udev);
+
if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
if (!dev_cache_add_dir("/dev")) {
log_error("Failed to add /dev to internal "
return 0;
}
+ if (device_list_from_udev) {
+ len = strlen(cv->v.str);
+ len = udev_dir_len > len ? len : udev_dir_len;
+ if (strncmp(udev_dir, cv->v.str, len) ||
+ udev_dir[len] != cv->v.str[len]) {
+ device_list_from_udev = 0;
+ init_obtain_device_list_from_udev(0);
+ }
+ }
+
if (!dev_cache_add_dir(cv->v.str)) {
log_error("Failed to add %s to internal device cache",
cv->v.str);
#define _free(x) dm_pool_free(_cache.mem, (x))
#define _strdup(x) dm_pool_strdup(_cache.mem, (x))
-static int _insert(const char *path, int rec);
+static int _insert(const char *path, int rec, int check_with_udev_db);
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias, int use_malloc)
}
}
- if (!(sl->str = dm_pool_strdup(_cache.mem, path)))
- return_0;
+ sl->str = path;
if (!dm_list_empty(&dev->aliases)) {
oldpath = dm_list_item(dev->aliases.n, struct str_list)->str;
struct device *dev;
static dev_t loopfile_count = 0;
int loopfile = 0;
+ char *path_copy;
/* Generate pretend device numbers for loopfiles */
if (!d) {
}
}
- if (!loopfile && !_add_alias(dev, path)) {
+ if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
+ log_error("Failed to duplicate path string.");
+ return 0;
+ }
+
+ if (!loopfile && !_add_alias(dev, path_copy)) {
log_error("Couldn't add alias to dev cache.");
return 0;
}
- if (!dm_hash_insert(_cache.names, path, dev)) {
+ if (!dm_hash_insert(_cache.names, path_copy, dev)) {
log_error("Couldn't add name to hash in dev cache.");
return 0;
}
return_0;
_collapse_slashes(path);
- r &= _insert(path, 1);
+ r &= _insert(path, 1, 0);
dm_free(path);
free(dirent[n]);
return 1;
}
-static int _insert(const char *path, int rec)
+#ifdef UDEV_SYNC_SUPPORT
+
+static int _device_in_udev_db(const dev_t d)
+{
+ struct udev *udev;
+ struct udev_device *udev_device;
+
+ if (!(udev = udev_get_library_context()))
+ return_0;
+
+ if ((udev_device = udev_device_new_from_devnum(udev, 'b', d))) {
+ udev_device_unref(udev_device);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int _insert_udev_dir(struct udev *udev, const char *dir)
+{
+ struct udev_enumerate *udev_enum = NULL;
+ struct udev_list_entry *device_entry, *symlink_entry;
+ const char *node_name, *symlink_name;
+ struct udev_device *device;
+ int r = 1;
+
+ if (!(udev_enum = udev_enumerate_new(udev)))
+ goto bad;
+
+ if (udev_enumerate_add_match_subsystem(udev_enum, "block") ||
+ udev_enumerate_scan_devices(udev_enum))
+ goto bad;
+
+ udev_list_entry_foreach(device_entry, udev_enumerate_get_list_entry(udev_enum)) {
+ device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(device_entry));
+
+ node_name = udev_device_get_devnode(device);
+ r &= _insert(node_name, 0, 0);
+
+ udev_list_entry_foreach(symlink_entry, udev_device_get_devlinks_list_entry(device)) {
+ symlink_name = udev_list_entry_get_name(symlink_entry);
+ r &= _insert(symlink_name, 0, 0);
+ }
+
+ udev_device_unref(device);
+ }
+
+ udev_enumerate_unref(udev_enum);
+ return r;
+
+bad:
+ log_error("Failed to enumerate udev device list.");
+ udev_enumerate_unref(udev_enum);
+ return 0;
+}
+
+static void _insert_dirs(struct dm_list *dirs)
+{
+ struct dir_list *dl;
+ struct udev *udev;
+ int with_udev;
+
+ with_udev = obtain_device_list_from_udev() &&
+ (udev = udev_get_library_context());
+
+ dm_list_iterate_items(dl, &_cache.dirs) {
+ if (with_udev) {
+ if (!_insert_udev_dir(udev, dl->dir))
+ log_debug("%s: Failed to insert devices from "
+ "udev-managed directory to device "
+ "cache fully", dl->dir);
+ }
+ else if (!_insert_dir(dl->dir))
+ log_debug("%s: Failed to insert devices to"
+ "device cache fully", dl->dir);
+ }
+}
+
+#else /* UDEV_SYNC_SUPPORT */
+
+static int _device_in_udev_db(const dev_t d)
+{
+ return 0;
+}
+
+static void _insert_dirs(struct dm_list *dirs)
+{
+ struct dir_list *dl;
+
+ dm_list_iterate_items(dl, &_cache.dirs)
+ _insert_dir(dl->dir);
+}
+
+#endif /* UDEV_SYNC_SUPPORT */
+
+static int _insert(const char *path, int rec, int check_with_udev_db)
{
struct stat info;
int r = 0;
return 0;
}
+ if (check_with_udev_db && !_device_in_udev_db(info.st_rdev)) {
+ log_very_verbose("%s: Not in udev db", path);
+ return 0;
+ }
+
if (S_ISDIR(info.st_mode)) { /* add a directory */
/* check it's not a symbolic link */
if (lstat(path, &info) < 0) {
if (_cache.has_scanned && !dev_scan)
return;
- dm_list_iterate_items(dl, &_cache.dirs)
- _insert_dir(dl->dir);
+ _insert_dirs(&_cache.dirs);
dm_list_iterate_items(dl, &_cache.files)
_insert_file(dl->dir);
if (dm_list_size(&dev->aliases) > 1) {
dm_list_del(dev->aliases.n);
if (!r)
- _insert(name, 0);
+ _insert(name, 0, obtain_device_list_from_udev());
continue;
}
}
if (!d) {
- _insert(name, 0);
+ _insert(name, 0, obtain_device_list_from_udev());
d = (struct device *) dm_hash_lookup(_cache.names, name);
if (!d) {
_full_scan(0);