]> sourceware.org Git - lvm2.git/blob - libdm/libdm-deptree.c
Add thin_pool dm message support
[lvm2.git] / libdm / libdm-deptree.c
1 /*
2 * Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
3 *
4 * This file is part of the device-mapper userspace tools.
5 *
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU Lesser General Public License v.2.1.
9 *
10 * You should have received a copy of the GNU Lesser General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13 */
14
15 #include "dmlib.h"
16 #include "libdm-targets.h"
17 #include "libdm-common.h"
18 #include "kdev_t.h"
19 #include "dm-ioctl.h"
20
21 #include <stdarg.h>
22 #include <sys/param.h>
23 #include <sys/utsname.h>
24
25 #define MAX_TARGET_PARAMSIZE 500000
26
27 /* FIXME Fix interface so this is used only by LVM */
28 #define UUID_PREFIX "LVM-"
29
30 #define REPLICATOR_LOCAL_SITE 0
31
32 /* Supported segment types */
33 enum {
34 SEG_CRYPT,
35 SEG_ERROR,
36 SEG_LINEAR,
37 SEG_MIRRORED,
38 SEG_REPLICATOR,
39 SEG_REPLICATOR_DEV,
40 SEG_SNAPSHOT,
41 SEG_SNAPSHOT_ORIGIN,
42 SEG_SNAPSHOT_MERGE,
43 SEG_STRIPED,
44 SEG_ZERO,
45 SEG_THIN_POOL,
46 SEG_THIN,
47 SEG_RAID1,
48 SEG_RAID4,
49 SEG_RAID5_LA,
50 SEG_RAID5_RA,
51 SEG_RAID5_LS,
52 SEG_RAID5_RS,
53 SEG_RAID6_ZR,
54 SEG_RAID6_NR,
55 SEG_RAID6_NC,
56 SEG_LAST,
57 };
58
59 /* FIXME Add crypt and multipath support */
60
61 struct {
62 unsigned type;
63 const char *target;
64 } dm_segtypes[] = {
65 { SEG_CRYPT, "crypt" },
66 { SEG_ERROR, "error" },
67 { SEG_LINEAR, "linear" },
68 { SEG_MIRRORED, "mirror" },
69 { SEG_REPLICATOR, "replicator" },
70 { SEG_REPLICATOR_DEV, "replicator-dev" },
71 { SEG_SNAPSHOT, "snapshot" },
72 { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
73 { SEG_SNAPSHOT_MERGE, "snapshot-merge" },
74 { SEG_STRIPED, "striped" },
75 { SEG_ZERO, "zero"},
76 { SEG_THIN_POOL, "thin-pool"},
77 { SEG_THIN, "thin"},
78 { SEG_RAID1, "raid1"},
79 { SEG_RAID4, "raid4"},
80 { SEG_RAID5_LA, "raid5_la"},
81 { SEG_RAID5_RA, "raid5_ra"},
82 { SEG_RAID5_LS, "raid5_ls"},
83 { SEG_RAID5_RS, "raid5_rs"},
84 { SEG_RAID6_ZR, "raid6_zr"},
85 { SEG_RAID6_NR, "raid6_nr"},
86 { SEG_RAID6_NC, "raid6_nc"},
87
88 /*
89 *WARNING: Since 'raid' target overloads this 1:1 mapping table
90 * for search do not add new enum elements past them!
91 */
92 { SEG_RAID5_LS, "raid5"}, /* same as "raid5_ls" (default for MD also) */
93 { SEG_RAID6_ZR, "raid6"}, /* same as "raid6_zr" */
94 { SEG_LAST, NULL },
95 };
96
97 /* Some segment types have a list of areas of other devices attached */
98 struct seg_area {
99 struct dm_list list;
100
101 struct dm_tree_node *dev_node;
102
103 uint64_t offset;
104
105 unsigned rsite_index; /* Replicator site index */
106 struct dm_tree_node *slog; /* Replicator sync log node */
107 uint64_t region_size; /* Replicator sync log size */
108 uint32_t flags; /* Replicator sync log flags */
109 };
110
111 struct thin_message {
112 struct dm_list list;
113 struct dm_thin_message message;
114 };
115
116 /* Replicator-log has a list of sites */
117 /* FIXME: maybe move to seg_area too? */
118 struct replicator_site {
119 struct dm_list list;
120
121 unsigned rsite_index;
122 dm_replicator_mode_t mode;
123 uint32_t async_timeout;
124 uint32_t fall_behind_ios;
125 uint64_t fall_behind_data;
126 };
127
128 /* Per-segment properties */
129 struct load_segment {
130 struct dm_list list;
131
132 unsigned type;
133
134 uint64_t size;
135
136 unsigned area_count; /* Linear + Striped + Mirrored + Crypt + Replicator */
137 struct dm_list areas; /* Linear + Striped + Mirrored + Crypt + Replicator */
138
139 uint32_t stripe_size; /* Striped + raid */
140
141 int persistent; /* Snapshot */
142 uint32_t chunk_size; /* Snapshot */
143 struct dm_tree_node *cow; /* Snapshot */
144 struct dm_tree_node *origin; /* Snapshot + Snapshot origin */
145 struct dm_tree_node *merge; /* Snapshot */
146
147 struct dm_tree_node *log; /* Mirror + Replicator */
148 uint32_t region_size; /* Mirror + raid */
149 unsigned clustered; /* Mirror */
150 unsigned mirror_area_count; /* Mirror */
151 uint32_t flags; /* Mirror log */
152 char *uuid; /* Clustered mirror log */
153
154 const char *cipher; /* Crypt */
155 const char *chainmode; /* Crypt */
156 const char *iv; /* Crypt */
157 uint64_t iv_offset; /* Crypt */
158 const char *key; /* Crypt */
159
160 const char *rlog_type; /* Replicator */
161 struct dm_list rsites; /* Replicator */
162 unsigned rsite_count; /* Replicator */
163 unsigned rdevice_count; /* Replicator */
164 struct dm_tree_node *replicator;/* Replicator-dev */
165 uint64_t rdevice_index; /* Replicator-dev */
166
167 uint64_t rebuilds; /* raid */
168
169 struct dm_tree_node *metadata; /* Thin_pool */
170 struct dm_tree_node *pool; /* Thin_pool, Thin */
171 struct dm_list thin_messages; /* Thin_pool */
172 uint64_t low_water_mark_size; /* Thin_pool */
173 uint32_t data_block_size; /* Thin_pool */
174 unsigned skip_block_zeroing; /* Thin_pool */
175 uint32_t device_id; /* Thin */
176
177 };
178
179 /* Per-device properties */
180 struct load_properties {
181 int read_only;
182 uint32_t major;
183 uint32_t minor;
184
185 uint32_t read_ahead;
186 uint32_t read_ahead_flags;
187
188 uint64_t thin_pool_transaction_id; /* Thin_pool */
189
190 unsigned segment_count;
191 unsigned size_changed;
192 struct dm_list segs;
193
194 const char *new_name;
195
196 /* If immediate_dev_node is set to 1, try to create the dev node
197 * as soon as possible (e.g. in preload stage even during traversal
198 * and processing of dm tree). This will also flush all stacked dev
199 * node operations, synchronizing with udev.
200 */
201 unsigned immediate_dev_node;
202
203 /*
204 * If the device size changed from zero and this is set,
205 * don't resume the device immediately, even if the device
206 * has parents. This works provided the parents do not
207 * validate the device size and is required by pvmove to
208 * avoid starting the mirror resync operation too early.
209 */
210 unsigned delay_resume_if_new;
211 };
212
213 /* Two of these used to join two nodes with uses and used_by. */
214 struct dm_tree_link {
215 struct dm_list list;
216 struct dm_tree_node *node;
217 };
218
219 struct dm_tree_node {
220 struct dm_tree *dtree;
221
222 const char *name;
223 const char *uuid;
224 struct dm_info info;
225
226 struct dm_list uses; /* Nodes this node uses */
227 struct dm_list used_by; /* Nodes that use this node */
228
229 int activation_priority; /* 0 gets activated first */
230
231 uint16_t udev_flags; /* Udev control flags */
232
233 void *context; /* External supplied context */
234
235 struct load_properties props; /* For creation/table (re)load */
236
237 /*
238 * If presuspend of child node is needed
239 * Note: only direct child is allowed
240 */
241 struct dm_tree_node *presuspend_node;
242 };
243
244 struct dm_tree {
245 struct dm_pool *mem;
246 struct dm_hash_table *devs;
247 struct dm_hash_table *uuids;
248 struct dm_tree_node root;
249 int skip_lockfs; /* 1 skips lockfs (for non-snapshots) */
250 int no_flush; /* 1 sets noflush (mirrors/multipath) */
251 int retry_remove; /* 1 retries remove if not successful */
252 uint32_t cookie;
253 };
254
255 struct dm_tree *dm_tree_create(void)
256 {
257 struct dm_pool *dmem;
258 struct dm_tree *dtree;
259
260 if (!(dmem = dm_pool_create("dtree", 1024)) ||
261 !(dtree = dm_pool_zalloc(dmem, sizeof(*dtree)))) {
262 log_error("Failed to allocate dtree.");
263 if (dmem)
264 dm_pool_destroy(dmem);
265 return NULL;
266 }
267
268 dtree->root.dtree = dtree;
269 dm_list_init(&dtree->root.uses);
270 dm_list_init(&dtree->root.used_by);
271 dtree->skip_lockfs = 0;
272 dtree->no_flush = 0;
273 dtree->mem = dmem;
274
275 if (!(dtree->devs = dm_hash_create(8))) {
276 log_error("dtree hash creation failed");
277 dm_pool_destroy(dtree->mem);
278 return NULL;
279 }
280
281 if (!(dtree->uuids = dm_hash_create(32))) {
282 log_error("dtree uuid hash creation failed");
283 dm_hash_destroy(dtree->devs);
284 dm_pool_destroy(dtree->mem);
285 return NULL;
286 }
287
288 return dtree;
289 }
290
291 void dm_tree_free(struct dm_tree *dtree)
292 {
293 if (!dtree)
294 return;
295
296 dm_hash_destroy(dtree->uuids);
297 dm_hash_destroy(dtree->devs);
298 dm_pool_destroy(dtree->mem);
299 }
300
301 static int _nodes_are_linked(const struct dm_tree_node *parent,
302 const struct dm_tree_node *child)
303 {
304 struct dm_tree_link *dlink;
305
306 dm_list_iterate_items(dlink, &parent->uses)
307 if (dlink->node == child)
308 return 1;
309
310 return 0;
311 }
312
313 static int _link(struct dm_list *list, struct dm_tree_node *node)
314 {
315 struct dm_tree_link *dlink;
316
317 if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
318 log_error("dtree link allocation failed");
319 return 0;
320 }
321
322 dlink->node = node;
323 dm_list_add(list, &dlink->list);
324
325 return 1;
326 }
327
328 static int _link_nodes(struct dm_tree_node *parent,
329 struct dm_tree_node *child)
330 {
331 if (_nodes_are_linked(parent, child))
332 return 1;
333
334 if (!_link(&parent->uses, child))
335 return 0;
336
337 if (!_link(&child->used_by, parent))
338 return 0;
339
340 return 1;
341 }
342
343 static void _unlink(struct dm_list *list, struct dm_tree_node *node)
344 {
345 struct dm_tree_link *dlink;
346
347 dm_list_iterate_items(dlink, list)
348 if (dlink->node == node) {
349 dm_list_del(&dlink->list);
350 break;
351 }
352 }
353
354 static void _unlink_nodes(struct dm_tree_node *parent,
355 struct dm_tree_node *child)
356 {
357 if (!_nodes_are_linked(parent, child))
358 return;
359
360 _unlink(&parent->uses, child);
361 _unlink(&child->used_by, parent);
362 }
363
364 static int _add_to_toplevel(struct dm_tree_node *node)
365 {
366 return _link_nodes(&node->dtree->root, node);
367 }
368
369 static void _remove_from_toplevel(struct dm_tree_node *node)
370 {
371 _unlink_nodes(&node->dtree->root, node);
372 }
373
374 static int _add_to_bottomlevel(struct dm_tree_node *node)
375 {
376 return _link_nodes(node, &node->dtree->root);
377 }
378
379 static void _remove_from_bottomlevel(struct dm_tree_node *node)
380 {
381 _unlink_nodes(node, &node->dtree->root);
382 }
383
384 static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
385 {
386 /* Don't link to root node if child already has a parent */
387 if (parent == &parent->dtree->root) {
388 if (dm_tree_node_num_children(child, 1))
389 return 1;
390 } else
391 _remove_from_toplevel(child);
392
393 if (child == &child->dtree->root) {
394 if (dm_tree_node_num_children(parent, 0))
395 return 1;
396 } else
397 _remove_from_bottomlevel(parent);
398
399 return _link_nodes(parent, child);
400 }
401
402 static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
403 const char *name,
404 const char *uuid,
405 struct dm_info *info,
406 void *context,
407 uint16_t udev_flags)
408 {
409 struct dm_tree_node *node;
410 uint64_t dev;
411
412 if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
413 log_error("_create_dm_tree_node alloc failed");
414 return NULL;
415 }
416
417 node->dtree = dtree;
418
419 node->name = name;
420 node->uuid = uuid;
421 node->info = *info;
422 node->context = context;
423 node->udev_flags = udev_flags;
424 node->activation_priority = 0;
425
426 dm_list_init(&node->uses);
427 dm_list_init(&node->used_by);
428 dm_list_init(&node->props.segs);
429
430 dev = MKDEV(info->major, info->minor);
431
432 if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
433 sizeof(dev), node)) {
434 log_error("dtree node hash insertion failed");
435 dm_pool_free(dtree->mem, node);
436 return NULL;
437 }
438
439 if (uuid && *uuid &&
440 !dm_hash_insert(dtree->uuids, uuid, node)) {
441 log_error("dtree uuid hash insertion failed");
442 dm_hash_remove_binary(dtree->devs, (const char *) &dev,
443 sizeof(dev));
444 dm_pool_free(dtree->mem, node);
445 return NULL;
446 }
447
448 return node;
449 }
450
451 static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
452 uint32_t major, uint32_t minor)
453 {
454 uint64_t dev = MKDEV(major, minor);
455
456 return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
457 sizeof(dev));
458 }
459
460 static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
461 const char *uuid)
462 {
463 struct dm_tree_node *node;
464
465 if ((node = dm_hash_lookup(dtree->uuids, uuid)))
466 return node;
467
468 if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
469 return NULL;
470
471 return dm_hash_lookup(dtree->uuids, uuid + sizeof(UUID_PREFIX) - 1);
472 }
473
474 static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
475 const char **name, const char **uuid,
476 struct dm_info *info, struct dm_deps **deps)
477 {
478 memset(info, 0, sizeof(*info));
479
480 if (!dm_is_dm_major(major)) {
481 *name = "";
482 *uuid = "";
483 *deps = NULL;
484 info->major = major;
485 info->minor = minor;
486 info->exists = 0;
487 info->live_table = 0;
488 info->inactive_table = 0;
489 info->read_only = 0;
490 return 1;
491 }
492
493 if (!(*dmt = dm_task_create(DM_DEVICE_DEPS))) {
494 log_error("deps dm_task creation failed");
495 return 0;
496 }
497
498 if (!dm_task_set_major(*dmt, major)) {
499 log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
500 major, minor);
501 goto failed;
502 }
503
504 if (!dm_task_set_minor(*dmt, minor)) {
505 log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
506 major, minor);
507 goto failed;
508 }
509
510 if (!dm_task_run(*dmt)) {
511 log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
512 major, minor);
513 goto failed;
514 }
515
516 if (!dm_task_get_info(*dmt, info)) {
517 log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
518 major, minor);
519 goto failed;
520 }
521
522 if (!info->exists) {
523 *name = "";
524 *uuid = "";
525 *deps = NULL;
526 } else {
527 if (info->major != major) {
528 log_error("Inconsistent dtree major number: %u != %u",
529 major, info->major);
530 goto failed;
531 }
532 if (info->minor != minor) {
533 log_error("Inconsistent dtree minor number: %u != %u",
534 minor, info->minor);
535 goto failed;
536 }
537 if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
538 log_error("name pool_strdup failed");
539 goto failed;
540 }
541 if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
542 log_error("uuid pool_strdup failed");
543 goto failed;
544 }
545 *deps = dm_task_get_deps(*dmt);
546 }
547
548 return 1;
549
550 failed:
551 dm_task_destroy(*dmt);
552 return 0;
553 }
554
555 static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
556 struct dm_tree_node *parent,
557 uint32_t major, uint32_t minor,
558 uint16_t udev_flags)
559 {
560 struct dm_task *dmt = NULL;
561 struct dm_info info;
562 struct dm_deps *deps = NULL;
563 const char *name = NULL;
564 const char *uuid = NULL;
565 struct dm_tree_node *node = NULL;
566 uint32_t i;
567 int new = 0;
568
569 /* Already in tree? */
570 if (!(node = _find_dm_tree_node(dtree, major, minor))) {
571 if (!_deps(&dmt, dtree->mem, major, minor, &name, &uuid, &info, &deps))
572 return_NULL;
573
574 if (!(node = _create_dm_tree_node(dtree, name, uuid, &info,
575 NULL, udev_flags)))
576 goto_out;
577 new = 1;
578 }
579
580 if (!_link_tree_nodes(parent, node)) {
581 node = NULL;
582 goto_out;
583 }
584
585 /* If node was already in tree, no need to recurse. */
586 if (!new)
587 goto out;
588
589 /* Can't recurse if not a mapped device or there are no dependencies */
590 if (!node->info.exists || !deps->count) {
591 if (!_add_to_bottomlevel(node)) {
592 stack;
593 node = NULL;
594 }
595 goto out;
596 }
597
598 /* Add dependencies to tree */
599 for (i = 0; i < deps->count; i++)
600 if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
601 MINOR(deps->device[i]), udev_flags)) {
602 node = NULL;
603 goto_out;
604 }
605
606 out:
607 if (dmt)
608 dm_task_destroy(dmt);
609
610 return node;
611 }
612
613 static int _node_clear_table(struct dm_tree_node *dnode)
614 {
615 struct dm_task *dmt;
616 struct dm_info *info;
617 const char *name;
618 int r;
619
620 if (!(info = &dnode->info)) {
621 log_error("_node_clear_table failed: missing info");
622 return 0;
623 }
624
625 if (!(name = dm_tree_node_get_name(dnode))) {
626 log_error("_node_clear_table failed: missing name");
627 return 0;
628 }
629
630 /* Is there a table? */
631 if (!info->exists || !info->inactive_table)
632 return 1;
633
634 // FIXME Get inactive deps. If any dev referenced has 1 opener and no live table, remove it after the clear.
635
636 log_verbose("Clearing inactive table %s (%" PRIu32 ":%" PRIu32 ")",
637 name, info->major, info->minor);
638
639 if (!(dmt = dm_task_create(DM_DEVICE_CLEAR))) {
640 log_error("Table clear dm_task creation failed for %s", name);
641 return 0;
642 }
643
644 if (!dm_task_set_major(dmt, info->major) ||
645 !dm_task_set_minor(dmt, info->minor)) {
646 log_error("Failed to set device number for %s table clear", name);
647 dm_task_destroy(dmt);
648 return 0;
649 }
650
651 r = dm_task_run(dmt);
652
653 if (!dm_task_get_info(dmt, info)) {
654 log_error("_node_clear_table failed: info missing after running task for %s", name);
655 r = 0;
656 }
657
658 dm_task_destroy(dmt);
659
660 return r;
661 }
662
663 struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
664 const char *name,
665 const char *uuid,
666 uint32_t major, uint32_t minor,
667 int read_only,
668 int clear_inactive,
669 void *context)
670 {
671 struct dm_tree_node *dnode;
672 struct dm_info info;
673 const char *name2;
674 const char *uuid2;
675
676 /* Do we need to add node to tree? */
677 if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
678 if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
679 log_error("name pool_strdup failed");
680 return NULL;
681 }
682 if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
683 log_error("uuid pool_strdup failed");
684 return NULL;
685 }
686
687 info.major = 0;
688 info.minor = 0;
689 info.exists = 0;
690 info.live_table = 0;
691 info.inactive_table = 0;
692 info.read_only = 0;
693
694 if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2, &info,
695 context, 0)))
696 return_NULL;
697
698 /* Attach to root node until a table is supplied */
699 if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
700 return_NULL;
701
702 dnode->props.major = major;
703 dnode->props.minor = minor;
704 dnode->props.new_name = NULL;
705 dnode->props.size_changed = 0;
706 } else if (strcmp(name, dnode->name)) {
707 /* Do we need to rename node? */
708 if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
709 log_error("name pool_strdup failed");
710 return 0;
711 }
712 }
713
714 dnode->props.read_only = read_only ? 1 : 0;
715 dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
716 dnode->props.read_ahead_flags = 0;
717
718 if (clear_inactive && !_node_clear_table(dnode))
719 return_NULL;
720
721 dnode->context = context;
722 dnode->udev_flags = 0;
723
724 return dnode;
725 }
726
727 struct dm_tree_node *dm_tree_add_new_dev_with_udev_flags(struct dm_tree *dtree,
728 const char *name,
729 const char *uuid,
730 uint32_t major,
731 uint32_t minor,
732 int read_only,
733 int clear_inactive,
734 void *context,
735 uint16_t udev_flags)
736 {
737 struct dm_tree_node *node;
738
739 if ((node = dm_tree_add_new_dev(dtree, name, uuid, major, minor, read_only,
740 clear_inactive, context)))
741 node->udev_flags = udev_flags;
742
743 return node;
744 }
745
746 void dm_tree_node_set_udev_flags(struct dm_tree_node *dnode, uint16_t udev_flags)
747
748 {
749 struct dm_info *dinfo = &dnode->info;
750
751 if (udev_flags != dnode->udev_flags)
752 log_debug("Resetting %s (%" PRIu32 ":%" PRIu32
753 ") udev_flags from 0x%x to 0x%x",
754 dnode->name, dinfo->major, dinfo->minor,
755 dnode->udev_flags, udev_flags);
756 dnode->udev_flags = udev_flags;
757 }
758
759 void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
760 uint32_t read_ahead,
761 uint32_t read_ahead_flags)
762 {
763 dnode->props.read_ahead = read_ahead;
764 dnode->props.read_ahead_flags = read_ahead_flags;
765 }
766
767 void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
768 struct dm_tree_node *presuspend_node)
769 {
770 node->presuspend_node = presuspend_node;
771 }
772
773 int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
774 {
775 return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0;
776 }
777
778 int dm_tree_add_dev_with_udev_flags(struct dm_tree *dtree, uint32_t major,
779 uint32_t minor, uint16_t udev_flags)
780 {
781 return _add_dev(dtree, &dtree->root, major, minor, udev_flags) ? 1 : 0;
782 }
783
784 const char *dm_tree_node_get_name(const struct dm_tree_node *node)
785 {
786 return node->info.exists ? node->name : "";
787 }
788
789 const char *dm_tree_node_get_uuid(const struct dm_tree_node *node)
790 {
791 return node->info.exists ? node->uuid : "";
792 }
793
794 const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node)
795 {
796 return &node->info;
797 }
798
799 void *dm_tree_node_get_context(const struct dm_tree_node *node)
800 {
801 return node->context;
802 }
803
804 int dm_tree_node_size_changed(const struct dm_tree_node *dnode)
805 {
806 return dnode->props.size_changed;
807 }
808
809 int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted)
810 {
811 if (inverted) {
812 if (_nodes_are_linked(&node->dtree->root, node))
813 return 0;
814 return dm_list_size(&node->used_by);
815 }
816
817 if (_nodes_are_linked(node, &node->dtree->root))
818 return 0;
819
820 return dm_list_size(&node->uses);
821 }
822
823 /*
824 * Returns 1 if no prefix supplied
825 */
826 static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len)
827 {
828 if (!uuid_prefix)
829 return 1;
830
831 if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
832 return 1;
833
834 /* Handle transition: active device uuids might be missing the prefix */
835 if (uuid_prefix_len <= 4)
836 return 0;
837
838 if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
839 return 0;
840
841 if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
842 return 0;
843
844 if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
845 return 1;
846
847 return 0;
848 }
849
850 /*
851 * Returns 1 if no children.
852 */
853 static int _children_suspended(struct dm_tree_node *node,
854 uint32_t inverted,
855 const char *uuid_prefix,
856 size_t uuid_prefix_len)
857 {
858 struct dm_list *list;
859 struct dm_tree_link *dlink;
860 const struct dm_info *dinfo;
861 const char *uuid;
862
863 if (inverted) {
864 if (_nodes_are_linked(&node->dtree->root, node))
865 return 1;
866 list = &node->used_by;
867 } else {
868 if (_nodes_are_linked(node, &node->dtree->root))
869 return 1;
870 list = &node->uses;
871 }
872
873 dm_list_iterate_items(dlink, list) {
874 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
875 stack;
876 continue;
877 }
878
879 /* Ignore if it doesn't belong to this VG */
880 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
881 continue;
882
883 /* Ignore if parent node wants to presuspend this node */
884 if (dlink->node->presuspend_node == node)
885 continue;
886
887 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
888 stack; /* FIXME Is this normal? */
889 return 0;
890 }
891
892 if (!dinfo->suspended)
893 return 0;
894 }
895
896 return 1;
897 }
898
899 /*
900 * Set major and minor to zero for root of tree.
901 */
902 struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
903 uint32_t major,
904 uint32_t minor)
905 {
906 if (!major && !minor)
907 return &dtree->root;
908
909 return _find_dm_tree_node(dtree, major, minor);
910 }
911
912 /*
913 * Set uuid to NULL for root of tree.
914 */
915 struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
916 const char *uuid)
917 {
918 if (!uuid || !*uuid)
919 return &dtree->root;
920
921 return _find_dm_tree_node_by_uuid(dtree, uuid);
922 }
923
924 /*
925 * First time set *handle to NULL.
926 * Set inverted to invert the tree.
927 */
928 struct dm_tree_node *dm_tree_next_child(void **handle,
929 const struct dm_tree_node *parent,
930 uint32_t inverted)
931 {
932 struct dm_list **dlink = (struct dm_list **) handle;
933 const struct dm_list *use_list;
934
935 if (inverted)
936 use_list = &parent->used_by;
937 else
938 use_list = &parent->uses;
939
940 if (!*dlink)
941 *dlink = dm_list_first(use_list);
942 else
943 *dlink = dm_list_next(use_list, *dlink);
944
945 return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
946 }
947
948 /*
949 * Deactivate a device with its dependencies if the uuid prefix matches.
950 */
951 static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
952 struct dm_info *info)
953 {
954 struct dm_task *dmt;
955 int r;
956
957 if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
958 log_error("_info_by_dev: dm_task creation failed");
959 return 0;
960 }
961
962 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
963 log_error("_info_by_dev: Failed to set device number");
964 dm_task_destroy(dmt);
965 return 0;
966 }
967
968 if (!with_open_count && !dm_task_no_open_count(dmt))
969 log_error("Failed to disable open_count");
970
971 if ((r = dm_task_run(dmt)))
972 r = dm_task_get_info(dmt, info);
973
974 dm_task_destroy(dmt);
975
976 return r;
977 }
978
979 static int _check_device_not_in_use(struct dm_info *info)
980 {
981 if (!info->exists)
982 return 1;
983
984 /* If sysfs is not used, use open_count information only. */
985 if (!*dm_sysfs_dir()) {
986 if (info->open_count) {
987 log_error("Device %" PRIu32 ":%" PRIu32 " in use",
988 info->major, info->minor);
989 return 0;
990 }
991
992 return 1;
993 }
994
995 if (dm_device_has_holders(info->major, info->minor)) {
996 log_error("Device %" PRIu32 ":%" PRIu32 " is used "
997 "by another device.", info->major, info->minor);
998 return 0;
999 }
1000
1001 if (dm_device_has_mounted_fs(info->major, info->minor)) {
1002 log_error("Device %" PRIu32 ":%" PRIu32 " contains "
1003 "a filesystem in use.", info->major, info->minor);
1004 return 0;
1005 }
1006
1007 return 1;
1008 }
1009
1010 /* Check if all parent nodes of given node have open_count == 0 */
1011 static int _node_has_closed_parents(struct dm_tree_node *node,
1012 const char *uuid_prefix,
1013 size_t uuid_prefix_len)
1014 {
1015 struct dm_tree_link *dlink;
1016 const struct dm_info *dinfo;
1017 struct dm_info info;
1018 const char *uuid;
1019
1020 /* Iterate through parents of this node */
1021 dm_list_iterate_items(dlink, &node->used_by) {
1022 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
1023 stack;
1024 continue;
1025 }
1026
1027 /* Ignore if it doesn't belong to this VG */
1028 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1029 continue;
1030
1031 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
1032 stack; /* FIXME Is this normal? */
1033 return 0;
1034 }
1035
1036 /* Refresh open_count */
1037 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
1038 !info.exists)
1039 continue;
1040
1041 if (info.open_count) {
1042 log_debug("Node %s %d:%d has open_count %d", uuid_prefix,
1043 dinfo->major, dinfo->minor, info.open_count);
1044 return 0;
1045 }
1046 }
1047
1048 return 1;
1049 }
1050
1051 static int _deactivate_node(const char *name, uint32_t major, uint32_t minor,
1052 uint32_t *cookie, uint16_t udev_flags, int retry)
1053 {
1054 struct dm_task *dmt;
1055 int r = 0;
1056
1057 log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
1058
1059 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {
1060 log_error("Deactivation dm_task creation failed for %s", name);
1061 return 0;
1062 }
1063
1064 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
1065 log_error("Failed to set device number for %s deactivation", name);
1066 goto out;
1067 }
1068
1069 if (!dm_task_no_open_count(dmt))
1070 log_error("Failed to disable open_count");
1071
1072 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
1073 goto out;
1074
1075
1076 if (retry)
1077 dm_task_retry_remove(dmt);
1078
1079 r = dm_task_run(dmt);
1080
1081 /* FIXME Until kernel returns actual name so dm-iface.c can handle it */
1082 rm_dev_node(name, dmt->cookie_set && !(udev_flags & DM_UDEV_DISABLE_DM_RULES_FLAG),
1083 dmt->cookie_set && (udev_flags & DM_UDEV_DISABLE_LIBRARY_FALLBACK));
1084
1085 /* FIXME Remove node from tree or mark invalid? */
1086
1087 out:
1088 dm_task_destroy(dmt);
1089
1090 return r;
1091 }
1092
1093 static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
1094 uint32_t minor, uint32_t *cookie, uint16_t udev_flags)
1095 {
1096 struct dm_task *dmt;
1097 int r = 0;
1098
1099 log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);
1100
1101 if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {
1102 log_error("Rename dm_task creation failed for %s", old_name);
1103 return 0;
1104 }
1105
1106 if (!dm_task_set_name(dmt, old_name)) {
1107 log_error("Failed to set name for %s rename.", old_name);
1108 goto out;
1109 }
1110
1111 if (!dm_task_set_newname(dmt, new_name))
1112 goto_out;
1113
1114 if (!dm_task_no_open_count(dmt))
1115 log_error("Failed to disable open_count");
1116
1117 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
1118 goto out;
1119
1120 r = dm_task_run(dmt);
1121
1122 out:
1123 dm_task_destroy(dmt);
1124
1125 return r;
1126 }
1127
1128 /* FIXME Merge with _suspend_node? */
1129 static int _resume_node(const char *name, uint32_t major, uint32_t minor,
1130 uint32_t read_ahead, uint32_t read_ahead_flags,
1131 struct dm_info *newinfo, uint32_t *cookie,
1132 uint16_t udev_flags, int already_suspended)
1133 {
1134 struct dm_task *dmt;
1135 int r = 0;
1136
1137 log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
1138
1139 if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {
1140 log_debug("Suspend dm_task creation failed for %s.", name);
1141 return 0;
1142 }
1143
1144 /* FIXME Kernel should fill in name on return instead */
1145 if (!dm_task_set_name(dmt, name)) {
1146 log_debug("Failed to set device name for %s resumption.", name);
1147 goto out;
1148 }
1149
1150 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
1151 log_error("Failed to set device number for %s resumption.", name);
1152 goto out;
1153 }
1154
1155 if (!dm_task_no_open_count(dmt))
1156 log_error("Failed to disable open_count");
1157
1158 if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
1159 log_error("Failed to set read ahead");
1160
1161 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
1162 goto_out;
1163
1164 if (!(r = dm_task_run(dmt)))
1165 goto_out;
1166
1167 if (already_suspended)
1168 dec_suspended();
1169
1170 if (!(r = dm_task_get_info(dmt, newinfo)))
1171 stack;
1172
1173 out:
1174 dm_task_destroy(dmt);
1175
1176 return r;
1177 }
1178
1179 static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
1180 int skip_lockfs, int no_flush, struct dm_info *newinfo)
1181 {
1182 struct dm_task *dmt;
1183 int r;
1184
1185 log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
1186 name, major, minor,
1187 skip_lockfs ? "" : " with filesystem sync",
1188 no_flush ? "" : " with device flush");
1189
1190 if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
1191 log_error("Suspend dm_task creation failed for %s", name);
1192 return 0;
1193 }
1194
1195 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
1196 log_error("Failed to set device number for %s suspension.", name);
1197 dm_task_destroy(dmt);
1198 return 0;
1199 }
1200
1201 if (!dm_task_no_open_count(dmt))
1202 log_error("Failed to disable open_count");
1203
1204 if (skip_lockfs && !dm_task_skip_lockfs(dmt))
1205 log_error("Failed to set skip_lockfs flag.");
1206
1207 if (no_flush && !dm_task_no_flush(dmt))
1208 log_error("Failed to set no_flush flag.");
1209
1210 if ((r = dm_task_run(dmt))) {
1211 inc_suspended();
1212 r = dm_task_get_info(dmt, newinfo);
1213 }
1214
1215 dm_task_destroy(dmt);
1216
1217 return r;
1218 }
1219
1220 static int _thin_pool_status_transaction_id(struct dm_tree_node *dnode, uint64_t *transaction_id)
1221 {
1222 struct dm_task *dmt;
1223 int r = 0;
1224 uint64_t start, length;
1225 char *type = NULL;
1226 char *params = NULL;
1227
1228 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
1229 return_0;
1230
1231 if (!dm_task_set_major(dmt, dnode->info.major) ||
1232 !dm_task_set_minor(dmt, dnode->info.minor)) {
1233 log_error("Failed to set major minor.");
1234 goto out;
1235 }
1236
1237 if (!dm_task_run(dmt))
1238 goto_out;
1239
1240 dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
1241
1242 if (type && (strcmp(type, "thin-pool") != 0)) {
1243 log_error(INTERNAL_ERROR
1244 "Expected thin-pool target for %d:%d and got %s.",
1245 dnode->info.major, dnode->info.minor, type);
1246 goto out;
1247 }
1248
1249 if (!params || (sscanf(params, "%" PRIu64, transaction_id) != 1)) {
1250 log_error(INTERNAL_ERROR
1251 "Failed to parse transaction_id from %s.", params);
1252 goto out;
1253 }
1254
1255 log_debug("Thin pool transaction id: %" PRIu64 " status: %s.", *transaction_id, params);
1256
1257 r = 1;
1258 out:
1259 dm_task_destroy(dmt);
1260
1261 return r;
1262 }
1263
1264 static int _thin_pool_node_message(struct dm_tree_node *dnode, struct thin_message *tm)
1265 {
1266 struct dm_task *dmt;
1267 struct dm_thin_message *m = &tm->message;
1268 char buf[64];
1269 int r;
1270
1271 switch (m->type) {
1272 case DM_THIN_MESSAGE_CREATE_SNAP:
1273 r = dm_snprintf(buf, sizeof(buf), "create_snap %u %u",
1274 m->u.m_create_snap.device_id,
1275 m->u.m_create_snap.origin_id);
1276 break;
1277 case DM_THIN_MESSAGE_CREATE_THIN:
1278 r = dm_snprintf(buf, sizeof(buf), "create_thin %u",
1279 m->u.m_create_thin.device_id);
1280 break;
1281 case DM_THIN_MESSAGE_DELETE:
1282 r = dm_snprintf(buf, sizeof(buf), "delete %u",
1283 m->u.m_delete.device_id);
1284 break;
1285 case DM_THIN_MESSAGE_TRIM:
1286 r = dm_snprintf(buf, sizeof(buf), "trim %u %" PRIu64,
1287 m->u.m_trim.device_id,
1288 m->u.m_trim.new_size);
1289 break;
1290 case DM_THIN_MESSAGE_SET_TRANSACTION_ID:
1291 r = dm_snprintf(buf, sizeof(buf),
1292 "set_transaction_id %" PRIu64 " %" PRIu64,
1293 m->u.m_set_transaction_id.current_id,
1294 m->u.m_set_transaction_id.new_id);
1295 break;
1296 }
1297
1298 if (!r) {
1299 log_error("Failed to prepare message.");
1300 return 0;
1301 }
1302
1303 r = 0;
1304
1305 if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
1306 return_0;
1307
1308 if (!dm_task_set_major(dmt, dnode->info.major) ||
1309 !dm_task_set_minor(dmt, dnode->info.minor)) {
1310 log_error("Failed to set message major minor.");
1311 goto out;
1312 }
1313
1314 if (!dm_task_set_message(dmt, buf))
1315 goto_out;
1316
1317 if (!dm_task_run(dmt))
1318 goto_out;
1319
1320 r = 1;
1321 out:
1322 dm_task_destroy(dmt);
1323
1324 return r;
1325 }
1326
1327 static int _thin_pool_node_send_messages(struct dm_tree_node *dnode,
1328 const char *uuid_prefix,
1329 size_t uuid_prefix_len)
1330 {
1331 struct load_segment *seg;
1332 struct thin_message *tmsg;
1333 uint64_t current_id;
1334 const char *uuid;
1335
1336 if ((dnode == &dnode->dtree->root) || /* root has rops.segs uninitialized */
1337 (dm_list_size(&dnode->props.segs) != 1))
1338 return 1;
1339
1340 seg = dm_list_item(dm_list_last(&dnode->props.segs), struct load_segment);
1341
1342 if (seg->type != SEG_THIN_POOL)
1343 return 1;
1344
1345 if (!(uuid = dm_tree_node_get_uuid(dnode)))
1346 return_0;
1347
1348 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len)) {
1349 log_debug("UUID \"%s\" does not match.", uuid);
1350 return 1;
1351 }
1352
1353 if (!_thin_pool_status_transaction_id(dnode, &current_id))
1354 return_0;
1355
1356 log_debug("Expecting transaction_id: %" PRIu64, dnode->props.thin_pool_transaction_id);
1357 if (current_id == dnode->props.thin_pool_transaction_id)
1358 return 1; /* In sync - skip messages */
1359
1360 if (current_id != (dnode->props.thin_pool_transaction_id - 1)) {
1361 log_error("Thin pool transaction_id=%" PRIu64 ", while expected: %" PRIu64 ".",
1362 current_id, dnode->props.thin_pool_transaction_id - 1);
1363 return 0; /* Nothing to send */
1364 }
1365
1366 dm_list_iterate_items(tmsg, &seg->thin_messages)
1367 if (!(_thin_pool_node_message(dnode, tmsg)))
1368 return_0;
1369
1370 return 1;
1371 }
1372
1373 /*
1374 * FIXME Don't attempt to deactivate known internal dependencies.
1375 */
1376 static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
1377 const char *uuid_prefix,
1378 size_t uuid_prefix_len,
1379 unsigned level)
1380 {
1381 int r = 1;
1382 void *handle = NULL;
1383 struct dm_tree_node *child = dnode;
1384 struct dm_info info;
1385 const struct dm_info *dinfo;
1386 const char *name;
1387 const char *uuid;
1388
1389 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1390 if (!(dinfo = dm_tree_node_get_info(child))) {
1391 stack;
1392 continue;
1393 }
1394
1395 if (!(name = dm_tree_node_get_name(child))) {
1396 stack;
1397 continue;
1398 }
1399
1400 if (!(uuid = dm_tree_node_get_uuid(child))) {
1401 stack;
1402 continue;
1403 }
1404
1405 /* Ignore if it doesn't belong to this VG */
1406 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1407 continue;
1408
1409 /* Refresh open_count */
1410 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
1411 !info.exists)
1412 continue;
1413
1414 if (!_check_device_not_in_use(&info))
1415 continue;
1416
1417 /* Also checking open_count in parent nodes of presuspend_node */
1418 if ((child->presuspend_node &&
1419 !_node_has_closed_parents(child->presuspend_node,
1420 uuid_prefix, uuid_prefix_len))) {
1421 /* Only report error from (likely non-internal) dependency at top level */
1422 if (!level) {
1423 log_error("Unable to deactivate open %s (%" PRIu32
1424 ":%" PRIu32 ")", name, info.major,
1425 info.minor);
1426 r = 0;
1427 }
1428 continue;
1429 }
1430
1431 /* Suspend child node first if requested */
1432 if (child->presuspend_node &&
1433 !dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
1434 continue;
1435
1436 if (!_deactivate_node(name, info.major, info.minor,
1437 &child->dtree->cookie, child->udev_flags,
1438 child->dtree->retry_remove)) {
1439 log_error("Unable to deactivate %s (%" PRIu32
1440 ":%" PRIu32 ")", name, info.major,
1441 info.minor);
1442 r = 0;
1443 continue;
1444 } else if (info.suspended)
1445 dec_suspended();
1446
1447 if (dm_tree_node_num_children(child, 0)) {
1448 if (!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
1449 return_0;
1450 }
1451 }
1452
1453 return r;
1454 }
1455
1456 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
1457 const char *uuid_prefix,
1458 size_t uuid_prefix_len)
1459 {
1460 return _dm_tree_deactivate_children(dnode, uuid_prefix, uuid_prefix_len, 0);
1461 }
1462
1463 void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
1464 {
1465 dnode->dtree->skip_lockfs = 1;
1466 }
1467
1468 void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
1469 {
1470 dnode->dtree->no_flush = 1;
1471 }
1472
1473 void dm_tree_retry_remove(struct dm_tree_node *dnode)
1474 {
1475 dnode->dtree->retry_remove = 1;
1476 }
1477
1478 int dm_tree_suspend_children(struct dm_tree_node *dnode,
1479 const char *uuid_prefix,
1480 size_t uuid_prefix_len)
1481 {
1482 int r = 1;
1483 void *handle = NULL;
1484 struct dm_tree_node *child = dnode;
1485 struct dm_info info, newinfo;
1486 const struct dm_info *dinfo;
1487 const char *name;
1488 const char *uuid;
1489
1490 /* Suspend nodes at this level of the tree */
1491 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1492 if (!(dinfo = dm_tree_node_get_info(child))) {
1493 stack;
1494 continue;
1495 }
1496
1497 if (!(name = dm_tree_node_get_name(child))) {
1498 stack;
1499 continue;
1500 }
1501
1502 if (!(uuid = dm_tree_node_get_uuid(child))) {
1503 stack;
1504 continue;
1505 }
1506
1507 /* Ignore if it doesn't belong to this VG */
1508 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1509 continue;
1510
1511 /* Ensure immediate parents are already suspended */
1512 if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
1513 continue;
1514
1515 if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
1516 !info.exists || info.suspended)
1517 continue;
1518
1519 if (!_suspend_node(name, info.major, info.minor,
1520 child->dtree->skip_lockfs,
1521 child->dtree->no_flush, &newinfo)) {
1522 log_error("Unable to suspend %s (%" PRIu32
1523 ":%" PRIu32 ")", name, info.major,
1524 info.minor);
1525 r = 0;
1526 continue;
1527 }
1528
1529 /* Update cached info */
1530 child->info = newinfo;
1531 }
1532
1533 /* Then suspend any child nodes */
1534 handle = NULL;
1535
1536 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1537 if (!(uuid = dm_tree_node_get_uuid(child))) {
1538 stack;
1539 continue;
1540 }
1541
1542 /* Ignore if it doesn't belong to this VG */
1543 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1544 continue;
1545
1546 if (dm_tree_node_num_children(child, 0))
1547 if (!dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
1548 return_0;
1549 }
1550
1551 return r;
1552 }
1553
1554 int dm_tree_activate_children(struct dm_tree_node *dnode,
1555 const char *uuid_prefix,
1556 size_t uuid_prefix_len)
1557 {
1558 int r = 1;
1559 void *handle = NULL;
1560 struct dm_tree_node *child = dnode;
1561 struct dm_info newinfo;
1562 const char *name;
1563 const char *uuid;
1564 int priority;
1565
1566 /* Activate children first */
1567 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1568 if (!(uuid = dm_tree_node_get_uuid(child))) {
1569 stack;
1570 continue;
1571 }
1572
1573 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1574 continue;
1575
1576 if (dm_tree_node_num_children(child, 0))
1577 if (!dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len))
1578 return_0;
1579 }
1580
1581 handle = NULL;
1582
1583 for (priority = 0; priority < 3; priority++) {
1584 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1585 if (priority != child->activation_priority)
1586 continue;
1587
1588 if (!(uuid = dm_tree_node_get_uuid(child))) {
1589 stack;
1590 continue;
1591 }
1592
1593 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1594 continue;
1595
1596 if (!(name = dm_tree_node_get_name(child))) {
1597 stack;
1598 continue;
1599 }
1600
1601 /* Rename? */
1602 if (child->props.new_name) {
1603 if (!_rename_node(name, child->props.new_name, child->info.major,
1604 child->info.minor, &child->dtree->cookie,
1605 child->udev_flags)) {
1606 log_error("Failed to rename %s (%" PRIu32
1607 ":%" PRIu32 ") to %s", name, child->info.major,
1608 child->info.minor, child->props.new_name);
1609 return 0;
1610 }
1611 child->name = child->props.new_name;
1612 child->props.new_name = NULL;
1613 }
1614
1615 if (!child->info.inactive_table && !child->info.suspended)
1616 continue;
1617
1618 if (!_resume_node(child->name, child->info.major, child->info.minor,
1619 child->props.read_ahead, child->props.read_ahead_flags,
1620 &newinfo, &child->dtree->cookie, child->udev_flags, child->info.suspended)) {
1621 log_error("Unable to resume %s (%" PRIu32
1622 ":%" PRIu32 ")", child->name, child->info.major,
1623 child->info.minor);
1624 r = 0;
1625 continue;
1626 }
1627
1628 /* Update cached info */
1629 child->info = newinfo;
1630 }
1631 }
1632
1633 handle = NULL;
1634
1635 return r;
1636 }
1637
1638 static int _create_node(struct dm_tree_node *dnode)
1639 {
1640 int r = 0;
1641 struct dm_task *dmt;
1642
1643 log_verbose("Creating %s", dnode->name);
1644
1645 if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {
1646 log_error("Create dm_task creation failed for %s", dnode->name);
1647 return 0;
1648 }
1649
1650 if (!dm_task_set_name(dmt, dnode->name)) {
1651 log_error("Failed to set device name for %s", dnode->name);
1652 goto out;
1653 }
1654
1655 if (!dm_task_set_uuid(dmt, dnode->uuid)) {
1656 log_error("Failed to set uuid for %s", dnode->name);
1657 goto out;
1658 }
1659
1660 if (dnode->props.major &&
1661 (!dm_task_set_major(dmt, dnode->props.major) ||
1662 !dm_task_set_minor(dmt, dnode->props.minor))) {
1663 log_error("Failed to set device number for %s creation.", dnode->name);
1664 goto out;
1665 }
1666
1667 if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1668 log_error("Failed to set read only flag for %s", dnode->name);
1669 goto out;
1670 }
1671
1672 if (!dm_task_no_open_count(dmt))
1673 log_error("Failed to disable open_count");
1674
1675 if ((r = dm_task_run(dmt)))
1676 r = dm_task_get_info(dmt, &dnode->info);
1677
1678 out:
1679 dm_task_destroy(dmt);
1680
1681 return r;
1682 }
1683
1684
1685 static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
1686 {
1687 if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
1688 log_error("Failed to format %s device number for %s as dm "
1689 "target (%u,%u)",
1690 node->name, node->uuid, node->info.major, node->info.minor);
1691 return 0;
1692 }
1693
1694 return 1;
1695 }
1696
1697 /* simplify string emiting code */
1698 #define EMIT_PARAMS(p, str...)\
1699 do {\
1700 int w;\
1701 if ((w = dm_snprintf(params + p, paramsize - (size_t) p, str)) < 0) {\
1702 stack; /* Out of space */\
1703 return -1;\
1704 }\
1705 p += w;\
1706 } while (0)
1707
1708 /*
1709 * _emit_areas_line
1710 *
1711 * Returns: 1 on success, 0 on failure
1712 */
1713 static int _emit_areas_line(struct dm_task *dmt __attribute__((unused)),
1714 struct load_segment *seg, char *params,
1715 size_t paramsize, int *pos)
1716 {
1717 struct seg_area *area;
1718 char devbuf[DM_FORMAT_DEV_BUFSIZE];
1719 unsigned first_time = 1;
1720 const char *logtype, *synctype;
1721 unsigned log_parm_count;
1722
1723 dm_list_iterate_items(area, &seg->areas) {
1724 switch (seg->type) {
1725 case SEG_REPLICATOR_DEV:
1726 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1727 return_0;
1728
1729 EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf);
1730 if (first_time)
1731 EMIT_PARAMS(*pos, " nolog 0");
1732 else {
1733 /* Remote devices */
1734 log_parm_count = (area->flags &
1735 (DM_NOSYNC | DM_FORCESYNC)) ? 2 : 1;
1736
1737 if (!area->slog) {
1738 devbuf[0] = 0; /* Only core log parameters */
1739 logtype = "core";
1740 } else {
1741 devbuf[0] = ' '; /* Extra space before device name */
1742 if (!_build_dev_string(devbuf + 1,
1743 sizeof(devbuf) - 1,
1744 area->slog))
1745 return_0;
1746 logtype = "disk";
1747 log_parm_count++; /* Extra sync log device name parameter */
1748 }
1749
1750 EMIT_PARAMS(*pos, " %s %u%s %" PRIu64, logtype,
1751 log_parm_count, devbuf, area->region_size);
1752
1753 synctype = (area->flags & DM_NOSYNC) ?
1754 " nosync" : (area->flags & DM_FORCESYNC) ?
1755 " sync" : NULL;
1756
1757 if (synctype)
1758 EMIT_PARAMS(*pos, "%s", synctype);
1759 }
1760 break;
1761 case SEG_RAID1:
1762 case SEG_RAID4:
1763 case SEG_RAID5_LA:
1764 case SEG_RAID5_RA:
1765 case SEG_RAID5_LS:
1766 case SEG_RAID5_RS:
1767 case SEG_RAID6_ZR:
1768 case SEG_RAID6_NR:
1769 case SEG_RAID6_NC:
1770 if (!area->dev_node) {
1771 EMIT_PARAMS(*pos, " -");
1772 break;
1773 }
1774 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1775 return_0;
1776
1777 EMIT_PARAMS(*pos, " %s", devbuf);
1778 break;
1779 default:
1780 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1781 return_0;
1782
1783 EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
1784 devbuf, area->offset);
1785 }
1786
1787 first_time = 0;
1788 }
1789
1790 return 1;
1791 }
1792
1793 static int _replicator_emit_segment_line(const struct load_segment *seg, char *params,
1794 size_t paramsize, int *pos)
1795 {
1796 const struct load_segment *rlog_seg;
1797 struct replicator_site *rsite;
1798 char rlogbuf[DM_FORMAT_DEV_BUFSIZE];
1799 unsigned parm_count;
1800
1801 if (!seg->log || !_build_dev_string(rlogbuf, sizeof(rlogbuf), seg->log))
1802 return_0;
1803
1804 rlog_seg = dm_list_item(dm_list_last(&seg->log->props.segs),
1805 struct load_segment);
1806
1807 EMIT_PARAMS(*pos, "%s 4 %s 0 auto %" PRIu64,
1808 seg->rlog_type, rlogbuf, rlog_seg->size);
1809
1810 dm_list_iterate_items(rsite, &seg->rsites) {
1811 parm_count = (rsite->fall_behind_data
1812 || rsite->fall_behind_ios
1813 || rsite->async_timeout) ? 4 : 2;
1814
1815 EMIT_PARAMS(*pos, " blockdev %u %u %s", parm_count, rsite->rsite_index,
1816 (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");
1817
1818 if (rsite->fall_behind_data)
1819 EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
1820 else if (rsite->fall_behind_ios)
1821 EMIT_PARAMS(*pos, " ios %" PRIu32, rsite->fall_behind_ios);
1822 else if (rsite->async_timeout)
1823 EMIT_PARAMS(*pos, " timeout %" PRIu32, rsite->async_timeout);
1824 }
1825
1826 return 1;
1827 }
1828
1829 /*
1830 * Returns: 1 on success, 0 on failure
1831 */
1832 static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *seg,
1833 char *params, size_t paramsize)
1834 {
1835 int block_on_error = 0;
1836 int handle_errors = 0;
1837 int dm_log_userspace = 0;
1838 struct utsname uts;
1839 unsigned log_parm_count;
1840 int pos = 0, parts;
1841 char logbuf[DM_FORMAT_DEV_BUFSIZE];
1842 const char *logtype;
1843 unsigned kmaj = 0, kmin = 0, krel = 0;
1844
1845 if (uname(&uts) == -1) {
1846 log_error("Cannot read kernel release version.");
1847 return 0;
1848 }
1849
1850 /* Kernels with a major number of 2 always had 3 parts. */
1851 parts = sscanf(uts.release, "%u.%u.%u", &kmaj, &kmin, &krel);
1852 if (parts < 1 || (kmaj < 3 && parts < 3)) {
1853 log_error("Wrong kernel release version %s.", uts.release);
1854 return 0;
1855 }
1856
1857 if ((seg->flags & DM_BLOCK_ON_ERROR)) {
1858 /*
1859 * Originally, block_on_error was an argument to the log
1860 * portion of the mirror CTR table. It was renamed to
1861 * "handle_errors" and now resides in the 'features'
1862 * section of the mirror CTR table (i.e. at the end).
1863 *
1864 * We can identify whether to use "block_on_error" or
1865 * "handle_errors" by the dm-mirror module's version
1866 * number (>= 1.12) or by the kernel version (>= 2.6.22).
1867 */
1868 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 22))
1869 handle_errors = 1;
1870 else
1871 block_on_error = 1;
1872 }
1873
1874 if (seg->clustered) {
1875 /* Cluster mirrors require a UUID */
1876 if (!seg->uuid)
1877 return_0;
1878
1879 /*
1880 * Cluster mirrors used to have their own log
1881 * types. Now they are accessed through the
1882 * userspace log type.
1883 *
1884 * The dm-log-userspace module was added to the
1885 * 2.6.31 kernel.
1886 */
1887 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 31))
1888 dm_log_userspace = 1;
1889 }
1890
1891 /* Region size */
1892 log_parm_count = 1;
1893
1894 /* [no]sync, block_on_error etc. */
1895 log_parm_count += hweight32(seg->flags);
1896
1897 /* "handle_errors" is a feature arg now */
1898 if (handle_errors)
1899 log_parm_count--;
1900
1901 /* DM_CORELOG does not count in the param list */
1902 if (seg->flags & DM_CORELOG)
1903 log_parm_count--;
1904
1905 if (seg->clustered) {
1906 log_parm_count++; /* For UUID */
1907
1908 if (!dm_log_userspace)
1909 EMIT_PARAMS(pos, "clustered-");
1910 else
1911 /* For clustered-* type field inserted later */
1912 log_parm_count++;
1913 }
1914
1915 if (!seg->log)
1916 logtype = "core";
1917 else {
1918 logtype = "disk";
1919 log_parm_count++;
1920 if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
1921 return_0;
1922 }
1923
1924 if (dm_log_userspace)
1925 EMIT_PARAMS(pos, "userspace %u %s clustered-%s",
1926 log_parm_count, seg->uuid, logtype);
1927 else
1928 EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count);
1929
1930 if (seg->log)
1931 EMIT_PARAMS(pos, " %s", logbuf);
1932
1933 EMIT_PARAMS(pos, " %u", seg->region_size);
1934
1935 if (seg->clustered && !dm_log_userspace)
1936 EMIT_PARAMS(pos, " %s", seg->uuid);
1937
1938 if ((seg->flags & DM_NOSYNC))
1939 EMIT_PARAMS(pos, " nosync");
1940 else if ((seg->flags & DM_FORCESYNC))
1941 EMIT_PARAMS(pos, " sync");
1942
1943 if (block_on_error)
1944 EMIT_PARAMS(pos, " block_on_error");
1945
1946 EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
1947
1948 if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
1949 return_0;
1950
1951 if (handle_errors)
1952 EMIT_PARAMS(pos, " 1 handle_errors");
1953
1954 return 1;
1955 }
1956
1957 static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
1958 uint32_t minor, struct load_segment *seg,
1959 uint64_t *seg_start, char *params,
1960 size_t paramsize)
1961 {
1962 uint32_t i;
1963 int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */
1964 int pos = 0;
1965
1966 if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC))
1967 param_count++;
1968
1969 if (seg->region_size)
1970 param_count += 2;
1971
1972 /* rebuilds is 64-bit */
1973 param_count += 2 * hweight32(seg->rebuilds & 0xFFFFFFFF);
1974 param_count += 2 * hweight32(seg->rebuilds >> 32);
1975
1976 if ((seg->type == SEG_RAID1) && seg->stripe_size)
1977 log_error("WARNING: Ignoring RAID1 stripe size");
1978
1979 EMIT_PARAMS(pos, "%s %d %u", dm_segtypes[seg->type].target,
1980 param_count, seg->stripe_size);
1981
1982 if (seg->flags & DM_NOSYNC)
1983 EMIT_PARAMS(pos, " nosync");
1984 else if (seg->flags & DM_FORCESYNC)
1985 EMIT_PARAMS(pos, " sync");
1986
1987 if (seg->region_size)
1988 EMIT_PARAMS(pos, " region_size %u", seg->region_size);
1989
1990 for (i = 0; i < (seg->area_count / 2); i++)
1991 if (seg->rebuilds & (1 << i))
1992 EMIT_PARAMS(pos, " rebuild %u", i);
1993
1994 /* Print number of metadata/data device pairs */
1995 EMIT_PARAMS(pos, " %u", seg->area_count/2);
1996
1997 if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
1998 return_0;
1999
2000 return 1;
2001 }
2002
2003 static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
2004 uint32_t minor, struct load_segment *seg,
2005 uint64_t *seg_start, char *params,
2006 size_t paramsize)
2007 {
2008 int pos = 0;
2009 int r;
2010 int target_type_is_raid = 0;
2011 char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
2012 char pool[DM_FORMAT_DEV_BUFSIZE], metadata[DM_FORMAT_DEV_BUFSIZE];
2013
2014 switch(seg->type) {
2015 case SEG_ERROR:
2016 case SEG_ZERO:
2017 case SEG_LINEAR:
2018 break;
2019 case SEG_MIRRORED:
2020 /* Mirrors are pretty complicated - now in separate function */
2021 r = _mirror_emit_segment_line(dmt, seg, params, paramsize);
2022 if (!r)
2023 return_0;
2024 break;
2025 case SEG_REPLICATOR:
2026 if ((r = _replicator_emit_segment_line(seg, params, paramsize,
2027 &pos)) <= 0) {
2028 stack;
2029 return r;
2030 }
2031 break;
2032 case SEG_REPLICATOR_DEV:
2033 if (!seg->replicator || !_build_dev_string(originbuf,
2034 sizeof(originbuf),
2035 seg->replicator))
2036 return_0;
2037
2038 EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
2039 break;
2040 case SEG_SNAPSHOT:
2041 case SEG_SNAPSHOT_MERGE:
2042 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
2043 return_0;
2044 if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
2045 return_0;
2046 EMIT_PARAMS(pos, "%s %s %c %d", originbuf, cowbuf,
2047 seg->persistent ? 'P' : 'N', seg->chunk_size);
2048 break;
2049 case SEG_SNAPSHOT_ORIGIN:
2050 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
2051 return_0;
2052 EMIT_PARAMS(pos, "%s", originbuf);
2053 break;
2054 case SEG_STRIPED:
2055 EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
2056 break;
2057 case SEG_CRYPT:
2058 EMIT_PARAMS(pos, "%s%s%s%s%s %s %" PRIu64 " ", seg->cipher,
2059 seg->chainmode ? "-" : "", seg->chainmode ?: "",
2060 seg->iv ? "-" : "", seg->iv ?: "", seg->key,
2061 seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
2062 seg->iv_offset : *seg_start);
2063 break;
2064 case SEG_RAID1:
2065 case SEG_RAID4:
2066 case SEG_RAID5_LA:
2067 case SEG_RAID5_RA:
2068 case SEG_RAID5_LS:
2069 case SEG_RAID5_RS:
2070 case SEG_RAID6_ZR:
2071 case SEG_RAID6_NR:
2072 case SEG_RAID6_NC:
2073 target_type_is_raid = 1;
2074 r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start,
2075 params, paramsize);
2076 if (!r)
2077 return_0;
2078
2079 break;
2080 case SEG_THIN_POOL:
2081 if (!_build_dev_string(metadata, sizeof(metadata), seg->metadata))
2082 return_0;
2083 if (!_build_dev_string(pool, sizeof(pool), seg->pool))
2084 return_0;
2085 EMIT_PARAMS(pos, "%s %s %d %" PRIu64 " %s", metadata, pool,
2086 seg->data_block_size, seg->low_water_mark_size,
2087 seg->skip_block_zeroing ? "1 skip_block_zeroing" : "");
2088 break;
2089 case SEG_THIN:
2090 if (!_build_dev_string(pool, sizeof(pool), seg->pool))
2091 return_0;
2092 EMIT_PARAMS(pos, "%s %d", pool, seg->device_id);
2093 break;
2094 }
2095
2096 switch(seg->type) {
2097 case SEG_ERROR:
2098 case SEG_REPLICATOR:
2099 case SEG_SNAPSHOT:
2100 case SEG_SNAPSHOT_ORIGIN:
2101 case SEG_SNAPSHOT_MERGE:
2102 case SEG_ZERO:
2103 case SEG_THIN_POOL:
2104 case SEG_THIN:
2105 break;
2106 case SEG_CRYPT:
2107 case SEG_LINEAR:
2108 case SEG_REPLICATOR_DEV:
2109 case SEG_STRIPED:
2110 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
2111 stack;
2112 return r;
2113 }
2114 if (!params[0]) {
2115 log_error("No parameters supplied for %s target "
2116 "%u:%u.", dm_segtypes[seg->type].target,
2117 major, minor);
2118 return 0;
2119 }
2120 break;
2121 }
2122
2123 log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64
2124 " %" PRIu64 " %s %s", major, minor,
2125 *seg_start, seg->size, target_type_is_raid ? "raid" :
2126 dm_segtypes[seg->type].target, params);
2127
2128 if (!dm_task_add_target(dmt, *seg_start, seg->size,
2129 target_type_is_raid ? "raid" :
2130 dm_segtypes[seg->type].target, params))
2131 return_0;
2132
2133 *seg_start += seg->size;
2134
2135 return 1;
2136 }
2137
2138 #undef EMIT_PARAMS
2139
2140 static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
2141 struct load_segment *seg, uint64_t *seg_start)
2142 {
2143 char *params;
2144 size_t paramsize = 4096;
2145 int ret;
2146
2147 do {
2148 if (!(params = dm_malloc(paramsize))) {
2149 log_error("Insufficient space for target parameters.");
2150 return 0;
2151 }
2152
2153 params[0] = '\0';
2154 ret = _emit_segment_line(dmt, major, minor, seg, seg_start,
2155 params, paramsize);
2156 dm_free(params);
2157
2158 if (!ret)
2159 stack;
2160
2161 if (ret >= 0)
2162 return ret;
2163
2164 log_debug("Insufficient space in params[%" PRIsize_t
2165 "] for target parameters.", paramsize);
2166
2167 paramsize *= 2;
2168 } while (paramsize < MAX_TARGET_PARAMSIZE);
2169
2170 log_error("Target parameter size too big. Aborting.");
2171 return 0;
2172 }
2173
2174 static int _load_node(struct dm_tree_node *dnode)
2175 {
2176 int r = 0;
2177 struct dm_task *dmt;
2178 struct load_segment *seg;
2179 uint64_t seg_start = 0, existing_table_size;
2180
2181 log_verbose("Loading %s table (%" PRIu32 ":%" PRIu32 ")", dnode->name,
2182 dnode->info.major, dnode->info.minor);
2183
2184 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
2185 log_error("Reload dm_task creation failed for %s", dnode->name);
2186 return 0;
2187 }
2188
2189 if (!dm_task_set_major(dmt, dnode->info.major) ||
2190 !dm_task_set_minor(dmt, dnode->info.minor)) {
2191 log_error("Failed to set device number for %s reload.", dnode->name);
2192 goto out;
2193 }
2194
2195 if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
2196 log_error("Failed to set read only flag for %s", dnode->name);
2197 goto out;
2198 }
2199
2200 if (!dm_task_no_open_count(dmt))
2201 log_error("Failed to disable open_count");
2202
2203 dm_list_iterate_items(seg, &dnode->props.segs)
2204 if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor,
2205 seg, &seg_start))
2206 goto_out;
2207
2208 if (!dm_task_suppress_identical_reload(dmt))
2209 log_error("Failed to suppress reload of identical tables.");
2210
2211 if ((r = dm_task_run(dmt))) {
2212 r = dm_task_get_info(dmt, &dnode->info);
2213 if (r && !dnode->info.inactive_table)
2214 log_verbose("Suppressed %s identical table reload.",
2215 dnode->name);
2216
2217 existing_table_size = dm_task_get_existing_table_size(dmt);
2218 if ((dnode->props.size_changed =
2219 (existing_table_size == seg_start) ? 0 : 1)) {
2220 log_debug("Table size changed from %" PRIu64 " to %"
2221 PRIu64 " for %s", existing_table_size,
2222 seg_start, dnode->name);
2223 /*
2224 * Kernel usually skips size validation on zero-length devices
2225 * now so no need to preload them.
2226 */
2227 /* FIXME In which kernel version did this begin? */
2228 if (!existing_table_size && dnode->props.delay_resume_if_new)
2229 dnode->props.size_changed = 0;
2230 }
2231 }
2232
2233 dnode->props.segment_count = 0;
2234
2235 out:
2236 dm_task_destroy(dmt);
2237
2238 return r;
2239 }
2240
2241 int dm_tree_preload_children(struct dm_tree_node *dnode,
2242 const char *uuid_prefix,
2243 size_t uuid_prefix_len)
2244 {
2245 int r = 1;
2246 void *handle = NULL;
2247 struct dm_tree_node *child;
2248 struct dm_info newinfo;
2249 int update_devs_flag = 0;
2250
2251 /* Preload children first */
2252 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
2253 /* Skip existing non-device-mapper devices */
2254 if (!child->info.exists && child->info.major)
2255 continue;
2256
2257 /* Ignore if it doesn't belong to this VG */
2258 if (child->info.exists &&
2259 !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
2260 continue;
2261
2262 if (dm_tree_node_num_children(child, 0))
2263 if (!dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len))
2264 return_0;
2265
2266 /* FIXME Cope if name exists with no uuid? */
2267 if (!child->info.exists) {
2268 if (!_create_node(child)) {
2269 stack;
2270 return 0;
2271 }
2272 }
2273
2274 if (!child->info.inactive_table && child->props.segment_count) {
2275 if (!_load_node(child)) {
2276 stack;
2277 return 0;
2278 }
2279 }
2280
2281 /* Propagate device size change change */
2282 if (child->props.size_changed)
2283 dnode->props.size_changed = 1;
2284
2285 /* Resume device immediately if it has parents and its size changed */
2286 if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
2287 continue;
2288
2289 if (!child->info.inactive_table && !child->info.suspended)
2290 continue;
2291
2292 if (!_resume_node(child->name, child->info.major, child->info.minor,
2293 child->props.read_ahead, child->props.read_ahead_flags,
2294 &newinfo, &child->dtree->cookie, child->udev_flags,
2295 child->info.suspended)) {
2296 log_error("Unable to resume %s (%" PRIu32
2297 ":%" PRIu32 ")", child->name, child->info.major,
2298 child->info.minor);
2299 r = 0;
2300 continue;
2301 }
2302
2303 /* Update cached info */
2304 child->info = newinfo;
2305
2306 /*
2307 * Prepare for immediate synchronization with udev and flush all stacked
2308 * dev node operations if requested by immediate_dev_node property. But
2309 * finish processing current level in the tree first.
2310 */
2311 if (child->props.immediate_dev_node)
2312 update_devs_flag = 1;
2313 }
2314
2315 handle = NULL;
2316
2317 if (update_devs_flag) {
2318 if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
2319 stack;
2320 dm_tree_set_cookie(dnode, 0);
2321 }
2322
2323 if (r && !_thin_pool_node_send_messages(dnode, uuid_prefix, uuid_prefix_len)) {
2324 stack;
2325 if (!(dm_tree_deactivate_children(dnode, uuid_prefix, uuid_prefix_len)))
2326 log_error("Failed to deactivate %s", dnode->name);
2327 r = 0;
2328 }
2329
2330 return r;
2331 }
2332
2333 /*
2334 * Returns 1 if unsure.
2335 */
2336 int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
2337 const char *uuid_prefix,
2338 size_t uuid_prefix_len)
2339 {
2340 void *handle = NULL;
2341 struct dm_tree_node *child = dnode;
2342 const char *uuid;
2343
2344 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
2345 if (!(uuid = dm_tree_node_get_uuid(child))) {
2346 log_error("Failed to get uuid for dtree node.");
2347 return 1;
2348 }
2349
2350 if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
2351 return 1;
2352
2353 if (dm_tree_node_num_children(child, 0))
2354 dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
2355 }
2356
2357 return 0;
2358 }
2359
2360 /*
2361 * Target functions
2362 */
2363 static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
2364 {
2365 struct load_segment *seg;
2366
2367 if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
2368 log_error("dtree node segment allocation failed");
2369 return NULL;
2370 }
2371
2372 seg->type = type;
2373 seg->size = size;
2374 seg->area_count = 0;
2375 dm_list_init(&seg->areas);
2376 seg->stripe_size = 0;
2377 seg->persistent = 0;
2378 seg->chunk_size = 0;
2379 seg->cow = NULL;
2380 seg->origin = NULL;
2381 seg->merge = NULL;
2382
2383 dm_list_add(&dnode->props.segs, &seg->list);
2384 dnode->props.segment_count++;
2385
2386 return seg;
2387 }
2388
2389 int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
2390 uint64_t size,
2391 const char *origin_uuid)
2392 {
2393 struct load_segment *seg;
2394 struct dm_tree_node *origin_node;
2395
2396 if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
2397 return_0;
2398
2399 if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
2400 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
2401 return 0;
2402 }
2403
2404 seg->origin = origin_node;
2405 if (!_link_tree_nodes(dnode, origin_node))
2406 return_0;
2407
2408 /* Resume snapshot origins after new snapshots */
2409 dnode->activation_priority = 1;
2410
2411 return 1;
2412 }
2413
2414 static int _add_snapshot_target(struct dm_tree_node *node,
2415 uint64_t size,
2416 const char *origin_uuid,
2417 const char *cow_uuid,
2418 const char *merge_uuid,
2419 int persistent,
2420 uint32_t chunk_size)
2421 {
2422 struct load_segment *seg;
2423 struct dm_tree_node *origin_node, *cow_node, *merge_node;
2424 unsigned seg_type;
2425
2426 seg_type = !merge_uuid ? SEG_SNAPSHOT : SEG_SNAPSHOT_MERGE;
2427
2428 if (!(seg = _add_segment(node, seg_type, size)))
2429 return_0;
2430
2431 if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
2432 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
2433 return 0;
2434 }
2435
2436 seg->origin = origin_node;
2437 if (!_link_tree_nodes(node, origin_node))
2438 return_0;
2439
2440 if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
2441 log_error("Couldn't find snapshot COW device uuid %s.", cow_uuid);
2442 return 0;
2443 }
2444
2445 seg->cow = cow_node;
2446 if (!_link_tree_nodes(node, cow_node))
2447 return_0;
2448
2449 seg->persistent = persistent ? 1 : 0;
2450 seg->chunk_size = chunk_size;
2451
2452 if (merge_uuid) {
2453 if (!(merge_node = dm_tree_find_node_by_uuid(node->dtree, merge_uuid))) {
2454 /* not a pure error, merging snapshot may have been deactivated */
2455 log_verbose("Couldn't find merging snapshot uuid %s.", merge_uuid);
2456 } else {
2457 seg->merge = merge_node;
2458 /* must not link merging snapshot, would undermine activation_priority below */
2459 }
2460
2461 /* Resume snapshot-merge (acting origin) after other snapshots */
2462 node->activation_priority = 1;
2463 if (seg->merge) {
2464 /* Resume merging snapshot after snapshot-merge */
2465 seg->merge->activation_priority = 2;
2466 }
2467 }
2468
2469 return 1;
2470 }
2471
2472
2473 int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
2474 uint64_t size,
2475 const char *origin_uuid,
2476 const char *cow_uuid,
2477 int persistent,
2478 uint32_t chunk_size)
2479 {
2480 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2481 NULL, persistent, chunk_size);
2482 }
2483
2484 int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
2485 uint64_t size,
2486 const char *origin_uuid,
2487 const char *cow_uuid,
2488 const char *merge_uuid,
2489 uint32_t chunk_size)
2490 {
2491 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2492 merge_uuid, 1, chunk_size);
2493 }
2494
2495 int dm_tree_node_add_error_target(struct dm_tree_node *node,
2496 uint64_t size)
2497 {
2498 if (!_add_segment(node, SEG_ERROR, size))
2499 return_0;
2500
2501 return 1;
2502 }
2503
2504 int dm_tree_node_add_zero_target(struct dm_tree_node *node,
2505 uint64_t size)
2506 {
2507 if (!_add_segment(node, SEG_ZERO, size))
2508 return_0;
2509
2510 return 1;
2511 }
2512
2513 int dm_tree_node_add_linear_target(struct dm_tree_node *node,
2514 uint64_t size)
2515 {
2516 if (!_add_segment(node, SEG_LINEAR, size))
2517 return_0;
2518
2519 return 1;
2520 }
2521
2522 int dm_tree_node_add_striped_target(struct dm_tree_node *node,
2523 uint64_t size,
2524 uint32_t stripe_size)
2525 {
2526 struct load_segment *seg;
2527
2528 if (!(seg = _add_segment(node, SEG_STRIPED, size)))
2529 return_0;
2530
2531 seg->stripe_size = stripe_size;
2532
2533 return 1;
2534 }
2535
2536 int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
2537 uint64_t size,
2538 const char *cipher,
2539 const char *chainmode,
2540 const char *iv,
2541 uint64_t iv_offset,
2542 const char *key)
2543 {
2544 struct load_segment *seg;
2545
2546 if (!(seg = _add_segment(node, SEG_CRYPT, size)))
2547 return_0;
2548
2549 seg->cipher = cipher;
2550 seg->chainmode = chainmode;
2551 seg->iv = iv;
2552 seg->iv_offset = iv_offset;
2553 seg->key = key;
2554
2555 return 1;
2556 }
2557
2558 int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
2559 uint32_t region_size,
2560 unsigned clustered,
2561 const char *log_uuid,
2562 unsigned area_count,
2563 uint32_t flags)
2564 {
2565 struct dm_tree_node *log_node = NULL;
2566 struct load_segment *seg;
2567
2568 if (!node->props.segment_count) {
2569 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
2570 return 0;
2571 }
2572
2573 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2574
2575 if (log_uuid) {
2576 if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
2577 log_error("log uuid pool_strdup failed");
2578 return 0;
2579 }
2580 if ((flags & DM_CORELOG))
2581 /* For pvmove: immediate resume (for size validation) isn't needed. */
2582 node->props.delay_resume_if_new = 1;
2583 else {
2584 if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
2585 log_error("Couldn't find mirror log uuid %s.", log_uuid);
2586 return 0;
2587 }
2588
2589 if (clustered)
2590 log_node->props.immediate_dev_node = 1;
2591
2592 /* The kernel validates the size of disk logs. */
2593 /* FIXME Propagate to any devices below */
2594 log_node->props.delay_resume_if_new = 0;
2595
2596 if (!_link_tree_nodes(node, log_node))
2597 return_0;
2598 }
2599 }
2600
2601 seg->log = log_node;
2602 seg->region_size = region_size;
2603 seg->clustered = clustered;
2604 seg->mirror_area_count = area_count;
2605 seg->flags = flags;
2606
2607 return 1;
2608 }
2609
2610 int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
2611 uint64_t size)
2612 {
2613 if (!_add_segment(node, SEG_MIRRORED, size))
2614 return_0;
2615
2616 return 1;
2617 }
2618
2619 int dm_tree_node_add_raid_target(struct dm_tree_node *node,
2620 uint64_t size,
2621 const char *raid_type,
2622 uint32_t region_size,
2623 uint32_t stripe_size,
2624 uint64_t rebuilds,
2625 uint64_t reserved2)
2626 {
2627 int i;
2628 struct load_segment *seg = NULL;
2629
2630 for (i = 0; dm_segtypes[i].target && !seg; i++)
2631 if (!strcmp(raid_type, dm_segtypes[i].target))
2632 if (!(seg = _add_segment(node,
2633 dm_segtypes[i].type, size)))
2634 return_0;
2635
2636 if (!seg)
2637 return_0;
2638
2639 seg->region_size = region_size;
2640 seg->stripe_size = stripe_size;
2641 seg->area_count = 0;
2642 seg->rebuilds = rebuilds;
2643
2644 return 1;
2645 }
2646
2647 int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
2648 uint64_t size,
2649 const char *rlog_uuid,
2650 const char *rlog_type,
2651 unsigned rsite_index,
2652 dm_replicator_mode_t mode,
2653 uint32_t async_timeout,
2654 uint64_t fall_behind_data,
2655 uint32_t fall_behind_ios)
2656 {
2657 struct load_segment *rseg;
2658 struct replicator_site *rsite;
2659
2660 /* Local site0 - adds replicator segment and links rlog device */
2661 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2662 if (node->props.segment_count) {
2663 log_error(INTERNAL_ERROR "Attempt to add replicator segment to already used node.");
2664 return 0;
2665 }
2666
2667 if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
2668 return_0;
2669
2670 if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
2671 log_error("Missing replicator log uuid %s.", rlog_uuid);
2672 return 0;
2673 }
2674
2675 if (!_link_tree_nodes(node, rseg->log))
2676 return_0;
2677
2678 if (strcmp(rlog_type, "ringbuffer") != 0) {
2679 log_error("Unsupported replicator log type %s.", rlog_type);
2680 return 0;
2681 }
2682
2683 if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
2684 return_0;
2685
2686 dm_list_init(&rseg->rsites);
2687 rseg->rdevice_count = 0;
2688 node->activation_priority = 1;
2689 }
2690
2691 /* Add site to segment */
2692 if (mode == DM_REPLICATOR_SYNC
2693 && (async_timeout || fall_behind_ios || fall_behind_data)) {
2694 log_error("Async parameters passed for synchronnous replicator.");
2695 return 0;
2696 }
2697
2698 if (node->props.segment_count != 1) {
2699 log_error(INTERNAL_ERROR "Attempt to add remote site area before setting replicator log.");
2700 return 0;
2701 }
2702
2703 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2704 if (rseg->type != SEG_REPLICATOR) {
2705 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2706 dm_segtypes[rseg->type].target);
2707 return 0;
2708 }
2709
2710 if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof(*rsite)))) {
2711 log_error("Failed to allocate remote site segment.");
2712 return 0;
2713 }
2714
2715 dm_list_add(&rseg->rsites, &rsite->list);
2716 rseg->rsite_count++;
2717
2718 rsite->mode = mode;
2719 rsite->async_timeout = async_timeout;
2720 rsite->fall_behind_data = fall_behind_data;
2721 rsite->fall_behind_ios = fall_behind_ios;
2722 rsite->rsite_index = rsite_index;
2723
2724 return 1;
2725 }
2726
2727 /* Appends device node to Replicator */
2728 int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
2729 uint64_t size,
2730 const char *replicator_uuid,
2731 uint64_t rdevice_index,
2732 const char *rdev_uuid,
2733 unsigned rsite_index,
2734 const char *slog_uuid,
2735 uint32_t slog_flags,
2736 uint32_t slog_region_size)
2737 {
2738 struct seg_area *area;
2739 struct load_segment *rseg;
2740 struct load_segment *rep_seg;
2741
2742 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2743 /* Site index for local target */
2744 if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
2745 return_0;
2746
2747 if (!(rseg->replicator = dm_tree_find_node_by_uuid(node->dtree, replicator_uuid))) {
2748 log_error("Missing replicator uuid %s.", replicator_uuid);
2749 return 0;
2750 }
2751
2752 /* Local slink0 for replicator must be always initialized first */
2753 if (rseg->replicator->props.segment_count != 1) {
2754 log_error(INTERNAL_ERROR "Attempt to use non replicator segment.");
2755 return 0;
2756 }
2757
2758 rep_seg = dm_list_item(dm_list_last(&rseg->replicator->props.segs), struct load_segment);
2759 if (rep_seg->type != SEG_REPLICATOR) {
2760 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2761 dm_segtypes[rep_seg->type].target);
2762 return 0;
2763 }
2764 rep_seg->rdevice_count++;
2765
2766 if (!_link_tree_nodes(node, rseg->replicator))
2767 return_0;
2768
2769 rseg->rdevice_index = rdevice_index;
2770 } else {
2771 /* Local slink0 for replicator must be always initialized first */
2772 if (node->props.segment_count != 1) {
2773 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment.");
2774 return 0;
2775 }
2776
2777 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2778 if (rseg->type != SEG_REPLICATOR_DEV) {
2779 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment %s.",
2780 dm_segtypes[rseg->type].target);
2781 return 0;
2782 }
2783 }
2784
2785 if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
2786 log_error("Unspecified sync log uuid.");
2787 return 0;
2788 }
2789
2790 if (!dm_tree_node_add_target_area(node, NULL, rdev_uuid, 0))
2791 return_0;
2792
2793 area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
2794
2795 if (!(slog_flags & DM_CORELOG)) {
2796 if (!(area->slog = dm_tree_find_node_by_uuid(node->dtree, slog_uuid))) {
2797 log_error("Couldn't find sync log uuid %s.", slog_uuid);
2798 return 0;
2799 }
2800
2801 if (!_link_tree_nodes(node, area->slog))
2802 return_0;
2803 }
2804
2805 area->flags = slog_flags;
2806 area->region_size = slog_region_size;
2807 area->rsite_index = rsite_index;
2808
2809 return 1;
2810 }
2811
2812 static int _thin_validate_device_id(uint32_t device_id)
2813 {
2814 if (device_id > DM_THIN_MAX_DEVICE_ID) {
2815 log_error("Device id %u is higher then %u.",
2816 device_id, DM_THIN_MAX_DEVICE_ID);
2817 return 0;
2818 }
2819
2820 return 1;
2821 }
2822
2823 int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
2824 uint64_t size,
2825 uint64_t transaction_id,
2826 const char *metadata_uuid,
2827 const char *pool_uuid,
2828 uint32_t data_block_size,
2829 uint64_t low_water_mark_size,
2830 unsigned skip_block_zeroing)
2831 {
2832 struct load_segment *seg;
2833
2834 if (data_block_size < DM_THIN_MIN_DATA_SIZE) {
2835 log_error("Data block size %u is lower then %u sectors.",
2836 data_block_size, DM_THIN_MIN_DATA_SIZE);
2837 return 0;
2838 }
2839
2840 if (data_block_size > DM_THIN_MAX_DATA_SIZE) {
2841 log_error("Data block size %u is higher then %u sectors.",
2842 data_block_size, DM_THIN_MAX_DATA_SIZE);
2843 return 0;
2844 }
2845
2846 if (!(seg = _add_segment(node, SEG_THIN_POOL, size)))
2847 return_0;
2848
2849 if (!(seg->metadata = dm_tree_find_node_by_uuid(node->dtree, metadata_uuid))) {
2850 log_error("Missing metadata uuid %s.", metadata_uuid);
2851 return 0;
2852 }
2853
2854 if (!_link_tree_nodes(node, seg->metadata))
2855 return_0;
2856
2857 if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
2858 log_error("Missing pool uuid %s.", pool_uuid);
2859 return 0;
2860 }
2861
2862 if (!_link_tree_nodes(node, seg->pool))
2863 return_0;
2864
2865 node->props.thin_pool_transaction_id = transaction_id; // compare on resume
2866 seg->low_water_mark_size = low_water_mark_size;
2867 seg->data_block_size = data_block_size;
2868 seg->skip_block_zeroing = skip_block_zeroing;
2869 dm_list_init(&seg->thin_messages);
2870
2871 return 1;
2872 }
2873
2874 int dm_tree_node_add_thin_pool_message(struct dm_tree_node *node,
2875 struct dm_thin_message *message)
2876 {
2877 struct load_segment *seg;
2878 struct thin_message *tm;
2879
2880 if (node->props.segment_count != 1) {
2881 log_error(INTERNAL_ERROR "Attempt to use non thin pool segment.");
2882 return 0;
2883 }
2884
2885 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2886
2887 if (seg->type != SEG_THIN_POOL) {
2888 log_error(INTERNAL_ERROR "Attempt to use non thin pool segment %s.",
2889 dm_segtypes[seg->type].target);
2890 return 0;
2891 }
2892
2893 if (!(tm = dm_pool_zalloc(node->dtree->mem, sizeof (*tm)))) {
2894 log_error("Failed to allocate thin message.");
2895 return 0;
2896 }
2897
2898 switch (message->type) {
2899 case DM_THIN_MESSAGE_CREATE_SNAP:
2900 /* Origin MUST be suspend! */
2901 if (message->u.m_create_snap.device_id == message->u.m_create_snap.origin_id) {
2902 log_error("Same origin used for thin snapshot.");
2903 return 0;
2904 }
2905 if (!_thin_validate_device_id(message->u.m_create_snap.device_id) ||
2906 !_thin_validate_device_id(message->u.m_create_snap.origin_id))
2907 return_0;
2908 tm->message.u.m_create_snap.device_id = message->u.m_create_snap.device_id;
2909 tm->message.u.m_create_snap.origin_id = message->u.m_create_snap.origin_id;
2910 break;
2911 case DM_THIN_MESSAGE_CREATE_THIN:
2912 if (!_thin_validate_device_id(message->u.m_create_thin.device_id))
2913 return_0;
2914 tm->message.u.m_create_thin.device_id = message->u.m_create_thin.device_id;
2915 break;
2916 case DM_THIN_MESSAGE_DELETE:
2917 if (!_thin_validate_device_id(message->u.m_delete.device_id))
2918 return_0;
2919 tm->message.u.m_delete.device_id = message->u.m_delete.device_id;
2920 break;
2921 case DM_THIN_MESSAGE_TRIM:
2922 if (!_thin_validate_device_id(message->u.m_trim.device_id))
2923 return_0;
2924 tm->message.u.m_trim.device_id = message->u.m_trim.device_id;
2925 tm->message.u.m_trim.new_size = message->u.m_trim.new_size;
2926 break;
2927 case DM_THIN_MESSAGE_SET_TRANSACTION_ID:
2928 if (message->u.m_set_transaction_id.current_id !=
2929 (message->u.m_set_transaction_id.new_id - 1)) {
2930 log_error("New transaction_id must be sequential.");
2931 return 0; /* FIXME: Maybe too strict here? */
2932 }
2933 tm->message.u.m_set_transaction_id.current_id =
2934 message->u.m_set_transaction_id.current_id;
2935 tm->message.u.m_set_transaction_id.new_id =
2936 message->u.m_set_transaction_id.new_id;
2937 break;
2938 default:
2939 log_error("Unsupported message type %d.", (int) message->type);
2940 return 0;
2941 }
2942
2943 tm->message.type = message->type;
2944 dm_list_add(&seg->thin_messages, &tm->list);
2945
2946 return 1;
2947 }
2948
2949 int dm_tree_node_add_thin_target(struct dm_tree_node *node,
2950 uint64_t size,
2951 const char *thin_pool_uuid,
2952 uint32_t device_id)
2953 {
2954 struct load_segment *seg;
2955
2956 if (!_thin_validate_device_id(device_id))
2957 return_0;
2958
2959 if (!(seg = _add_segment(node, SEG_THIN, size)))
2960 return_0;
2961
2962 if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, thin_pool_uuid))) {
2963 log_error("Missing thin pool uuid %s.", thin_pool_uuid);
2964 return 0;
2965 }
2966
2967 if (!_link_tree_nodes(node, seg->pool))
2968 return_0;
2969
2970 seg->device_id = device_id;
2971
2972 return 1;
2973 }
2974
2975 static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
2976 {
2977 struct seg_area *area;
2978
2979 if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
2980 log_error("Failed to allocate target segment area.");
2981 return 0;
2982 }
2983
2984 area->dev_node = dev_node;
2985 area->offset = offset;
2986
2987 dm_list_add(&seg->areas, &area->list);
2988 seg->area_count++;
2989
2990 return 1;
2991 }
2992
2993 int dm_tree_node_add_target_area(struct dm_tree_node *node,
2994 const char *dev_name,
2995 const char *uuid,
2996 uint64_t offset)
2997 {
2998 struct load_segment *seg;
2999 struct stat info;
3000 struct dm_tree_node *dev_node;
3001
3002 if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
3003 log_error("dm_tree_node_add_target_area called without device");
3004 return 0;
3005 }
3006
3007 if (uuid) {
3008 if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
3009 log_error("Couldn't find area uuid %s.", uuid);
3010 return 0;
3011 }
3012 if (!_link_tree_nodes(node, dev_node))
3013 return_0;
3014 } else {
3015 if (stat(dev_name, &info) < 0) {
3016 log_error("Device %s not found.", dev_name);
3017 return 0;
3018 }
3019
3020 if (!S_ISBLK(info.st_mode)) {
3021 log_error("Device %s is not a block device.", dev_name);
3022 return 0;
3023 }
3024
3025 /* FIXME Check correct macro use */
3026 if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev),
3027 MINOR(info.st_rdev), 0)))
3028 return_0;
3029 }
3030
3031 if (!node->props.segment_count) {
3032 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
3033 return 0;
3034 }
3035
3036 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
3037
3038 if (!_add_area(node, seg, dev_node, offset))
3039 return_0;
3040
3041 return 1;
3042 }
3043
3044 int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset)
3045 {
3046 struct load_segment *seg;
3047
3048 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
3049
3050 switch (seg->type) {
3051 case SEG_RAID1:
3052 case SEG_RAID4:
3053 case SEG_RAID5_LA:
3054 case SEG_RAID5_RA:
3055 case SEG_RAID5_LS:
3056 case SEG_RAID5_RS:
3057 case SEG_RAID6_ZR:
3058 case SEG_RAID6_NR:
3059 case SEG_RAID6_NC:
3060 break;
3061 default:
3062 log_error("dm_tree_node_add_null_area() called on an unsupported segment type");
3063 return 0;
3064 }
3065
3066 if (!_add_area(node, seg, NULL, offset))
3067 return_0;
3068
3069 return 1;
3070 }
3071
3072 void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie)
3073 {
3074 node->dtree->cookie = cookie;
3075 }
3076
3077 uint32_t dm_tree_get_cookie(struct dm_tree_node *node)
3078 {
3079 return node->dtree->cookie;
3080 }
This page took 0.181008 seconds and 6 git commands to generate.