Import lvm2 from NetBSD
[dragonfly.git] / contrib / lvm2 / dist / libdm / libdm-deptree.c
1 /*      $NetBSD: libdm-deptree.c,v 1.4 2009/12/02 00:58:03 haad Exp $   */
2
3 /*
4  * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
5  *
6  * This file is part of the device-mapper userspace tools.
7  *
8  * This copyrighted material is made available to anyone wishing to use,
9  * modify, copy, or redistribute it subject to the terms and conditions
10  * of the GNU Lesser General Public License v.2.1.
11  *
12  * You should have received a copy of the GNU Lesser General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 #include "dmlib.h"
18 #include "libdm-targets.h"
19 #include "libdm-common.h"
20 #include "kdev_t.h"
21 #include "dm-ioctl.h"
22
23 #include <stdarg.h>
24 #include <sys/param.h>
25 #include <sys/utsname.h>
26
27 #define MAX_TARGET_PARAMSIZE 500000
28
29 /* FIXME Fix interface so this is used only by LVM */
30 #define UUID_PREFIX "LVM-"
31
32 /* Supported segment types */
33 enum {
34         SEG_CRYPT,
35         SEG_ERROR,
36         SEG_LINEAR,
37         SEG_MIRRORED,
38         SEG_SNAPSHOT,
39         SEG_SNAPSHOT_ORIGIN,
40         SEG_STRIPED,
41         SEG_ZERO,
42 };
43
44 /* FIXME Add crypt and multipath support */
45
46 struct {
47         unsigned type;
48         const char *target;
49 } dm_segtypes[] = {
50         { SEG_CRYPT, "crypt" },
51         { SEG_ERROR, "error" },
52         { SEG_LINEAR, "linear" },
53         { SEG_MIRRORED, "mirror" },
54         { SEG_SNAPSHOT, "snapshot" },
55         { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
56         { SEG_STRIPED, "striped" },
57         { SEG_ZERO, "zero"},
58 };
59
60 /* Some segment types have a list of areas of other devices attached */
61 struct seg_area {
62         struct dm_list list;
63
64         struct dm_tree_node *dev_node;
65
66         uint64_t offset;
67 };
68
69 /* Per-segment properties */
70 struct load_segment {
71         struct dm_list list;
72
73         unsigned type;
74
75         uint64_t size;
76
77         unsigned area_count;            /* Linear + Striped + Mirrored + Crypt */
78         struct dm_list areas;           /* Linear + Striped + Mirrored + Crypt */
79
80         uint32_t stripe_size;           /* Striped */
81
82         int persistent;                 /* Snapshot */
83         uint32_t chunk_size;            /* Snapshot */
84         struct dm_tree_node *cow;       /* Snapshot */
85         struct dm_tree_node *origin;    /* Snapshot + Snapshot origin */
86
87         struct dm_tree_node *log;       /* Mirror */
88         uint32_t region_size;           /* Mirror */
89         unsigned clustered;             /* Mirror */
90         unsigned mirror_area_count;     /* Mirror */
91         uint32_t flags;                 /* Mirror log */
92         char *uuid;                     /* Clustered mirror log */
93
94         const char *cipher;             /* Crypt */
95         const char *chainmode;          /* Crypt */
96         const char *iv;                 /* Crypt */
97         uint64_t iv_offset;             /* Crypt */
98         const char *key;                /* Crypt */
99 };
100
101 /* Per-device properties */
102 struct load_properties {
103         int read_only;
104         uint32_t major;
105         uint32_t minor;
106
107         uint32_t read_ahead;
108         uint32_t read_ahead_flags;
109
110         unsigned segment_count;
111         unsigned size_changed;
112         struct dm_list segs;
113
114         const char *new_name;
115 };
116
117 /* Two of these used to join two nodes with uses and used_by. */
118 struct dm_tree_link {
119         struct dm_list list;
120         struct dm_tree_node *node;
121 };
122
123 struct dm_tree_node {
124         struct dm_tree *dtree;
125
126         const char *name;
127         const char *uuid;
128         struct dm_info info;
129
130         struct dm_list uses;            /* Nodes this node uses */
131         struct dm_list used_by;         /* Nodes that use this node */
132
133         int activation_priority;        /* 0 gets activated first */
134
135         uint16_t udev_flags;            /* Udev control flags */
136
137         void *context;                  /* External supplied context */
138
139         struct load_properties props;   /* For creation/table (re)load */
140 };
141
142 struct dm_tree {
143         struct dm_pool *mem;
144         struct dm_hash_table *devs;
145         struct dm_hash_table *uuids;
146         struct dm_tree_node root;
147         int skip_lockfs;                /* 1 skips lockfs (for non-snapshots) */
148         int no_flush;           /* 1 sets noflush (mirrors/multipath) */
149         uint32_t cookie;
150 };
151
152 struct dm_tree *dm_tree_create(void)
153 {
154         struct dm_tree *dtree;
155
156         if (!(dtree = dm_malloc(sizeof(*dtree)))) {
157                 log_error("dm_tree_create malloc failed");
158                 return NULL;
159         }
160
161         memset(dtree, 0, sizeof(*dtree));
162         dtree->root.dtree = dtree;
163         dm_list_init(&dtree->root.uses);
164         dm_list_init(&dtree->root.used_by);
165         dtree->skip_lockfs = 0;
166         dtree->no_flush = 0;
167
168         if (!(dtree->mem = dm_pool_create("dtree", 1024))) {
169                 log_error("dtree pool creation failed");
170                 dm_free(dtree);
171                 return NULL;
172         }
173
174         if (!(dtree->devs = dm_hash_create(8))) {
175                 log_error("dtree hash creation failed");
176                 dm_pool_destroy(dtree->mem);
177                 dm_free(dtree);
178                 return NULL;
179         }
180
181         if (!(dtree->uuids = dm_hash_create(32))) {
182                 log_error("dtree uuid hash creation failed");
183                 dm_hash_destroy(dtree->devs);
184                 dm_pool_destroy(dtree->mem);
185                 dm_free(dtree);
186                 return NULL;
187         }
188
189         return dtree;
190 }
191
192 void dm_tree_free(struct dm_tree *dtree)
193 {
194         if (!dtree)
195                 return;
196
197         dm_hash_destroy(dtree->uuids);
198         dm_hash_destroy(dtree->devs);
199         dm_pool_destroy(dtree->mem);
200         dm_free(dtree);
201 }
202
203 static int _nodes_are_linked(struct dm_tree_node *parent,
204                              struct dm_tree_node *child)
205 {
206         struct dm_tree_link *dlink;
207
208         dm_list_iterate_items(dlink, &parent->uses)
209                 if (dlink->node == child)
210                         return 1;
211
212         return 0;
213 }
214
215 static int _link(struct dm_list *list, struct dm_tree_node *node)
216 {
217         struct dm_tree_link *dlink;
218
219         if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
220                 log_error("dtree link allocation failed");
221                 return 0;
222         }
223
224         dlink->node = node;
225         dm_list_add(list, &dlink->list);
226
227         return 1;
228 }
229
230 static int _link_nodes(struct dm_tree_node *parent,
231                        struct dm_tree_node *child)
232 {
233         if (_nodes_are_linked(parent, child))
234                 return 1;
235
236         if (!_link(&parent->uses, child))
237                 return 0;
238
239         if (!_link(&child->used_by, parent))
240                 return 0;
241
242         return 1;
243 }
244
245 static void _unlink(struct dm_list *list, struct dm_tree_node *node)
246 {
247         struct dm_tree_link *dlink;
248
249         dm_list_iterate_items(dlink, list)
250                 if (dlink->node == node) {
251                         dm_list_del(&dlink->list);
252                         break;
253                 }
254 }
255
256 static void _unlink_nodes(struct dm_tree_node *parent,
257                           struct dm_tree_node *child)
258 {
259         if (!_nodes_are_linked(parent, child))
260                 return;
261
262         _unlink(&parent->uses, child);
263         _unlink(&child->used_by, parent);
264 }
265
266 static int _add_to_toplevel(struct dm_tree_node *node)
267 {
268         return _link_nodes(&node->dtree->root, node);
269 }
270
271 static void _remove_from_toplevel(struct dm_tree_node *node)
272 {
273         return _unlink_nodes(&node->dtree->root, node);
274 }
275
276 static int _add_to_bottomlevel(struct dm_tree_node *node)
277 {
278         return _link_nodes(node, &node->dtree->root);
279 }
280
281 static void _remove_from_bottomlevel(struct dm_tree_node *node)
282 {
283         return _unlink_nodes(node, &node->dtree->root);
284 }
285
286 static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
287 {
288         /* Don't link to root node if child already has a parent */
289         if ((parent == &parent->dtree->root)) {
290                 if (dm_tree_node_num_children(child, 1))
291                         return 1;
292         } else
293                 _remove_from_toplevel(child);
294
295         if ((child == &child->dtree->root)) {
296                 if (dm_tree_node_num_children(parent, 0))
297                         return 1;
298         } else
299                 _remove_from_bottomlevel(parent);
300
301         return _link_nodes(parent, child);
302 }
303
304 static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
305                                                  const char *name,
306                                                  const char *uuid,
307                                                  struct dm_info *info,
308                                                  void *context,
309                                                  uint16_t udev_flags)
310 {
311         struct dm_tree_node *node;
312         uint64_t dev;
313
314         if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
315                 log_error("_create_dm_tree_node alloc failed");
316                 return NULL;
317         }
318
319         node->dtree = dtree;
320
321         node->name = name;
322         node->uuid = uuid;
323         node->info = *info;
324         node->context = context;
325         node->udev_flags = udev_flags;
326         node->activation_priority = 0;
327
328         dm_list_init(&node->uses);
329         dm_list_init(&node->used_by);
330         dm_list_init(&node->props.segs);
331
332         dev = MKDEV(info->major, info->minor);
333
334         if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
335                                 sizeof(dev), node)) {
336                 log_error("dtree node hash insertion failed");
337                 dm_pool_free(dtree->mem, node);
338                 return NULL;
339         }
340
341         if (uuid && *uuid &&
342             !dm_hash_insert(dtree->uuids, uuid, node)) {
343                 log_error("dtree uuid hash insertion failed");
344                 dm_hash_remove_binary(dtree->devs, (const char *) &dev,
345                                       sizeof(dev));
346                 dm_pool_free(dtree->mem, node);
347                 return NULL;
348         }
349
350         return node;
351 }
352
353 static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
354                                                uint32_t major, uint32_t minor)
355 {
356         uint64_t dev = MKDEV(major, minor);
357
358         return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
359                                   sizeof(dev));
360 }
361
362 static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
363                                                        const char *uuid)
364 {
365         struct dm_tree_node *node;
366
367         if ((node = dm_hash_lookup(dtree->uuids, uuid)))
368                 return node;
369
370         if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
371                 return NULL;
372
373         return dm_hash_lookup(dtree->uuids, uuid + sizeof(UUID_PREFIX) - 1);
374 }
375
376 static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
377                  const char **name, const char **uuid,
378                  struct dm_info *info, struct dm_deps **deps)
379 {
380         memset(info, 0, sizeof(*info));
381
382         if (!dm_is_dm_major(major)) {
383                 *name = "";
384                 *uuid = "";
385                 *deps = NULL;
386                 info->major = major;
387                 info->minor = minor;
388                 info->exists = 0;
389                 info->live_table = 0;
390                 info->inactive_table = 0;
391                 info->read_only = 0;
392                 return 1;
393         }
394
395         if (!(*dmt = dm_task_create(DM_DEVICE_DEPS))) {
396                 log_error("deps dm_task creation failed");
397                 return 0;
398         }
399
400         if (!dm_task_set_major(*dmt, major)) {
401                 log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
402                           major, minor);
403                 goto failed;
404         }
405
406         if (!dm_task_set_minor(*dmt, minor)) {
407                 log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
408                           major, minor);
409                 goto failed;
410         }
411
412         if (!dm_task_run(*dmt)) {
413                 log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
414                           major, minor);
415                 goto failed;
416         }
417
418         if (!dm_task_get_info(*dmt, info)) {
419                 log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
420                           major, minor);
421                 goto failed;
422         }
423
424         if (!info->exists) {
425                 *name = "";
426                 *uuid = "";
427                 *deps = NULL;
428         } else {
429                 if (info->major != major) {
430                         log_error("Inconsistent dtree major number: %u != %u",
431                                   major, info->major);
432                         goto failed;
433                 }
434                 if (info->minor != minor) {
435                         log_error("Inconsistent dtree minor number: %u != %u",
436                                   minor, info->minor);
437                         goto failed;
438                 }
439                 if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
440                         log_error("name pool_strdup failed");
441                         goto failed;
442                 }
443                 if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
444                         log_error("uuid pool_strdup failed");
445                         goto failed;
446                 }
447                 *deps = dm_task_get_deps(*dmt);
448         }
449
450         return 1;
451
452 failed:
453         dm_task_destroy(*dmt);
454         return 0;
455 }
456
457 static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
458                                      struct dm_tree_node *parent,
459                                      uint32_t major, uint32_t minor)
460 {
461         struct dm_task *dmt = NULL;
462         struct dm_info info;
463         struct dm_deps *deps = NULL;
464         const char *name = NULL;
465         const char *uuid = NULL;
466         struct dm_tree_node *node = NULL;
467         uint32_t i;
468         int new = 0;
469
470         /* Already in tree? */
471         if (!(node = _find_dm_tree_node(dtree, major, minor))) {
472                 if (!_deps(&dmt, dtree->mem, major, minor, &name, &uuid, &info, &deps))
473                         return_NULL;
474
475                 if (!(node = _create_dm_tree_node(dtree, name, uuid, &info,
476                                                   NULL, 0)))
477                         goto_out;
478                 new = 1;
479         }
480
481         if (!_link_tree_nodes(parent, node)) {
482                 node = NULL;
483                 goto_out;
484         }
485
486         /* If node was already in tree, no need to recurse. */
487         if (!new)
488                 goto out;
489
490         /* Can't recurse if not a mapped device or there are no dependencies */
491         if (!node->info.exists || !deps->count) {
492                 if (!_add_to_bottomlevel(node)) {
493                         stack;
494                         node = NULL;
495                 }
496                 goto out;
497         }
498
499         /* Add dependencies to tree */
500         for (i = 0; i < deps->count; i++)
501                 if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
502                               MINOR(deps->device[i]))) {
503                         node = NULL;
504                         goto_out;
505                 }
506
507 out:
508         if (dmt)
509                 dm_task_destroy(dmt);
510
511         return node;
512 }
513
514 static int _node_clear_table(struct dm_tree_node *dnode)
515 {
516         struct dm_task *dmt;
517         struct dm_info *info;
518         const char *name;
519         int r;
520
521         if (!(info = &dnode->info)) {
522                 log_error("_node_clear_table failed: missing info");
523                 return 0;
524         }
525
526         if (!(name = dm_tree_node_get_name(dnode))) {
527                 log_error("_node_clear_table failed: missing name");
528                 return 0;
529         }
530
531         /* Is there a table? */
532         if (!info->exists || !info->inactive_table)
533                 return 1;
534
535         log_verbose("Clearing inactive table %s (%" PRIu32 ":%" PRIu32 ")",
536                     name, info->major, info->minor);
537
538         if (!(dmt = dm_task_create(DM_DEVICE_CLEAR))) {
539                 dm_task_destroy(dmt);
540                 log_error("Table clear dm_task creation failed for %s", name);
541                 return 0;
542         }
543
544         if (!dm_task_set_major(dmt, info->major) ||
545             !dm_task_set_minor(dmt, info->minor)) {
546                 log_error("Failed to set device number for %s table clear", name);
547                 dm_task_destroy(dmt);
548                 return 0;
549         }
550
551         r = dm_task_run(dmt);
552
553         if (!dm_task_get_info(dmt, info)) {
554                 log_error("_node_clear_table failed: info missing after running task for %s", name);
555                 r = 0;
556         }
557
558         dm_task_destroy(dmt);
559
560         return r;
561 }
562
563 struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
564                                             const char *name,
565                                             const char *uuid,
566                                             uint32_t major, uint32_t minor,
567                                             int read_only,
568                                             int clear_inactive,
569                                             void *context)
570 {
571         struct dm_tree_node *dnode;
572         struct dm_info info;
573         const char *name2;
574         const char *uuid2;
575
576         /* Do we need to add node to tree? */
577         if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
578                 if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
579                         log_error("name pool_strdup failed");
580                         return NULL;
581                 }
582                 if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
583                         log_error("uuid pool_strdup failed");
584                         return NULL;
585                 }
586
587                 info.major = 0;
588                 info.minor = 0;
589                 info.exists = 0;
590                 info.live_table = 0;
591                 info.inactive_table = 0;
592                 info.read_only = 0;
593
594                 if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2, &info,
595                                                    context, 0)))
596                         return_NULL;
597
598                 /* Attach to root node until a table is supplied */
599                 if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
600                         return_NULL;
601
602                 dnode->props.major = major;
603                 dnode->props.minor = minor;
604                 dnode->props.new_name = NULL;
605                 dnode->props.size_changed = 0;
606         } else if (strcmp(name, dnode->name)) {
607                 /* Do we need to rename node? */
608                 if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
609                         log_error("name pool_strdup failed");
610                         return 0;
611                 }
612         }
613
614         dnode->props.read_only = read_only ? 1 : 0;
615         dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
616         dnode->props.read_ahead_flags = 0;
617
618         if (clear_inactive && !_node_clear_table(dnode))
619                 return_NULL;
620
621         dnode->context = context;
622         dnode->udev_flags = 0;
623
624         return dnode;
625 }
626
627 struct dm_tree_node *dm_tree_add_new_dev_with_udev_flags(struct dm_tree *dtree,
628                                                          const char *name,
629                                                          const char *uuid,
630                                                          uint32_t major,
631                                                          uint32_t minor,
632                                                          int read_only,
633                                                          int clear_inactive,
634                                                          void *context,
635                                                          uint16_t udev_flags)
636 {
637         struct dm_tree_node *node;
638
639         if ((node = dm_tree_add_new_dev(dtree, name, uuid, major, minor, read_only,
640                                        clear_inactive, context)))
641                 node->udev_flags = udev_flags;
642
643         return node;
644 }
645
646
647 void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
648                                  uint32_t read_ahead,
649                                  uint32_t read_ahead_flags)
650 {                          
651         dnode->props.read_ahead = read_ahead;
652         dnode->props.read_ahead_flags = read_ahead_flags;
653 }
654
655 int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
656 {
657         return _add_dev(dtree, &dtree->root, major, minor) ? 1 : 0;
658 }
659
660 const char *dm_tree_node_get_name(struct dm_tree_node *node)
661 {
662         return node->info.exists ? node->name : "";
663 }
664
665 const char *dm_tree_node_get_uuid(struct dm_tree_node *node)
666 {
667         return node->info.exists ? node->uuid : "";
668 }
669
670 const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node)
671 {
672         return &node->info;
673 }
674
675 void *dm_tree_node_get_context(struct dm_tree_node *node)
676 {
677         return node->context;
678 }
679
680 int dm_tree_node_size_changed(struct dm_tree_node *dnode)
681 {
682         return dnode->props.size_changed;
683 }
684
685 int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted)
686 {
687         if (inverted) {
688                 if (_nodes_are_linked(&node->dtree->root, node))
689                         return 0;
690                 return dm_list_size(&node->used_by);
691         }
692
693         if (_nodes_are_linked(node, &node->dtree->root))
694                 return 0;
695
696         return dm_list_size(&node->uses);
697 }
698
699 /*
700  * Returns 1 if no prefix supplied
701  */
702 static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len)
703 {
704         if (!uuid_prefix)
705                 return 1;
706
707         if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
708                 return 1;
709
710         /* Handle transition: active device uuids might be missing the prefix */
711         if (uuid_prefix_len <= 4)
712                 return 0;
713
714         if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
715                 return 0;
716
717         if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
718                 return 0;
719
720         if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
721                 return 1;
722
723         return 0;
724 }
725
726 /*
727  * Returns 1 if no children.
728  */
729 static int _children_suspended(struct dm_tree_node *node,
730                                uint32_t inverted,
731                                const char *uuid_prefix,
732                                size_t uuid_prefix_len)
733 {
734         struct dm_list *list;
735         struct dm_tree_link *dlink;
736         const struct dm_info *dinfo;
737         const char *uuid;
738
739         if (inverted) {
740                 if (_nodes_are_linked(&node->dtree->root, node))
741                         return 1;
742                 list = &node->used_by;
743         } else {
744                 if (_nodes_are_linked(node, &node->dtree->root))
745                         return 1;
746                 list = &node->uses;
747         }
748
749         dm_list_iterate_items(dlink, list) {
750                 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
751                         stack;
752                         continue;
753                 }
754
755                 /* Ignore if it doesn't belong to this VG */
756                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
757                         continue;
758
759                 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
760                         stack;  /* FIXME Is this normal? */
761                         return 0;
762                 }
763
764                 if (!dinfo->suspended)
765                         return 0;
766         }
767
768         return 1;
769 }
770
771 /*
772  * Set major and minor to zero for root of tree.
773  */
774 struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
775                                           uint32_t major,
776                                           uint32_t minor)
777 {
778         if (!major && !minor)
779                 return &dtree->root;
780
781         return _find_dm_tree_node(dtree, major, minor);
782 }
783
784 /*
785  * Set uuid to NULL for root of tree.
786  */
787 struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
788                                                   const char *uuid)
789 {
790         if (!uuid || !*uuid)
791                 return &dtree->root;
792
793         return _find_dm_tree_node_by_uuid(dtree, uuid);
794 }
795
796 /*
797  * First time set *handle to NULL.
798  * Set inverted to invert the tree.
799  */
800 struct dm_tree_node *dm_tree_next_child(void **handle,
801                                            struct dm_tree_node *parent,
802                                            uint32_t inverted)
803 {
804         struct dm_list **dlink = (struct dm_list **) handle;
805         struct dm_list *use_list;
806
807         if (inverted)
808                 use_list = &parent->used_by;
809         else
810                 use_list = &parent->uses;
811
812         if (!*dlink)
813                 *dlink = dm_list_first(use_list);
814         else
815                 *dlink = dm_list_next(use_list, *dlink);
816
817         return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
818 }
819
820 /*
821  * Deactivate a device with its dependencies if the uuid prefix matches.
822  */
823 static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
824                         struct dm_info *info)
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                 r = dm_task_get_info(dmt, info);
845
846         dm_task_destroy(dmt);
847
848         return r;
849 }
850
851 static int _deactivate_node(const char *name, uint32_t major, uint32_t minor,
852                             uint32_t *cookie, uint16_t udev_flags)
853 {
854         struct dm_task *dmt;
855         int r = 0;
856
857         log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
858
859         if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {
860                 log_error("Deactivation dm_task creation failed for %s", name);
861                 return 0;
862         }
863
864         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
865                 log_error("Failed to set device number for %s deactivation", name);
866                 goto out;
867         }
868
869         if (!dm_task_no_open_count(dmt))
870                 log_error("Failed to disable open_count");
871
872         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
873                 goto out;
874
875         r = dm_task_run(dmt);
876
877         /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
878         rm_dev_node(name, dmt->cookie_set);
879
880         /* FIXME Remove node from tree or mark invalid? */
881
882 out:
883         dm_task_destroy(dmt);
884
885         return r;
886 }
887
888 static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
889                         uint32_t minor, uint32_t *cookie, uint16_t udev_flags)
890 {
891         struct dm_task *dmt;
892         int r = 0;
893
894         log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);
895
896         if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {
897                 log_error("Rename dm_task creation failed for %s", old_name);
898                 return 0;
899         }
900
901         if (!dm_task_set_name(dmt, old_name)) {
902                 log_error("Failed to set name for %s rename.", old_name);
903                 goto out;
904         }
905
906         if (!dm_task_set_newname(dmt, new_name))
907                 goto_out;
908
909         if (!dm_task_no_open_count(dmt))
910                 log_error("Failed to disable open_count");
911
912         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
913                 goto out;
914
915         r = dm_task_run(dmt);
916
917 out:
918         dm_task_destroy(dmt);
919
920         return r;
921 }
922
923 /* FIXME Merge with _suspend_node? */
924 static int _resume_node(const char *name, uint32_t major, uint32_t minor,
925                         uint32_t read_ahead, uint32_t read_ahead_flags,
926                         struct dm_info *newinfo, uint32_t *cookie,
927                         uint16_t udev_flags)
928 {
929         struct dm_task *dmt;
930         int r = 0;
931
932         log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
933
934         if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {
935                 log_error("Suspend dm_task creation failed for %s", name);
936                 return 0;
937         }
938
939         /* FIXME Kernel should fill in name on return instead */
940         if (!dm_task_set_name(dmt, name)) {
941                 log_error("Failed to set readahead device name for %s", name);
942                 goto out;
943         }
944
945         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
946                 log_error("Failed to set device number for %s resumption.", name);
947                 goto out;
948         }
949
950         if (!dm_task_no_open_count(dmt))
951                 log_error("Failed to disable open_count");
952
953         if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
954                 log_error("Failed to set read ahead");
955
956         if (!dm_task_set_cookie(dmt, cookie, udev_flags))
957                 goto out;
958
959         if ((r = dm_task_run(dmt)))
960                 r = dm_task_get_info(dmt, newinfo);
961
962 out:
963         dm_task_destroy(dmt);
964
965         return r;
966 }
967
968 static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
969                          int skip_lockfs, int no_flush, struct dm_info *newinfo)
970 {
971         struct dm_task *dmt;
972         int r;
973
974         log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
975                     name, major, minor,
976                     skip_lockfs ? "" : " with filesystem sync",
977                     no_flush ? "" : " with device flush");
978
979         if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
980                 log_error("Suspend dm_task creation failed for %s", name);
981                 return 0;
982         }
983
984         if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
985                 log_error("Failed to set device number for %s suspension.", name);
986                 dm_task_destroy(dmt);
987                 return 0;
988         }
989
990         if (!dm_task_no_open_count(dmt))
991                 log_error("Failed to disable open_count");
992
993         if (skip_lockfs && !dm_task_skip_lockfs(dmt))
994                 log_error("Failed to set skip_lockfs flag.");
995
996         if (no_flush && !dm_task_no_flush(dmt))
997                 log_error("Failed to set no_flush flag.");
998
999         if ((r = dm_task_run(dmt)))
1000                 r = dm_task_get_info(dmt, newinfo);
1001
1002         dm_task_destroy(dmt);
1003
1004         return r;
1005 }
1006
1007 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
1008                                    const char *uuid_prefix,
1009                                    size_t uuid_prefix_len)
1010 {
1011         void *handle = NULL;
1012         struct dm_tree_node *child = dnode;
1013         struct dm_info info;
1014         const struct dm_info *dinfo;
1015         const char *name;
1016         const char *uuid;
1017
1018         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1019                 if (!(dinfo = dm_tree_node_get_info(child))) {
1020                         stack;
1021                         continue;
1022                 }
1023
1024                 if (!(name = dm_tree_node_get_name(child))) {
1025                         stack;
1026                         continue;
1027                 }
1028
1029                 if (!(uuid = dm_tree_node_get_uuid(child))) {
1030                         stack;
1031                         continue;
1032                 }
1033
1034                 /* Ignore if it doesn't belong to this VG */
1035                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1036                         continue;
1037
1038                 /* Refresh open_count */
1039                 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
1040                     !info.exists || info.open_count)
1041                         continue;
1042
1043                 if (!_deactivate_node(name, info.major, info.minor,
1044                                       &child->dtree->cookie, child->udev_flags)) {
1045                         log_error("Unable to deactivate %s (%" PRIu32
1046                                   ":%" PRIu32 ")", name, info.major,
1047                                   info.minor);
1048                         continue;
1049                 }
1050
1051                 if (dm_tree_node_num_children(child, 0))
1052                         dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len);
1053         }
1054
1055         return 1;
1056 }
1057
1058 void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
1059 {
1060         dnode->dtree->skip_lockfs = 1;
1061 }
1062
1063 void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
1064 {
1065         dnode->dtree->no_flush = 1;
1066 }
1067
1068 int dm_tree_suspend_children(struct dm_tree_node *dnode,
1069                                    const char *uuid_prefix,
1070                                    size_t uuid_prefix_len)
1071 {
1072         void *handle = NULL;
1073         struct dm_tree_node *child = dnode;
1074         struct dm_info info, newinfo;
1075         const struct dm_info *dinfo;
1076         const char *name;
1077         const char *uuid;
1078
1079         /* Suspend nodes at this level of the tree */
1080         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1081                 if (!(dinfo = dm_tree_node_get_info(child))) {
1082                         stack;
1083                         continue;
1084                 }
1085
1086                 if (!(name = dm_tree_node_get_name(child))) {
1087                         stack;
1088                         continue;
1089                 }
1090
1091                 if (!(uuid = dm_tree_node_get_uuid(child))) {
1092                         stack;
1093                         continue;
1094                 }
1095
1096                 /* Ignore if it doesn't belong to this VG */
1097                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1098                         continue;
1099
1100                 /* Ensure immediate parents are already suspended */
1101                 if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
1102                         continue;
1103
1104                 if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
1105                     !info.exists || info.suspended)
1106                         continue;
1107
1108                 if (!_suspend_node(name, info.major, info.minor,
1109                                    child->dtree->skip_lockfs,
1110                                    child->dtree->no_flush, &newinfo)) {
1111                         log_error("Unable to suspend %s (%" PRIu32
1112                                   ":%" PRIu32 ")", name, info.major,
1113                                   info.minor);
1114                         continue;
1115                 }
1116
1117                 /* Update cached info */
1118                 child->info = newinfo;
1119         }
1120
1121         /* Then suspend any child nodes */
1122         handle = NULL;
1123
1124         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1125                 if (!(uuid = dm_tree_node_get_uuid(child))) {
1126                         stack;
1127                         continue;
1128                 }
1129
1130                 /* Ignore if it doesn't belong to this VG */
1131                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1132                         continue;
1133
1134                 if (dm_tree_node_num_children(child, 0))
1135                         dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len);
1136         }
1137
1138         return 1;
1139 }
1140
1141 int dm_tree_activate_children(struct dm_tree_node *dnode,
1142                                  const char *uuid_prefix,
1143                                  size_t uuid_prefix_len)
1144 {
1145         void *handle = NULL;
1146         struct dm_tree_node *child = dnode;
1147         struct dm_info newinfo;
1148         const char *name;
1149         const char *uuid;
1150         int priority;
1151
1152         /* Activate children first */
1153         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1154                 if (!(uuid = dm_tree_node_get_uuid(child))) {
1155                         stack;
1156                         continue;
1157                 }
1158
1159                 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1160                         continue;
1161
1162                 if (dm_tree_node_num_children(child, 0))
1163                         dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len);
1164         }
1165
1166         handle = NULL;
1167
1168         for (priority = 0; priority < 2; priority++) {
1169                 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1170                         if (!(uuid = dm_tree_node_get_uuid(child))) {
1171                                 stack;
1172                                 continue;
1173                         }
1174
1175                         if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1176                                 continue;
1177
1178                         if (priority != child->activation_priority)
1179                                 continue;
1180
1181                         if (!(name = dm_tree_node_get_name(child))) {
1182                                 stack;
1183                                 continue;
1184                         }
1185
1186                         /* Rename? */
1187                         if (child->props.new_name) {
1188                                 if (!_rename_node(name, child->props.new_name, child->info.major,
1189                                                   child->info.minor, &child->dtree->cookie,
1190                                                   child->udev_flags)) {
1191                                         log_error("Failed to rename %s (%" PRIu32
1192                                                   ":%" PRIu32 ") to %s", name, child->info.major,
1193                                                   child->info.minor, child->props.new_name);
1194                                         return 0;
1195                                 }
1196                                 child->name = child->props.new_name;
1197                                 child->props.new_name = NULL;
1198                         }
1199
1200                         if (!child->info.inactive_table && !child->info.suspended)
1201                                 continue;
1202
1203                         if (!_resume_node(child->name, child->info.major, child->info.minor,
1204                                           child->props.read_ahead, child->props.read_ahead_flags,
1205                                           &newinfo, &child->dtree->cookie, child->udev_flags)) {
1206                                 log_error("Unable to resume %s (%" PRIu32
1207                                           ":%" PRIu32 ")", child->name, child->info.major,
1208                                           child->info.minor);
1209                                 continue;
1210                         }
1211
1212                         /* Update cached info */
1213                         child->info = newinfo;
1214                 }
1215         }
1216
1217         handle = NULL;
1218
1219         return 1;
1220 }
1221
1222 static int _create_node(struct dm_tree_node *dnode)
1223 {
1224         int r = 0;
1225         struct dm_task *dmt;
1226
1227         log_verbose("Creating %s", dnode->name);
1228
1229         if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {
1230                 log_error("Create dm_task creation failed for %s", dnode->name);
1231                 return 0;
1232         }
1233
1234         if (!dm_task_set_name(dmt, dnode->name)) {
1235                 log_error("Failed to set device name for %s", dnode->name);
1236                 goto out;
1237         }
1238
1239         if (!dm_task_set_uuid(dmt, dnode->uuid)) {
1240                 log_error("Failed to set uuid for %s", dnode->name);
1241                 goto out;
1242         }
1243
1244         if (dnode->props.major &&
1245             (!dm_task_set_major(dmt, dnode->props.major) ||
1246              !dm_task_set_minor(dmt, dnode->props.minor))) {
1247                 log_error("Failed to set device number for %s creation.", dnode->name);
1248                 goto out;
1249         }
1250
1251         if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1252                 log_error("Failed to set read only flag for %s", dnode->name);
1253                 goto out;
1254         }
1255
1256         if (!dm_task_no_open_count(dmt))
1257                 log_error("Failed to disable open_count");
1258
1259         if ((r = dm_task_run(dmt)))
1260                 r = dm_task_get_info(dmt, &dnode->info);
1261
1262 out:
1263         dm_task_destroy(dmt);
1264
1265         return r;
1266 }
1267
1268
1269 static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
1270 {
1271         if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
1272                 log_error("Failed to format %s device number for %s as dm "
1273                           "target (%u,%u)",
1274                           node->name, node->uuid, node->info.major, node->info.minor);
1275                 return 0;
1276         }
1277
1278         return 1;
1279 }
1280
1281 /* simplify string emiting code */
1282 #define EMIT_PARAMS(p, str...)\
1283 do {\
1284         int w;\
1285         if ((w = dm_snprintf(params + p, paramsize - (size_t) p, str)) < 0) {\
1286                 stack; /* Out of space */\
1287                 return -1;\
1288         }\
1289         p += w;\
1290 } while (0)
1291
1292 /*
1293  * _emit_areas_line
1294  *
1295  * Returns: 1 on success, 0 on failure
1296  */
1297 static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
1298                             struct load_segment *seg, char *params,
1299                             size_t paramsize, int *pos)
1300 {
1301         struct seg_area *area;
1302         char devbuf[DM_FORMAT_DEV_BUFSIZE];
1303         unsigned first_time = 1;
1304
1305         dm_list_iterate_items(area, &seg->areas) {
1306                 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1307                         return_0;
1308
1309                 EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
1310                             devbuf, area->offset);
1311
1312                 first_time = 0;
1313         }
1314
1315         return 1;
1316 }
1317
1318 /*
1319  * Returns: 1 on success, 0 on failure
1320  */
1321 static int _mirror_emit_segment_line(struct dm_task *dmt, uint32_t major,
1322                                      uint32_t minor, struct load_segment *seg,
1323                                      uint64_t *seg_start, char *params,
1324                                      size_t paramsize)
1325 {
1326         int r;
1327         int block_on_error = 0;
1328         int handle_errors = 0;
1329         int dm_log_userspace = 0;
1330         struct utsname uts;
1331         unsigned log_parm_count;
1332         int pos = 0;
1333         char logbuf[DM_FORMAT_DEV_BUFSIZE];
1334         const char *logtype;
1335
1336         r = uname(&uts);
1337         if (r)
1338                 return_0;
1339
1340         if ((seg->flags & DM_BLOCK_ON_ERROR)) {
1341                 /*
1342                  * Originally, block_on_error was an argument to the log
1343                  * portion of the mirror CTR table.  It was renamed to
1344                  * "handle_errors" and now resides in the 'features'
1345                  * section of the mirror CTR table (i.e. at the end).
1346                  *
1347                  * We can identify whether to use "block_on_error" or
1348                  * "handle_errors" by the dm-mirror module's version
1349                  * number (>= 1.12) or by the kernel version (>= 2.6.22).
1350                  */
1351                 if (strncmp(uts.release, "2.6.22", 6) >= 0)
1352                         handle_errors = 1;
1353                 else
1354                         block_on_error = 1;
1355         }
1356
1357         if (seg->clustered) {
1358                 /* Cluster mirrors require a UUID */
1359                 if (!seg->uuid)
1360                         return_0;
1361
1362                 /*
1363                  * Cluster mirrors used to have their own log
1364                  * types.  Now they are accessed through the
1365                  * userspace log type.
1366                  *
1367                  * The dm-log-userspace module was added to the
1368                  * 2.6.31 kernel.
1369                  */
1370                 if (strncmp(uts.release, "2.6.31", 6) >= 0)
1371                         dm_log_userspace = 1;
1372         }
1373
1374         /* Region size */
1375         log_parm_count = 1;
1376
1377         /* [no]sync, block_on_error etc. */
1378         log_parm_count += hweight32(seg->flags);
1379
1380         /* "handle_errors" is a feature arg now */
1381         if (handle_errors)
1382                 log_parm_count--;
1383
1384         /* DM_CORELOG does not count in the param list */
1385         if (seg->flags & DM_CORELOG)
1386                 log_parm_count--;
1387
1388         if (seg->clustered) {
1389                 log_parm_count++; /* For UUID */
1390
1391                 if (!dm_log_userspace)
1392                         EMIT_PARAMS(pos, "clustered-");
1393         }
1394
1395         if (!seg->log)
1396                 logtype = "core";
1397         else {
1398                 logtype = "disk";
1399                 log_parm_count++;
1400                 if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
1401                         return_0;
1402         }
1403
1404         if (dm_log_userspace)
1405                 EMIT_PARAMS(pos, "userspace %u %s clustered-%s",
1406                             log_parm_count, seg->uuid, logtype);
1407         else
1408                 EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count);
1409
1410         if (seg->log)
1411                 EMIT_PARAMS(pos, " %s", logbuf);
1412
1413         EMIT_PARAMS(pos, " %u", seg->region_size);
1414
1415         if (seg->clustered && !dm_log_userspace)
1416                 EMIT_PARAMS(pos, " %s", seg->uuid);
1417
1418         if ((seg->flags & DM_NOSYNC))
1419                 EMIT_PARAMS(pos, " nosync");
1420         else if ((seg->flags & DM_FORCESYNC))
1421                 EMIT_PARAMS(pos, " sync");
1422
1423         if (block_on_error)
1424                 EMIT_PARAMS(pos, " block_on_error");
1425
1426         EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
1427
1428         if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0)
1429                 return_0;
1430
1431         if (handle_errors)
1432                 EMIT_PARAMS(pos, " 1 handle_errors");
1433
1434         return 1;
1435 }
1436
1437 static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
1438                               uint32_t minor, struct load_segment *seg,
1439                               uint64_t *seg_start, char *params,
1440                               size_t paramsize)
1441 {
1442         int pos = 0;
1443         int r;
1444         char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
1445
1446         switch(seg->type) {
1447         case SEG_ERROR:
1448         case SEG_ZERO:
1449         case SEG_LINEAR:
1450                 break;
1451         case SEG_MIRRORED:
1452                 /* Mirrors are pretty complicated - now in separate function */
1453                 r = _mirror_emit_segment_line(dmt, major, minor, seg, seg_start,
1454                                               params, paramsize);
1455                 if (!r)
1456                         return_0;
1457                 break;
1458         case SEG_SNAPSHOT:
1459                 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1460                         return_0;
1461                 if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
1462                         return_0;
1463                 EMIT_PARAMS(pos, "%s %s %c %d", originbuf, cowbuf,
1464                             seg->persistent ? 'P' : 'N', seg->chunk_size);
1465                 break;
1466         case SEG_SNAPSHOT_ORIGIN:
1467                 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1468                         return_0;
1469                 EMIT_PARAMS(pos, "%s", originbuf);
1470                 break;
1471         case SEG_STRIPED:
1472                 EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
1473                 break;
1474         case SEG_CRYPT:
1475                 EMIT_PARAMS(pos, "%s%s%s%s%s %s %" PRIu64 " ", seg->cipher,
1476                             seg->chainmode ? "-" : "", seg->chainmode ?: "",
1477                             seg->iv ? "-" : "", seg->iv ?: "", seg->key,
1478                             seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
1479                             seg->iv_offset : *seg_start);
1480                 break;
1481         }
1482
1483         switch(seg->type) {
1484         case SEG_ERROR:
1485         case SEG_SNAPSHOT:
1486         case SEG_SNAPSHOT_ORIGIN:
1487         case SEG_ZERO:
1488                 break;
1489         case SEG_CRYPT:
1490         case SEG_LINEAR:
1491         case SEG_STRIPED:
1492                 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
1493                         stack;
1494                         return r;
1495                 }
1496                 break;
1497         }
1498
1499         log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64
1500                   " %" PRIu64 " %s %s", major, minor,
1501                   *seg_start, seg->size, dm_segtypes[seg->type].target, params);
1502
1503         if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))
1504                 return_0;
1505
1506         *seg_start += seg->size;
1507
1508         return 1;
1509 }
1510
1511 #undef EMIT_PARAMS
1512
1513 static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
1514                          struct load_segment *seg, uint64_t *seg_start)
1515 {
1516         char *params;
1517         size_t paramsize = 4096;
1518         int ret;
1519
1520         do {
1521                 if (!(params = dm_malloc(paramsize))) {
1522                         log_error("Insufficient space for target parameters.");
1523                         return 0;
1524                 }
1525
1526                 params[0] = '\0';
1527                 ret = _emit_segment_line(dmt, major, minor, seg, seg_start,
1528                                          params, paramsize);
1529                 dm_free(params);
1530
1531                 if (!ret)
1532                         stack;
1533
1534                 if (ret >= 0)
1535                         return ret;
1536
1537                 log_debug("Insufficient space in params[%" PRIsize_t
1538                           "] for target parameters.", paramsize);
1539
1540                 paramsize *= 2;
1541         } while (paramsize < MAX_TARGET_PARAMSIZE);
1542
1543         log_error("Target parameter size too big. Aborting.");
1544         return 0;
1545 }
1546
1547 static int _load_node(struct dm_tree_node *dnode)
1548 {
1549         int r = 0;
1550         struct dm_task *dmt;
1551         struct load_segment *seg;
1552         uint64_t seg_start = 0;
1553
1554         log_verbose("Loading %s table (%" PRIu32 ":%" PRIu32 ")", dnode->name,
1555                     dnode->info.major, dnode->info.minor);
1556
1557         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
1558                 log_error("Reload dm_task creation failed for %s", dnode->name);
1559                 return 0;
1560         }
1561
1562         if (!dm_task_set_major(dmt, dnode->info.major) ||
1563             !dm_task_set_minor(dmt, dnode->info.minor)) {
1564                 log_error("Failed to set device number for %s reload.", dnode->name);
1565                 goto out;
1566         }
1567
1568         if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1569                 log_error("Failed to set read only flag for %s", dnode->name);
1570                 goto out;
1571         }
1572
1573         if (!dm_task_no_open_count(dmt))
1574                 log_error("Failed to disable open_count");
1575
1576         dm_list_iterate_items(seg, &dnode->props.segs)
1577                 if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor,
1578                                    seg, &seg_start))
1579                         goto_out;
1580
1581         if (!dm_task_suppress_identical_reload(dmt))
1582                 log_error("Failed to suppress reload of identical tables.");
1583
1584         if ((r = dm_task_run(dmt))) {
1585                 r = dm_task_get_info(dmt, &dnode->info);
1586                 if (r && !dnode->info.inactive_table)
1587                         log_verbose("Suppressed %s identical table reload.",
1588                                     dnode->name);
1589
1590                 if ((dnode->props.size_changed =
1591                      (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
1592                         log_debug("Table size changed from %" PRIu64 " to %"
1593                                   PRIu64 " for %s",
1594                                   dm_task_get_existing_table_size(dmt),
1595                                   seg_start, dnode->name);
1596         }
1597
1598         dnode->props.segment_count = 0;
1599
1600 out:
1601         dm_task_destroy(dmt);
1602
1603         return r;
1604 }
1605
1606 int dm_tree_preload_children(struct dm_tree_node *dnode,
1607                              const char *uuid_prefix,
1608                              size_t uuid_prefix_len)
1609 {
1610         void *handle = NULL;
1611         struct dm_tree_node *child;
1612         struct dm_info newinfo;
1613
1614         /* Preload children first */
1615         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1616                 /* Skip existing non-device-mapper devices */
1617                 if (!child->info.exists && child->info.major)
1618                         continue;
1619
1620                 /* Ignore if it doesn't belong to this VG */
1621                 if (child->info.exists &&
1622                     !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
1623                         continue;
1624
1625                 if (dm_tree_node_num_children(child, 0))
1626                         dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len);
1627
1628                 /* FIXME Cope if name exists with no uuid? */
1629                 if (!child->info.exists) {
1630                         if (!_create_node(child)) {
1631                                 stack;
1632                                 return 0;
1633                         }
1634                 }
1635
1636                 if (!child->info.inactive_table && child->props.segment_count) {
1637                         if (!_load_node(child)) {
1638                                 stack;
1639                                 return 0;
1640                         }
1641                 }
1642
1643                 /* Propagate device size change change */
1644                 if (child->props.size_changed)
1645                         dnode->props.size_changed = 1;
1646
1647                 /* Resume device immediately if it has parents and its size changed */
1648                 if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
1649                         continue;
1650
1651                 if (!child->info.inactive_table && !child->info.suspended)
1652                         continue;
1653
1654                 if (!_resume_node(child->name, child->info.major, child->info.minor,
1655                                   child->props.read_ahead, child->props.read_ahead_flags,
1656                                   &newinfo, &child->dtree->cookie, child->udev_flags)) {
1657                         log_error("Unable to resume %s (%" PRIu32
1658                                   ":%" PRIu32 ")", child->name, child->info.major,
1659                                   child->info.minor);
1660                         continue;
1661                 }
1662
1663                 /* Update cached info */
1664                 child->info = newinfo;
1665         }
1666
1667         handle = NULL;
1668
1669         return 1;
1670 }
1671
1672 /*
1673  * Returns 1 if unsure.
1674  */
1675 int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
1676                                  const char *uuid_prefix,
1677                                  size_t uuid_prefix_len)
1678 {
1679         void *handle = NULL;
1680         struct dm_tree_node *child = dnode;
1681         const char *uuid;
1682
1683         while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1684                 if (!(uuid = dm_tree_node_get_uuid(child))) {
1685                         log_error("Failed to get uuid for dtree node.");
1686                         return 1;
1687                 }
1688
1689                 if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1690                         return 1;
1691
1692                 if (dm_tree_node_num_children(child, 0))
1693                         dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
1694         }
1695
1696         return 0;
1697 }
1698
1699 /*
1700  * Target functions
1701  */
1702 static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
1703 {
1704         struct load_segment *seg;
1705
1706         if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
1707                 log_error("dtree node segment allocation failed");
1708                 return NULL;
1709         }
1710
1711         seg->type = type;
1712         seg->size = size;
1713         seg->area_count = 0;
1714         dm_list_init(&seg->areas);
1715         seg->stripe_size = 0;
1716         seg->persistent = 0;
1717         seg->chunk_size = 0;
1718         seg->cow = NULL;
1719         seg->origin = NULL;
1720
1721         dm_list_add(&dnode->props.segs, &seg->list);
1722         dnode->props.segment_count++;
1723
1724         return seg;
1725 }
1726
1727 int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
1728                                                uint64_t size,
1729                                                const char *origin_uuid)
1730 {
1731         struct load_segment *seg;
1732         struct dm_tree_node *origin_node;
1733
1734         if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
1735                 return_0;
1736
1737         if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
1738                 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
1739                 return 0;
1740         }
1741
1742         seg->origin = origin_node;
1743         if (!_link_tree_nodes(dnode, origin_node))
1744                 return_0;
1745
1746         /* Resume snapshot origins after new snapshots */
1747         dnode->activation_priority = 1;
1748
1749         return 1;
1750 }
1751
1752 int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
1753                                         uint64_t size,
1754                                         const char *origin_uuid,
1755                                         const char *cow_uuid,
1756                                         int persistent,
1757                                         uint32_t chunk_size)
1758 {
1759         struct load_segment *seg;
1760         struct dm_tree_node *origin_node, *cow_node;
1761
1762         if (!(seg = _add_segment(node, SEG_SNAPSHOT, size)))
1763                 return_0;
1764
1765         if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
1766                 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
1767                 return 0;
1768         }
1769
1770         seg->origin = origin_node;
1771         if (!_link_tree_nodes(node, origin_node))
1772                 return_0;
1773
1774         if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
1775                 log_error("Couldn't find snapshot origin uuid %s.", cow_uuid);
1776                 return 0;
1777         }
1778
1779         seg->cow = cow_node;
1780         if (!_link_tree_nodes(node, cow_node))
1781                 return_0;
1782
1783         seg->persistent = persistent ? 1 : 0;
1784         seg->chunk_size = chunk_size;
1785
1786         return 1;
1787 }
1788
1789 int dm_tree_node_add_error_target(struct dm_tree_node *node,
1790                                      uint64_t size)
1791 {
1792         if (!_add_segment(node, SEG_ERROR, size))
1793                 return_0;
1794
1795         return 1;
1796 }
1797
1798 int dm_tree_node_add_zero_target(struct dm_tree_node *node,
1799                                     uint64_t size)
1800 {
1801         if (!_add_segment(node, SEG_ZERO, size))
1802                 return_0;
1803
1804         return 1;
1805 }
1806
1807 int dm_tree_node_add_linear_target(struct dm_tree_node *node,
1808                                       uint64_t size)
1809 {
1810         if (!_add_segment(node, SEG_LINEAR, size))
1811                 return_0;
1812
1813         return 1;
1814 }
1815
1816 int dm_tree_node_add_striped_target(struct dm_tree_node *node,
1817                                        uint64_t size,
1818                                        uint32_t stripe_size)
1819 {
1820         struct load_segment *seg;
1821
1822         if (!(seg = _add_segment(node, SEG_STRIPED, size)))
1823                 return_0;
1824
1825         seg->stripe_size = stripe_size;
1826
1827         return 1;
1828 }
1829
1830 int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
1831                                   uint64_t size,
1832                                   const char *cipher,
1833                                   const char *chainmode,
1834                                   const char *iv,
1835                                   uint64_t iv_offset,
1836                                   const char *key)
1837 {
1838         struct load_segment *seg;
1839
1840         if (!(seg = _add_segment(node, SEG_CRYPT, size)))
1841                 return_0;
1842
1843         seg->cipher = cipher;
1844         seg->chainmode = chainmode;
1845         seg->iv = iv;
1846         seg->iv_offset = iv_offset;
1847         seg->key = key;
1848
1849         return 1;
1850 }
1851
1852 int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
1853                                           uint32_t region_size,
1854                                           unsigned clustered, 
1855                                           const char *log_uuid,
1856                                           unsigned area_count,
1857                                           uint32_t flags)
1858 {
1859         struct dm_tree_node *log_node = NULL;
1860         struct load_segment *seg;
1861
1862         if (!node->props.segment_count) {
1863                 log_error("Internal error: Attempt to add target area to missing segment.");
1864                 return 0;
1865         }
1866
1867         seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
1868
1869         if (log_uuid) {
1870                 if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
1871                         log_error("log uuid pool_strdup failed");
1872                         return 0;
1873                 }
1874                 if (!(flags & DM_CORELOG)) {
1875                         if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
1876                                 log_error("Couldn't find mirror log uuid %s.", log_uuid);
1877                                 return 0;
1878                         }
1879
1880                         if (!_link_tree_nodes(node, log_node))
1881                                 return_0;
1882                 }
1883         }
1884
1885         seg->log = log_node;
1886         seg->region_size = region_size;
1887         seg->clustered = clustered;
1888         seg->mirror_area_count = area_count;
1889         seg->flags = flags;
1890
1891         return 1;
1892 }
1893
1894 int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
1895                                       uint64_t size)
1896 {
1897         struct load_segment *seg;
1898
1899         if (!(seg = _add_segment(node, SEG_MIRRORED, size)))
1900                 return_0;
1901
1902         return 1;
1903 }
1904
1905 static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
1906 {
1907         struct seg_area *area;
1908
1909         if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
1910                 log_error("Failed to allocate target segment area.");
1911                 return 0;
1912         }
1913
1914         area->dev_node = dev_node;
1915         area->offset = offset;
1916
1917         dm_list_add(&seg->areas, &area->list);
1918         seg->area_count++;
1919
1920         return 1;
1921 }
1922
1923 int dm_tree_node_add_target_area(struct dm_tree_node *node,
1924                                     const char *dev_name,
1925                                     const char *uuid,
1926                                     uint64_t offset)
1927 {
1928         struct load_segment *seg;
1929         struct stat info;
1930         struct dm_tree_node *dev_node;
1931
1932         if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
1933                 log_error("dm_tree_node_add_target_area called without device");
1934                 return 0;
1935         }
1936
1937         if (uuid) {
1938                 if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
1939                         log_error("Couldn't find area uuid %s.", uuid);
1940                         return 0;
1941                 }
1942                 if (!_link_tree_nodes(node, dev_node))
1943                         return_0;
1944         } else {
1945                 if (stat(dev_name, &info) < 0) {
1946                         log_error("Device %s not found.", dev_name);
1947                         return 0;
1948                 }
1949 #ifndef __NetBSD__
1950                 if (!S_ISBLK(info.st_mode)) {
1951                         log_error("Device %s is not a block device.", dev_name);
1952                         return 0;
1953                 }
1954 #else
1955                 if (S_ISBLK(info.st_mode)) {
1956                         log_error("Device %s is a block device. Use raw devices on NetBSD.", dev_name);
1957                         return 0;
1958                 }
1959 #endif          
1960                 /* FIXME Check correct macro use */
1961                 if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), MINOR(info.st_rdev))))
1962                         return_0;
1963         }
1964
1965         if (!node->props.segment_count) {
1966                 log_error("Internal error: Attempt to add target area to missing segment.");
1967                 return 0;
1968         }
1969
1970         seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
1971
1972         if (!_add_area(node, seg, dev_node, offset))
1973                 return_0;
1974
1975         return 1;
1976 }
1977
1978 void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie)
1979 {
1980         node->dtree->cookie = cookie;
1981 }
1982
1983 uint32_t dm_tree_get_cookie(struct dm_tree_node *node)
1984 {
1985         return node->dtree->cookie;
1986 }