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