]> git.ozlabs.org Git - petitboot/blobdiff - discover/devmapper.c
lib/system: Add vgscan, vgchange utilities
[petitboot] / discover / devmapper.c
index e2ef0b59c279c294355ec28ff6045f150981495e..2b28e0f55bd45357ee5e6139edd285e2db2456c2 100644 (file)
@@ -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"
 #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;
        }
 
-       errno = 0;
-       sectors = strtoul(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;
        }
 
-       return sectors;
+out:
+       close(fd);
+       talloc_free(buf);
+       talloc_free(attr);
+       return (uint64_t)sectors;
 }
 
 /*
@@ -60,7 +128,7 @@ static inline int set_cookie(struct dm_task *task, uint32_t *cookie)
 
 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;
@@ -97,14 +165,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:
@@ -215,11 +285,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",
@@ -255,12 +325,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",
@@ -280,6 +350,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 ||
@@ -297,10 +368,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",
@@ -311,6 +383,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;