static struct {
struct dm_pool *mem;
struct dm_hash_table *names;
+ struct dm_hash_table *sysfs_only_names; /* see comments in _get_device_for_sysfs_dev_name_using_devno */
struct dm_hash_table *vgid_index;
struct dm_hash_table *lvid_index;
struct btree *devices;
char path[PATH_MAX];
char buf[PATH_MAX];
int major, minor;
+ dev_t devno;
+ struct device *dev;
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dev", dm_sysfs_dir(), devname) < 0) {
log_error("_get_device_for_non_dm_dev: %s: dm_snprintf failed", devname);
return NULL;
}
- return (struct device *) btree_lookup(_cache.devices, (uint32_t) MKDEV(major, minor));
+ devno = MKDEV(major, minor);
+ if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno))) {
+ /*
+ * If we get here, it means the device is referenced in sysfs, but it's not yet in /dev.
+ * This may happen in some rare cases right after LVs get created - we sync with udev
+ * (or alternatively we create /dev content ourselves) while VG lock is held. However,
+ * dev scan is done without VG lock so devices may already be in sysfs, but /dev may
+ * not be updated yet if we call LVM command right after LV creation. This is not a
+ * problem with devtmpfs as there's at least kernel name for device in /dev as soon
+ * as the sysfs item exists, but we still support environments without devtmpfs or
+ * where different directory for dev nodes is used (e.g. our test suite). So track
+ * such devices in _cache.sysfs_only_names hash for the vgid/lvid check to work still.
+ */
+ if (!_cache.sysfs_only_names) {
+ if (!(_cache.sysfs_only_names = dm_hash_create(32))) {
+ log_error("Failed to create hash in dev cache for sysfs-only devices.");
+ return NULL;
+ }
+ }
+
+ if (!(dev = (struct device *) dm_hash_lookup(_cache.sysfs_only_names, devname))) {
+ if (!(dev = _dev_create(devno)))
+ return_NULL;
+ if (!dm_hash_insert(_cache.sysfs_only_names, devname, dev)) {
+ log_error("Couldn't add device to sysfs-only hash in dev cache.");
+ return NULL;
+ }
+ }
+ }
+
+ return dev;
}
#define NOT_LVM_UUID "-"
if (_cache.names)
dm_hash_destroy(_cache.names);
+ if (_cache.sysfs_only_names)
+ dm_hash_destroy(_cache.sysfs_only_names);
+
if (_cache.vgid_index)
dm_hash_destroy(_cache.vgid_index);