#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;
}
- 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;
}
/*
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;
/* 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:
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);
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",
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",
static int create_snapshot(struct discover_device *device)
{
struct target target;
+ char *name = NULL;
int rc = -1;
if (!device->ramdisk || !device->ramdisk->base ||
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",
rc = 0;
out:
+ talloc_free(name);
talloc_free(target.params);
talloc_free(target.ttype);
return rc;