1 #include <talloc/talloc.h>
2 #include <types/types.h>
7 #include "libdevmapper.h"
11 #define MERGE_INTERVAL_US 200000
14 long unsigned int start_sector;
15 long unsigned int end_sector;
20 /* Return the number of sectors on a block device. Zero represents an error */
21 static unsigned int get_block_sectors(struct discover_device *device)
24 long unsigned int sectors;
26 tmp = discover_device_get_param(device, "ID_PART_ENTRY_SIZE");
28 pb_debug("Could not retrieve ID_PART_ENTRY_SIZE for %s\n",
34 sectors = strtoul(tmp, NULL, 0);
36 pb_debug("Error reading sector count for %s: %s\n",
37 device->device_path, strerror(errno));
45 * The system's libdm may or may not have udev sync support. Tell libdm
46 * to manage the creation of device nodes itself rather than waiting on udev
49 static inline int set_cookie(struct dm_task *task, uint32_t *cookie)
51 uint16_t udev_rules = 0;
54 dm_udev_set_sync_support(0);
55 udev_rules |= DM_UDEV_DISABLE_DM_RULES_FLAG |
56 DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
58 return dm_task_set_cookie(task, cookie, udev_rules);
61 static bool snapshot_merge_complete(const char *dm_name)
63 long long unsigned int sectors, meta_sectors;
64 char *params = NULL, *target_type = NULL;
65 uint64_t start, length;
70 task = dm_task_create(DM_DEVICE_STATUS);
72 pb_log("%s: Error creating task\n", __func__);
76 if (!dm_task_set_name(task, dm_name)) {
77 pb_log("No dm-device named '%s'\n", dm_name);
81 if (!dm_task_run(task)) {
82 pb_log("Unable to retrieve status for '%s'\n", dm_name);
86 dm_get_next_target(task, NULL, &start, &length, &target_type, ¶ms);
89 pb_log("Unable to retrieve params for '%s'\n", dm_name);
93 if (!strncmp(params, "Invalid", strlen("Invalid"))) {
94 pb_log("dm-device %s has become invalid\n", dm_name);
98 /* Merge is complete when metadata sectors are the only sectors
99 * allocated - see Documentation/device-mapper/snapshot.txt */
100 n = sscanf(params, "%llu/%*u %llu", §ors, &meta_sectors);
102 pb_log("%s unexpected status: '%s'\n", dm_name, params);
105 result = sectors == meta_sectors;
107 pb_debug("%s merging; %llu sectors, %llu metadata sectors\n",
108 dm_name, sectors, meta_sectors);
111 /* In case of error or an invalid snapshot return true so callers will
112 * move on and catch the error */
113 dm_task_destroy(task);
117 /* Resume or suspend dm device */
118 static int set_device_active(const char *dm_name, bool active)
120 struct dm_task *task;
125 task = dm_task_create(DM_DEVICE_RESUME);
127 task = dm_task_create(DM_DEVICE_SUSPEND);
130 pb_log("%s: Could not create dm_task\n", __func__);
134 if (!dm_task_set_name(task, dm_name)) {
135 pb_log("No dm-device named '%s'\n", dm_name);
139 if (!set_cookie(task, &cookie))
142 if (!dm_task_run(task)) {
143 pb_log("Unable to %s device '%s'\n",
144 active ? "resume" : "suspend", dm_name);
150 /* Wait for /dev/mapper/ entries to be updated */
151 dm_udev_wait(cookie);
154 dm_task_destroy(task);
158 /* Run a DM_DEVICE_CREATE task with provided table (ttype and params) */
159 static int run_create_task(const char *dm_name, const struct target *target)
161 struct dm_task *task;
164 pb_debug("%s: %lu %lu '%s' '%s'\n", __func__,
165 target->start_sector, target->end_sector,
166 target->ttype, target->params);
168 task = dm_task_create(DM_DEVICE_CREATE);
170 pb_log("Error creating new dm-task\n");
174 if (!dm_task_set_name(task, dm_name))
177 if (!dm_task_add_target(task, target->start_sector, target->end_sector,
178 target->ttype, target->params))
181 if (!dm_task_set_add_node(task, DM_ADD_NODE_ON_CREATE))
184 if (!set_cookie(task, &cookie))
187 if (!dm_task_run(task)) {
188 pb_log("Error executing dm-task\n");
192 /* Wait for /dev/mapper/ entry to appear */
193 dm_udev_wait(cookie);
195 dm_task_destroy(task);
199 static int create_base(struct discover_device *device)
201 struct target target;
205 if (!device->ramdisk)
208 target.start_sector = 0;
209 target.end_sector = device->ramdisk->sectors;
211 target.ttype = talloc_asprintf(device, "linear");
212 target.params = talloc_asprintf(device, "%s 0", device->device_path);
213 if (!target.ttype || !target.params) {
214 pb_log("Failed to allocate map parameters\n");
218 name = talloc_asprintf(device, "%s-base", device->device->id);
219 if (!name || run_create_task(name, &target))
222 device->ramdisk->base = talloc_asprintf(device, "/dev/mapper/%s-base",
224 if (!device->ramdisk->base) {
225 pb_log("Failed to track new device /dev/mapper/%s-base\n",
234 talloc_free(target.params);
235 talloc_free(target.ttype);
239 static int create_origin(struct discover_device *device)
241 struct target target;
245 if (!device->ramdisk || !device->ramdisk->base)
248 target.start_sector = 0;
249 target.end_sector = device->ramdisk->sectors;
251 target.ttype = talloc_asprintf(device, "snapshot-origin");
252 target.params = talloc_asprintf(device, "%s", device->ramdisk->base);
253 if (!target.ttype || !target.params) {
254 pb_log("Failed to allocate map parameters\n");
258 name = talloc_asprintf(device, "%s-origin", device->device->id);
259 if (!name || run_create_task(name, &target))
262 device->ramdisk->origin = talloc_asprintf(device,
263 "/dev/mapper/%s-origin",
265 if (!device->ramdisk->origin) {
266 pb_log("Failed to track new device /dev/mapper/%s-origin\n",
275 talloc_free(target.params);
276 talloc_free(target.ttype);
280 static int create_snapshot(struct discover_device *device)
282 struct target target;
285 if (!device->ramdisk || !device->ramdisk->base ||
286 !device->ramdisk->origin)
289 target.start_sector = 0;
290 target.end_sector = device->ramdisk->sectors;
292 target.ttype = talloc_asprintf(device, "snapshot");
293 target.params = talloc_asprintf(device, "%s %s P 8",
294 device->ramdisk->base, device->ramdisk->path);
295 if (!target.ttype || !target.params) {
296 pb_log("Failed to allocate snapshot parameters\n");
300 if (run_create_task(device->device->id, &target))
303 device->ramdisk->snapshot = talloc_asprintf(device, "/dev/mapper/%s",
305 if (!device->ramdisk->snapshot) {
306 pb_log("Failed to track new device /dev/mapper/%s\n",
314 talloc_free(target.params);
315 talloc_free(target.ttype);
319 int devmapper_init_snapshot(struct device_handler *handler,
320 struct discover_device *device)
322 struct ramdisk_device *ramdisk;
324 if (config_get()->disable_snapshots)
327 ramdisk = device_handler_get_ramdisk(handler);
329 pb_log("No ramdisk available for snapshot %s\n",
334 ramdisk->sectors = get_block_sectors(device);
335 if (!ramdisk->sectors) {
336 pb_log("Error retreiving sectors for %s\n",
341 device->ramdisk = ramdisk;
343 /* Create linear map */
344 if (create_base(device)) {
345 pb_log("Error creating linear base\n");
349 /* Create snapshot-origin */
350 if (create_origin(device)) {
351 pb_log("Error creating snapshot-origin\n");
355 if (set_device_active(device->ramdisk->origin, false)) {
356 pb_log("Failed to suspend origin\n");
360 /* Create snapshot */
361 if (create_snapshot(device)) {
362 pb_log("Error creating snapshot\n");
366 if (set_device_active(device->ramdisk->origin, true)) {
367 pb_log("Failed to resume origin\n");
371 pb_log("Snapshot successfully created for %s\n", device->device->id);
376 pb_log("Error creating snapshot devices for %s\n", device->device->id);
377 devmapper_destroy_snapshot(device);
381 /* Destroy specific dm device */
382 static int destroy_device(const char *dm_name)
384 struct dm_task *task;
388 task = dm_task_create(DM_DEVICE_REMOVE);
390 pb_log("%s: could not create dm_task\n", __func__);
394 if (!dm_task_set_name(task, dm_name)) {
395 pb_log("No dm device named '%s'\n", dm_name);
399 if (!set_cookie(task, &cookie))
402 if (!dm_task_run(task)) {
403 pb_log("Unable to remove device '%s'\n", dm_name);
409 /* Wait for /dev/mapper/ entries to be removed */
410 dm_udev_wait(cookie);
413 dm_task_destroy(task);
417 /* Destroy all dm devices related to a discover_device's snapshot */
418 int devmapper_destroy_snapshot(struct discover_device *device)
422 if (!device->ramdisk)
425 if (device->mounted) {
426 pb_log("Can not remove snapshot: %s is mounted\n",
431 /* Clean up dm devices in order */
432 if (device->ramdisk->snapshot)
433 if (destroy_device(device->ramdisk->snapshot))
436 if (device->ramdisk->origin)
437 if (destroy_device(device->ramdisk->origin))
440 if (device->ramdisk->base)
441 if (destroy_device(device->ramdisk->base))
447 pb_log("Warning: %s snapshot not cleanly removed\n",
449 device_handler_release_ramdisk(device);
453 static int reload_snapshot(struct discover_device *device, bool merge)
455 struct target target;
456 struct dm_task *task;
459 target.start_sector = 0;
460 target.end_sector = device->ramdisk->sectors;
463 target.ttype = talloc_asprintf(device, "snapshot-merge");
464 target.params = talloc_asprintf(device, "%s %s P 8",
465 device->ramdisk->base, device->ramdisk->path);
467 target.ttype = talloc_asprintf(device, "snapshot-origin");
468 target.params = talloc_asprintf(device, "%s",
469 device->ramdisk->base);
471 if (!target.ttype || !target.params) {
472 pb_log("%s: failed to allocate parameters\n", __func__);
476 task = dm_task_create(DM_DEVICE_RELOAD);
478 pb_log("%s: Error creating task\n", __func__);
482 if (!dm_task_set_name(task, device->ramdisk->origin)) {
483 pb_log("No dm-device named '%s'\n", device->ramdisk->origin);
487 if (!dm_task_add_target(task, target.start_sector, target.end_sector,
488 target.ttype, target.params)) {
489 pb_log("%s: Failed to set target\n", __func__);
493 if (!dm_task_run(task)) {
494 pb_log("Failed to reload %s\n", device->ramdisk->origin);
500 dm_task_destroy(task);
502 talloc_free(target.ttype);
503 talloc_free(target.params);
507 int devmapper_merge_snapshot(struct discover_device *device)
509 if (device->mounted) {
510 pb_log("%s: %s still mounted\n", __func__, device->device->id);
514 /* Suspend origin device */
515 if (set_device_active(device->ramdisk->origin, false)) {
516 pb_log("%s: failed to suspend %s\n",
517 __func__, device->ramdisk->origin);
521 /* Destroy snapshot */
522 if (destroy_device(device->ramdisk->snapshot)) {
523 /* The state of the snapshot is unknown, but try to
524 * resume to allow the snapshot to be remounted */
525 set_device_active(device->ramdisk->origin, true);
528 talloc_free(device->ramdisk->snapshot);
529 device->ramdisk->snapshot = NULL;
531 /* Reload origin device for merging */
532 reload_snapshot(device, true);
534 /* Resume origin device */
535 set_device_active(device->ramdisk->origin, true);
537 /* Block until merge complete */
538 while (!snapshot_merge_complete(device->ramdisk->origin))
539 usleep(MERGE_INTERVAL_US);
541 /* Suspend origin device */
542 set_device_active(device->ramdisk->origin, false);
544 /* Reload origin device */
545 reload_snapshot(device, false);
547 /* Re-create snapshot */
548 if (create_snapshot(device))
551 /* Resume origin device */
552 return set_device_active(device->ramdisk->origin, true);