summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2016-04-07 15:29:02 +1000
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>2016-04-08 14:16:00 +1000
commit0739476294f6925b01ad12b1b198f85b41bc657d (patch)
treea2d1f20bd197ce8f6a441b299fcef300baf61333
parent3b286d116f8fb8438b8ae52669d2c1778b7a370b (diff)
downloadtalos-petitboot-0739476294f6925b01ad12b1b198f85b41bc657d.tar.gz
talos-petitboot-0739476294f6925b01ad12b1b198f85b41bc657d.zip
discover/devmapper: Read device size from sysfs
If udev doesn't export the ID_PART_ENTRY_SIZE variable for a device we skip creating a snapshot for it. However in most cases the sysfs attribute which udev reads to find ID_PART_ENTRY_SIZE is still available. Therefore if we don't have access to ID_PART_ENTRY_SIZE try to find the size in sysfs directly. This allows us to create snapshots for devices which often don't have this udev variable set, such as software raid (md) devices and NVMe devices. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-rw-r--r--discover/devmapper.c86
-rw-r--r--discover/udev.c5
2 files changed, 79 insertions, 12 deletions
diff --git a/discover/devmapper.c b/discover/devmapper.c
index d3179f1..c1a5492 100644
--- a/discover/devmapper.c
+++ b/discover/devmapper.c
@@ -4,6 +4,10 @@
#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include "libdevmapper.h"
#include "devmapper.h"
#include "platform.h"
@@ -17,27 +21,91 @@ struct target {
char *params;
};
-/* Return the number of sectors on a block device. Zero represents an error */
-static uint64_t get_block_sectors(struct discover_device *device)
+static unsigned long read_param_uint(struct discover_device *device,
+ const char *param)
{
- unsigned long long sectors;
+ unsigned long value = 0;
const char *tmp;
- tmp = discover_device_get_param(device, "ID_PART_ENTRY_SIZE");
+ tmp = discover_device_get_param(device, param);
if (!tmp) {
- pb_debug("Could not retrieve ID_PART_ENTRY_SIZE for %s\n",
+ pb_debug("Could not retrieve parameter '%s' for %s\n",
+ param, device->device_path);
+ errno = EINVAL;
+ } else {
+ errno = 0;
+ value = strtoul(tmp, NULL, 0);
+ }
+
+ /* Return errno and result directly */
+ return value;
+}
+
+/* Return the number of sectors on a block device. Zero represents an error */
+static uint64_t get_block_sectors(struct discover_device *device)
+{
+ unsigned long major, minor, sectors = 0;
+ char *attr, *buf = NULL;
+ struct stat sb;
+ int fd = -1;
+ ssize_t sz;
+
+ sectors = read_param_uint(device, "ID_PART_ENTRY_SIZE");
+ if (!errno)
+ return (uint64_t)sectors;
+ else
+ pb_debug("Error reading sector count for %s: %m\n",
device->device_path);
+
+ /* Either the udev property is missing or we failed to parse it.
+ * Instead try to directly read the size attribute out of sysfs */
+ major = read_param_uint(device, "MAJOR");
+ if (errno) {
+ pb_debug("Error reading %s major number\n", device->device_path);
+ return 0;
+ }
+ minor = read_param_uint(device, "MINOR");
+ if (errno) {
+ pb_debug("Error reading %s minor number\n", device->device_path);
return 0;
}
- errno = 0;
- sectors = strtoull(tmp, NULL, 0);
+ attr = talloc_asprintf(device, "/sys/dev/block/%lu:%lu/size",
+ major, minor);
+ if (stat(attr, &sb)) {
+ pb_debug("Failed to stat %s, %m\n", attr);
+ goto out;
+ }
+
+ fd = open(attr, O_RDONLY);
+ if (fd < 0) {
+ pb_debug("Failed to open sysfs attribute for %s\n",
+ device->device_path);
+ goto out;
+ }
+
+ buf = talloc_array(device, char, sb.st_size);
+ if (!buf) {
+ pb_debug("Failed to allocate space for attr\n");
+ goto out;
+ }
+
+ sz = read(fd, buf, sb.st_size);
+ if (sz <= 0) {
+ pb_debug("Failed to read sysfs attr: %m\n");
+ goto out;
+ }
+
+ sectors = strtoul(buf, NULL, 0);
if (errno) {
- pb_debug("Error reading sector count for %s: %s\n",
- device->device_path, strerror(errno));
+ pb_debug("Failed to read sectors from sysfs: %m\n");
sectors = 0;
}
+out:
+ close(fd);
+ talloc_free(buf);
+ talloc_free(attr);
return (uint64_t)sectors;
}
diff --git a/discover/udev.c b/discover/udev.c
index 537ef10..23057bf 100644
--- a/discover/udev.c
+++ b/discover/udev.c
@@ -176,10 +176,9 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
udev_setup_device_params(dev, ddev);
- /* Create a snapshot for all disks, unless it is an assembled RAID array */
+ /* Create a snapshot for all disk devices */
if ((ddev->device->type == DEVICE_TYPE_DISK ||
- ddev->device->type == DEVICE_TYPE_USB) &&
- !udev_device_get_property_value(dev, "MD_LEVEL"))
+ ddev->device->type == DEVICE_TYPE_USB))
devmapper_init_snapshot(udev->handler, ddev);
device_handler_discover(udev->handler, ddev);
OpenPOWER on IntegriCloud