X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fdevmapper.c;h=d8445e62e999a7c7e9681fa7f3ce51ccf93b405e;hp=b3639320aecba713734d247fe2dc93948d9d5dd3;hb=6d06f0dbe1195cd8be7d3c54d02012ff16466d0c;hpb=754c0737db6b7337f1d3b40e6e52d9c3abec954f diff --git a/discover/devmapper.c b/discover/devmapper.c index b363932..d8445e6 100644 --- a/discover/devmapper.c +++ b/discover/devmapper.c @@ -2,55 +2,134 @@ #include #include #include +#include #include +#include +#include +#include + #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", §ors, &meta_sectors); + n = sscanf(params, "%" SCNu64 "/%*u %" SCNu64, + §ors, &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",