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