discover/grub: Use different paths to search for the BLS directory
[petitboot] / discover / devmapper.c
index b3639320aecba713734d247fe2dc93948d9d5dd3..d8445e62e999a7c7e9681fa7f3ce51ccf93b405e 100644 (file)
 #include <types/types.h>
 #include <log/log.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <string.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include "libdevmapper.h"
 #include "devmapper.h"
+#include "platform.h"
 
 #define MERGE_INTERVAL_US      200000
 
 struct target {
-       long unsigned int       start_sector;
-       long unsigned int       end_sector;
-       char                    *ttype;
-       char                    *params;
+       uint64_t        start_sector;
+       uint64_t        end_sector;
+       char            *ttype;
+       char            *params;
 };
 
-/* Return the number of sectors on a block device. Zero represents an error */
-static unsigned int get_block_sectors(struct discover_device *device)
+static unsigned long read_param_uint(struct discover_device *device,
+                               const char *param)
 {
+       unsigned long value = 0;
        const char *tmp;
-       long unsigned int sectors;
 
-       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;
+       }
+
+       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;
+       }
 
-       errno = 0;
-       sectors = strtoul(tmp, NULL, 0);
+       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;
        }
 
-       return sectors;
+out:
+       close(fd);
+       talloc_free(buf);
+       talloc_free(attr);
+       return (uint64_t)sectors;
 }
 
-/* Petitboot's libdm isn't compiled with --enable-udev_sync, so we set
- * empty cookie and flags unconditionally */
+/*
+ * The system's libdm may or may not have udev sync support. Tell libdm
+ * to manage the creation of device nodes itself rather than waiting on udev
+ * to do it
+ */
 static inline int set_cookie(struct dm_task *task, uint32_t *cookie)
 {
+       uint16_t udev_rules = 0;
        *cookie = 0;
-       return dm_task_set_cookie(task, cookie, 0);
+
+       dm_udev_set_sync_support(0);
+       udev_rules |= DM_UDEV_DISABLE_DM_RULES_FLAG |
+               DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
+
+       return dm_task_set_cookie(task, cookie, udev_rules);
 }
 
 static bool snapshot_merge_complete(const char *dm_name)
 {
-       long long unsigned int sectors, meta_sectors;
+       uint64_t sectors, meta_sectors;
        char *params = NULL,  *target_type = NULL;
        uint64_t start, length;
        struct dm_task *task;
@@ -87,14 +166,16 @@ static bool snapshot_merge_complete(const char *dm_name)
 
        /* Merge is complete when metadata sectors are the only sectors
         * allocated - see Documentation/device-mapper/snapshot.txt */
-       n = sscanf(params, "%llu/%*u %llu", &sectors, &meta_sectors);
+       n = sscanf(params, "%" SCNu64 "/%*u %" SCNu64,
+                       &sectors, &meta_sectors);
        if (n != 2) {
                pb_log("%s unexpected status: '%s'\n", dm_name, params);
                goto out;
        }
        result = sectors == meta_sectors;
 
-       pb_debug("%s merging; %llu sectors, %llu metadata sectors\n",
+       pb_debug("%s merging; %" PRIu64 " sectors, %" PRIu64
+                       " metadata sectors\n",
                 dm_name, sectors, meta_sectors);
 
 out:
@@ -151,7 +232,7 @@ static int run_create_task(const char *dm_name, const struct target *target)
        struct dm_task *task;
        uint32_t cookie;
 
-       pb_debug("%s: %lu %lu '%s' '%s'\n", __func__,
+       pb_debug("%s: %" PRIu64 " %" PRIu64 " '%s' '%s'\n", __func__,
                 target->start_sector, target->end_sector,
                 target->ttype, target->params);
 
@@ -205,11 +286,11 @@ static int create_base(struct discover_device *device)
                goto out;
        }
 
-       name = talloc_asprintf(device, "%s-base", device->device->id);
+       name = talloc_asprintf(device, "pb-%s-base", device->device->id);
        if (!name || run_create_task(name, &target))
                goto out;
 
-       device->ramdisk->base = talloc_asprintf(device, "/dev/mapper/%s-base",
+       device->ramdisk->base = talloc_asprintf(device, "/dev/mapper/pb-%s-base",
                                        device->device->id);
        if (!device->ramdisk->base) {
                pb_log("Failed to track new device /dev/mapper/%s-base\n",
@@ -245,12 +326,12 @@ static int create_origin(struct discover_device *device)
                goto out;
        }
 
-       name = talloc_asprintf(device, "%s-origin", device->device->id);
+       name = talloc_asprintf(device, "pb-%s-origin", device->device->id);
        if (!name || run_create_task(name, &target))
                goto out;
 
        device->ramdisk->origin = talloc_asprintf(device,
-                                       "/dev/mapper/%s-origin",
+                                       "/dev/mapper/pb-%s-origin",
                                        device->device->id);
        if (!device->ramdisk->origin) {
                pb_log("Failed to track new device /dev/mapper/%s-origin\n",
@@ -270,6 +351,7 @@ out:
 static int create_snapshot(struct discover_device *device)
 {
        struct target target;
+       char *name = NULL;
        int rc = -1;
 
        if (!device->ramdisk || !device->ramdisk->base ||
@@ -287,10 +369,11 @@ static int create_snapshot(struct discover_device *device)
                goto out;
        }
 
-       if (run_create_task(device->device->id, &target))
+       name = talloc_asprintf(device, "pb-%s", device->device->id);
+       if (!name || run_create_task(name, &target))
                goto out;
 
-       device->ramdisk->snapshot = talloc_asprintf(device, "/dev/mapper/%s",
+       device->ramdisk->snapshot = talloc_asprintf(device, "/dev/mapper/pb-%s",
                                                device->device->id);
        if (!device->ramdisk->snapshot) {
                pb_log("Failed to track new device /dev/mapper/%s\n",
@@ -301,6 +384,7 @@ static int create_snapshot(struct discover_device *device)
        rc = 0;
 
 out:
+       talloc_free(name);
        talloc_free(target.params);
        talloc_free(target.ttype);
        return rc;
@@ -311,6 +395,9 @@ int devmapper_init_snapshot(struct device_handler *handler,
 {
        struct ramdisk_device *ramdisk;
 
+       if (config_get()->disable_snapshots)
+               return 0;
+
        ramdisk = device_handler_get_ramdisk(handler);
        if (!ramdisk) {
                pb_log("No ramdisk available for snapshot %s\n",