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