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