diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index 5a5daf112..d8278d964 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -19,6 +19,7 @@ #include #include #include +#include /* * FIXME: really need to seperate names from the devices since @@ -303,10 +304,56 @@ int dev_cache_add_dir(const char *path) return 1; } +/* Check cached device name is still valid before returning it */ +/* This should be a rare occurrence */ +/* FIXME Make rest of code pass/cache struct device instead of dev_name */ +const char *dev_name_confirmed(struct device *dev) +{ + struct stat buf; + char *name; + int r; + + while ((r = stat(name = list_item(dev->aliases.n, + struct str_list)->str, &buf)) || + (buf.st_rdev != dev->dev)) { + if (r < 0) + log_sys_error("stat", name); + log_error("Path %s no longer valid for device(%d,%d)", + name, (int) MAJOR(dev->dev), (int) MINOR(dev->dev)); + + /* Remove the incorrect hash entry */ + hash_remove(_cache.names, name); + + /* Leave list alone if there isn't an alternative name */ + /* so dev_name will always find something to return. */ + /* Otherwise add the name to the correct device. */ + if (list_size(&dev->aliases) > 1) { + list_del(dev->aliases.n); + if (!r) + _insert(name, 0); + continue; + } + + log_error("Aborting - please provide new pathname for what " + "used to be %s", name); + return NULL; + } + + return dev_name(dev); +} + + struct device *dev_cache_get(const char *name, struct dev_filter *f) { + struct stat buf; struct device *d = (struct device *) hash_lookup(_cache.names, name); + /* If the entry's wrong, remove it */ + if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) { + hash_remove(_cache.names, name); + d = NULL; + } + if (!d) { _insert(name, 0); d = (struct device *) hash_lookup(_cache.names, name); @@ -353,5 +400,3 @@ struct device *dev_iter_get(struct dev_iter *iter) return NULL; } - - diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c index 8e1995c43..6f49165ff 100644 --- a/lib/device/dev-io.c +++ b/lib/device/dev-io.c @@ -65,7 +65,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size) int dev_open(struct device *dev, int flags) { struct stat buf; - const char *name = dev_name(dev); + const char *name = dev_name_confirmed(dev); + + if (!name) { + stack; + return 0; + } if (dev->fd >= 0) { log_error("Device '%s' has already been opened", name); diff --git a/lib/device/device.h b/lib/device/device.h index 427a640fb..794f7eff6 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -47,6 +47,8 @@ static inline const char *dev_name(struct device *dev) { return list_item(dev->aliases.n, struct str_list)->str; } +/* Return a valid device name from the alias list; NULL otherwise */ +const char *dev_name_confirmed(struct device *dev); static inline int is_lvm_partition(const char *name) { return 1;