]> sourceware.org Git - lvm2.git/blame - libdm/libdm-deptree.c
Fix memory leak in error path
[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,
45};
b4f1578f 46
165e4a11
AK
47/* FIXME Add crypt and multipath support */
48
49struct {
50 unsigned type;
51 const char *target;
52} dm_segtypes[] = {
12ca060e 53 { SEG_CRYPT, "crypt" },
165e4a11
AK
54 { SEG_ERROR, "error" },
55 { SEG_LINEAR, "linear" },
56 { SEG_MIRRORED, "mirror" },
b262f3e1
ZK
57 { SEG_REPLICATOR, "replicator" },
58 { SEG_REPLICATOR_DEV, "replicator-dev" },
165e4a11
AK
59 { SEG_SNAPSHOT, "snapshot" },
60 { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
aa6f4e51 61 { SEG_SNAPSHOT_MERGE, "snapshot-merge" },
165e4a11
AK
62 { SEG_STRIPED, "striped" },
63 { SEG_ZERO, "zero"},
64};
65
66/* Some segment types have a list of areas of other devices attached */
67struct seg_area {
2c44337b 68 struct dm_list list;
165e4a11 69
b4f1578f 70 struct dm_tree_node *dev_node;
165e4a11
AK
71
72 uint64_t offset;
b262f3e1
ZK
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? */
82struct 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;
165e4a11
AK
90};
91
92/* Per-segment properties */
93struct load_segment {
2c44337b 94 struct dm_list list;
165e4a11
AK
95
96 unsigned type;
97
98 uint64_t size;
99
b262f3e1
ZK
100 unsigned area_count; /* Linear + Striped + Mirrored + Crypt + Replicator */
101 struct dm_list areas; /* Linear + Striped + Mirrored + Crypt + Replicator */
165e4a11
AK
102
103 uint32_t stripe_size; /* Striped */
104
105 int persistent; /* Snapshot */
106 uint32_t chunk_size; /* Snapshot */
b4f1578f
AK
107 struct dm_tree_node *cow; /* Snapshot */
108 struct dm_tree_node *origin; /* Snapshot + Snapshot origin */
aa6f4e51 109 struct dm_tree_node *merge; /* Snapshot */
165e4a11 110
b262f3e1 111 struct dm_tree_node *log; /* Mirror + Replicator */
165e4a11
AK
112 uint32_t region_size; /* Mirror */
113 unsigned clustered; /* Mirror */
114 unsigned mirror_area_count; /* Mirror */
dbcb64b8 115 uint32_t flags; /* Mirror log */
67b25ed4 116 char *uuid; /* Clustered mirror log */
12ca060e
MB
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 */
b262f3e1
ZK
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 */
165e4a11
AK
130};
131
132/* Per-device properties */
133struct load_properties {
134 int read_only;
135 uint32_t major;
136 uint32_t minor;
137
52b84409
AK
138 uint32_t read_ahead;
139 uint32_t read_ahead_flags;
140
165e4a11 141 unsigned segment_count;
bb875bb9 142 unsigned size_changed;
2c44337b 143 struct dm_list segs;
165e4a11
AK
144
145 const char *new_name;
566515c0
PR
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;
165e4a11
AK
153};
154
155/* Two of these used to join two nodes with uses and used_by. */
b4f1578f 156struct dm_tree_link {
2c44337b 157 struct dm_list list;
b4f1578f 158 struct dm_tree_node *node;
165e4a11
AK
159};
160
b4f1578f
AK
161struct dm_tree_node {
162 struct dm_tree *dtree;
3d0480ed
AK
163
164 const char *name;
165 const char *uuid;
166 struct dm_info info;
167
2c44337b
AK
168 struct dm_list uses; /* Nodes this node uses */
169 struct dm_list used_by; /* Nodes that use this node */
165e4a11 170
56c28292
AK
171 int activation_priority; /* 0 gets activated first */
172
f16aea9e
PR
173 uint16_t udev_flags; /* Udev control flags */
174
165e4a11
AK
175 void *context; /* External supplied context */
176
177 struct load_properties props; /* For creation/table (re)load */
76d1aec8
ZK
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;
3d0480ed
AK
184};
185
b4f1578f 186struct dm_tree {
a3f6b2ce
AK
187 struct dm_pool *mem;
188 struct dm_hash_table *devs;
165e4a11 189 struct dm_hash_table *uuids;
b4f1578f 190 struct dm_tree_node root;
c55b1410 191 int skip_lockfs; /* 1 skips lockfs (for non-snapshots) */
b9ffd32c 192 int no_flush; /* 1 sets noflush (mirrors/multipath) */
bd90c6b2 193 uint32_t cookie;
3d0480ed
AK
194};
195
b4f1578f 196struct dm_tree *dm_tree_create(void)
3d0480ed 197{
b4f1578f 198 struct dm_tree *dtree;
3d0480ed 199
ac0252ca 200 if (!(dtree = dm_zalloc(sizeof(*dtree)))) {
b4f1578f 201 log_error("dm_tree_create malloc failed");
3d0480ed
AK
202 return NULL;
203 }
204
b4f1578f 205 dtree->root.dtree = dtree;
2c44337b
AK
206 dm_list_init(&dtree->root.uses);
207 dm_list_init(&dtree->root.used_by);
c55b1410 208 dtree->skip_lockfs = 0;
b9ffd32c 209 dtree->no_flush = 0;
3d0480ed 210
b4f1578f
AK
211 if (!(dtree->mem = dm_pool_create("dtree", 1024))) {
212 log_error("dtree pool creation failed");
213 dm_free(dtree);
3d0480ed
AK
214 return NULL;
215 }
216
b4f1578f
AK
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);
3d0480ed
AK
221 return NULL;
222 }
223
b4f1578f
AK
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);
165e4a11
AK
229 return NULL;
230 }
231
b4f1578f 232 return dtree;
3d0480ed
AK
233}
234
b4f1578f 235void dm_tree_free(struct dm_tree *dtree)
3d0480ed 236{
b4f1578f 237 if (!dtree)
3d0480ed
AK
238 return;
239
b4f1578f
AK
240 dm_hash_destroy(dtree->uuids);
241 dm_hash_destroy(dtree->devs);
242 dm_pool_destroy(dtree->mem);
243 dm_free(dtree);
3d0480ed
AK
244}
245
04bde319
ZK
246static int _nodes_are_linked(const struct dm_tree_node *parent,
247 const struct dm_tree_node *child)
3d0480ed 248{
b4f1578f 249 struct dm_tree_link *dlink;
3d0480ed 250
2c44337b 251 dm_list_iterate_items(dlink, &parent->uses)
3d0480ed
AK
252 if (dlink->node == child)
253 return 1;
3d0480ed
AK
254
255 return 0;
256}
257
2c44337b 258static int _link(struct dm_list *list, struct dm_tree_node *node)
3d0480ed 259{
b4f1578f 260 struct dm_tree_link *dlink;
3d0480ed 261
b4f1578f
AK
262 if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
263 log_error("dtree link allocation failed");
3d0480ed
AK
264 return 0;
265 }
266
267 dlink->node = node;
2c44337b 268 dm_list_add(list, &dlink->list);
3d0480ed
AK
269
270 return 1;
271}
272
b4f1578f
AK
273static int _link_nodes(struct dm_tree_node *parent,
274 struct dm_tree_node *child)
3d0480ed
AK
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
2c44337b 288static void _unlink(struct dm_list *list, struct dm_tree_node *node)
3d0480ed 289{
b4f1578f 290 struct dm_tree_link *dlink;
3d0480ed 291
2c44337b 292 dm_list_iterate_items(dlink, list)
3d0480ed 293 if (dlink->node == node) {
2c44337b 294 dm_list_del(&dlink->list);
3d0480ed
AK
295 break;
296 }
3d0480ed
AK
297}
298
b4f1578f
AK
299static void _unlink_nodes(struct dm_tree_node *parent,
300 struct dm_tree_node *child)
3d0480ed
AK
301{
302 if (!_nodes_are_linked(parent, child))
303 return;
304
305 _unlink(&parent->uses, child);
306 _unlink(&child->used_by, parent);
307}
308
b4f1578f 309static int _add_to_toplevel(struct dm_tree_node *node)
165e4a11 310{
b4f1578f 311 return _link_nodes(&node->dtree->root, node);
165e4a11
AK
312}
313
b4f1578f 314static void _remove_from_toplevel(struct dm_tree_node *node)
3d0480ed 315{
b1ebf028 316 _unlink_nodes(&node->dtree->root, node);
3d0480ed
AK
317}
318
b4f1578f 319static int _add_to_bottomlevel(struct dm_tree_node *node)
3d0480ed 320{
b4f1578f 321 return _link_nodes(node, &node->dtree->root);
3d0480ed
AK
322}
323
b4f1578f 324static void _remove_from_bottomlevel(struct dm_tree_node *node)
165e4a11 325{
b1ebf028 326 _unlink_nodes(node, &node->dtree->root);
165e4a11
AK
327}
328
b4f1578f 329static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
165e4a11
AK
330{
331 /* Don't link to root node if child already has a parent */
b4f1578f
AK
332 if ((parent == &parent->dtree->root)) {
333 if (dm_tree_node_num_children(child, 1))
165e4a11
AK
334 return 1;
335 } else
336 _remove_from_toplevel(child);
337
b4f1578f
AK
338 if ((child == &child->dtree->root)) {
339 if (dm_tree_node_num_children(parent, 0))
165e4a11
AK
340 return 1;
341 } else
342 _remove_from_bottomlevel(parent);
343
344 return _link_nodes(parent, child);
345}
346
b4f1578f 347static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
3d0480ed
AK
348 const char *name,
349 const char *uuid,
165e4a11 350 struct dm_info *info,
f16aea9e
PR
351 void *context,
352 uint16_t udev_flags)
3d0480ed 353{
b4f1578f 354 struct dm_tree_node *node;
3d0480ed
AK
355 uint64_t dev;
356
b4f1578f
AK
357 if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
358 log_error("_create_dm_tree_node alloc failed");
3d0480ed
AK
359 return NULL;
360 }
361
b4f1578f 362 node->dtree = dtree;
3d0480ed
AK
363
364 node->name = name;
365 node->uuid = uuid;
366 node->info = *info;
165e4a11 367 node->context = context;
f16aea9e 368 node->udev_flags = udev_flags;
56c28292 369 node->activation_priority = 0;
3d0480ed 370
2c44337b
AK
371 dm_list_init(&node->uses);
372 dm_list_init(&node->used_by);
373 dm_list_init(&node->props.segs);
3d0480ed
AK
374
375 dev = MKDEV(info->major, info->minor);
376
b4f1578f 377 if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
3d0480ed 378 sizeof(dev), node)) {
b4f1578f
AK
379 log_error("dtree node hash insertion failed");
380 dm_pool_free(dtree->mem, node);
3d0480ed
AK
381 return NULL;
382 }
383
165e4a11 384 if (uuid && *uuid &&
b4f1578f
AK
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,
165e4a11 388 sizeof(dev));
b4f1578f 389 dm_pool_free(dtree->mem, node);
165e4a11
AK
390 return NULL;
391 }
392
3d0480ed
AK
393 return node;
394}
395
b4f1578f 396static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
3d0480ed
AK
397 uint32_t major, uint32_t minor)
398{
399 uint64_t dev = MKDEV(major, minor);
400
b4f1578f 401 return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
3d0480ed
AK
402 sizeof(dev));
403}
404
b4f1578f 405static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
165e4a11
AK
406 const char *uuid)
407{
87f98002
AK
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);
165e4a11
AK
417}
418
a3f6b2ce 419static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
3d0480ed
AK
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;
165e4a11
AK
432 info->live_table = 0;
433 info->inactive_table = 0;
434 info->read_only = 0;
3d0480ed
AK
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
b4f1578f
AK
443 if (!dm_task_set_major(*dmt, major)) {
444 log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
445 major, minor);
3d0480ed 446 goto failed;
b4f1578f 447 }
3d0480ed 448
b4f1578f
AK
449 if (!dm_task_set_minor(*dmt, minor)) {
450 log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
451 major, minor);
3d0480ed 452 goto failed;
b4f1578f 453 }
3d0480ed 454
b4f1578f
AK
455 if (!dm_task_run(*dmt)) {
456 log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
457 major, minor);
3d0480ed 458 goto failed;
b4f1578f 459 }
3d0480ed 460
b4f1578f
AK
461 if (!dm_task_get_info(*dmt, info)) {
462 log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
463 major, minor);
3d0480ed 464 goto failed;
b4f1578f 465 }
3d0480ed
AK
466
467 if (!info->exists) {
468 *name = "";
469 *uuid = "";
470 *deps = NULL;
471 } else {
472 if (info->major != major) {
b4f1578f 473 log_error("Inconsistent dtree major number: %u != %u",
3d0480ed
AK
474 major, info->major);
475 goto failed;
476 }
477 if (info->minor != minor) {
b4f1578f 478 log_error("Inconsistent dtree minor number: %u != %u",
3d0480ed
AK
479 minor, info->minor);
480 goto failed;
481 }
a3f6b2ce 482 if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
3d0480ed
AK
483 log_error("name pool_strdup failed");
484 goto failed;
485 }
a3f6b2ce 486 if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
3d0480ed
AK
487 log_error("uuid pool_strdup failed");
488 goto failed;
489 }
490 *deps = dm_task_get_deps(*dmt);
491 }
492
493 return 1;
494
495failed:
496 dm_task_destroy(*dmt);
497 return 0;
498}
499
b4f1578f
AK
500static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
501 struct dm_tree_node *parent,
cda69e17
PR
502 uint32_t major, uint32_t minor,
503 uint16_t udev_flags)
3d0480ed
AK
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;
b4f1578f 510 struct dm_tree_node *node = NULL;
3d0480ed 511 uint32_t i;
3d0480ed
AK
512 int new = 0;
513
514 /* Already in tree? */
b4f1578f
AK
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;
3d0480ed 518
f16aea9e 519 if (!(node = _create_dm_tree_node(dtree, name, uuid, &info,
cda69e17 520 NULL, udev_flags)))
b4f1578f 521 goto_out;
3d0480ed
AK
522 new = 1;
523 }
524
165e4a11
AK
525 if (!_link_tree_nodes(parent, node)) {
526 node = NULL;
b4f1578f 527 goto_out;
165e4a11 528 }
3d0480ed
AK
529
530 /* If node was already in tree, no need to recurse. */
531 if (!new)
165e4a11 532 goto out;
3d0480ed
AK
533
534 /* Can't recurse if not a mapped device or there are no dependencies */
535 if (!node->info.exists || !deps->count) {
b4f1578f
AK
536 if (!_add_to_bottomlevel(node)) {
537 stack;
165e4a11 538 node = NULL;
b4f1578f 539 }
165e4a11 540 goto out;
3d0480ed
AK
541 }
542
543 /* Add dependencies to tree */
544 for (i = 0; i < deps->count; i++)
b4f1578f 545 if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
cda69e17 546 MINOR(deps->device[i]), udev_flags)) {
165e4a11 547 node = NULL;
b4f1578f 548 goto_out;
165e4a11 549 }
3d0480ed 550
3d0480ed
AK
551out:
552 if (dmt)
553 dm_task_destroy(dmt);
554
165e4a11
AK
555 return node;
556}
557
b4f1578f 558static int _node_clear_table(struct dm_tree_node *dnode)
165e4a11
AK
559{
560 struct dm_task *dmt;
561 struct dm_info *info;
562 const char *name;
563 int r;
564
565 if (!(info = &dnode->info)) {
b4f1578f 566 log_error("_node_clear_table failed: missing info");
165e4a11
AK
567 return 0;
568 }
569
b4f1578f
AK
570 if (!(name = dm_tree_node_get_name(dnode))) {
571 log_error("_node_clear_table failed: missing name");
165e4a11
AK
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))) {
165e4a11
AK
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)) {
b4f1578f 597 log_error("_node_clear_table failed: info missing after running task for %s", name);
165e4a11
AK
598 r = 0;
599 }
600
601 dm_task_destroy(dmt);
602
3d0480ed
AK
603 return r;
604}
605
b4f1578f 606struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
165e4a11
AK
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{
b4f1578f 614 struct dm_tree_node *dnode;
165e4a11
AK
615 struct dm_info info;
616 const char *name2;
617 const char *uuid2;
618
619 /* Do we need to add node to tree? */
b4f1578f
AK
620 if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
621 if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
165e4a11
AK
622 log_error("name pool_strdup failed");
623 return NULL;
624 }
b4f1578f 625 if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
165e4a11
AK
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
f16aea9e
PR
637 if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2, &info,
638 context, 0)))
b4f1578f 639 return_NULL;
165e4a11
AK
640
641 /* Attach to root node until a table is supplied */
b4f1578f
AK
642 if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
643 return_NULL;
165e4a11
AK
644
645 dnode->props.major = major;
646 dnode->props.minor = minor;
647 dnode->props.new_name = NULL;
bb875bb9 648 dnode->props.size_changed = 0;
165e4a11
AK
649 } else if (strcmp(name, dnode->name)) {
650 /* Do we need to rename node? */
b4f1578f 651 if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
165e4a11
AK
652 log_error("name pool_strdup failed");
653 return 0;
654 }
655 }
656
657 dnode->props.read_only = read_only ? 1 : 0;
52b84409
AK
658 dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
659 dnode->props.read_ahead_flags = 0;
165e4a11 660
b4f1578f
AK
661 if (clear_inactive && !_node_clear_table(dnode))
662 return_NULL;
165e4a11
AK
663
664 dnode->context = context;
f16aea9e 665 dnode->udev_flags = 0;
165e4a11
AK
666
667 return dnode;
668}
669
f16aea9e
PR
670struct 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
52b84409
AK
690void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
691 uint32_t read_ahead,
692 uint32_t read_ahead_flags)
08e64ce5 693{
52b84409
AK
694 dnode->props.read_ahead = read_ahead;
695 dnode->props.read_ahead_flags = read_ahead_flags;
696}
697
76d1aec8
ZK
698void 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
b4f1578f 704int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
3d0480ed 705{
cda69e17
PR
706 return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0;
707}
708
709int 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;
3d0480ed
AK
713}
714
04bde319 715const char *dm_tree_node_get_name(const struct dm_tree_node *node)
3d0480ed
AK
716{
717 return node->info.exists ? node->name : "";
718}
719
04bde319 720const char *dm_tree_node_get_uuid(const struct dm_tree_node *node)
3d0480ed
AK
721{
722 return node->info.exists ? node->uuid : "";
723}
724
04bde319 725const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node)
3d0480ed
AK
726{
727 return &node->info;
728}
729
04bde319 730void *dm_tree_node_get_context(const struct dm_tree_node *node)
165e4a11
AK
731{
732 return node->context;
733}
734
04bde319 735int dm_tree_node_size_changed(const struct dm_tree_node *dnode)
eb91c4ee
MB
736{
737 return dnode->props.size_changed;
738}
739
04bde319 740int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted)
3d0480ed
AK
741{
742 if (inverted) {
b4f1578f 743 if (_nodes_are_linked(&node->dtree->root, node))
3d0480ed 744 return 0;
2c44337b 745 return dm_list_size(&node->used_by);
3d0480ed
AK
746 }
747
b4f1578f 748 if (_nodes_are_linked(node, &node->dtree->root))
3d0480ed
AK
749 return 0;
750
2c44337b 751 return dm_list_size(&node->uses);
3d0480ed
AK
752}
753
2b69db1f
AK
754/*
755 * Returns 1 if no prefix supplied
756 */
757static 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
87f98002 769 if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
872dea04
AK
770 return 0;
771
87f98002 772 if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
2b69db1f
AK
773 return 0;
774
87f98002 775 if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
2b69db1f
AK
776 return 1;
777
778 return 0;
779}
780
690a5da2
AK
781/*
782 * Returns 1 if no children.
783 */
b4f1578f 784static int _children_suspended(struct dm_tree_node *node,
690a5da2
AK
785 uint32_t inverted,
786 const char *uuid_prefix,
787 size_t uuid_prefix_len)
788{
2c44337b 789 struct dm_list *list;
b4f1578f 790 struct dm_tree_link *dlink;
690a5da2
AK
791 const struct dm_info *dinfo;
792 const char *uuid;
793
794 if (inverted) {
b4f1578f 795 if (_nodes_are_linked(&node->dtree->root, node))
690a5da2
AK
796 return 1;
797 list = &node->used_by;
798 } else {
b4f1578f 799 if (_nodes_are_linked(node, &node->dtree->root))
690a5da2
AK
800 return 1;
801 list = &node->uses;
802 }
803
2c44337b 804 dm_list_iterate_items(dlink, list) {
b4f1578f 805 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
690a5da2
AK
806 stack;
807 continue;
808 }
809
810 /* Ignore if it doesn't belong to this VG */
2b69db1f 811 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
690a5da2
AK
812 continue;
813
76d1aec8
ZK
814 /* Ignore if parent node wants to presuspend this node */
815 if (dlink->node->presuspend_node == node)
816 continue;
817
b4f1578f
AK
818 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
819 stack; /* FIXME Is this normal? */
690a5da2
AK
820 return 0;
821 }
822
823 if (!dinfo->suspended)
824 return 0;
825 }
826
827 return 1;
828}
829
3d0480ed
AK
830/*
831 * Set major and minor to zero for root of tree.
832 */
b4f1578f 833struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
3d0480ed
AK
834 uint32_t major,
835 uint32_t minor)
836{
837 if (!major && !minor)
b4f1578f 838 return &dtree->root;
3d0480ed 839
b4f1578f 840 return _find_dm_tree_node(dtree, major, minor);
3d0480ed
AK
841}
842
165e4a11
AK
843/*
844 * Set uuid to NULL for root of tree.
845 */
b4f1578f 846struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
165e4a11
AK
847 const char *uuid)
848{
849 if (!uuid || !*uuid)
b4f1578f 850 return &dtree->root;
165e4a11 851
b4f1578f 852 return _find_dm_tree_node_by_uuid(dtree, uuid);
165e4a11
AK
853}
854
3d0480ed
AK
855/*
856 * First time set *handle to NULL.
857 * Set inverted to invert the tree.
858 */
b4f1578f 859struct dm_tree_node *dm_tree_next_child(void **handle,
04bde319
ZK
860 const struct dm_tree_node *parent,
861 uint32_t inverted)
3d0480ed 862{
2c44337b 863 struct dm_list **dlink = (struct dm_list **) handle;
04bde319 864 const struct dm_list *use_list;
3d0480ed
AK
865
866 if (inverted)
867 use_list = &parent->used_by;
868 else
869 use_list = &parent->uses;
870
871 if (!*dlink)
2c44337b 872 *dlink = dm_list_first(use_list);
3d0480ed 873 else
2c44337b 874 *dlink = dm_list_next(use_list, *dlink);
3d0480ed 875
2c44337b 876 return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
3d0480ed
AK
877}
878
3e8c6b73 879/*
a6d97ede 880 * Deactivate a device with its dependencies if the uuid prefix matches.
3e8c6b73 881 */
db208f51
AK
882static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
883 struct dm_info *info)
3e8c6b73
AK
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
db208f51
AK
899 if (!with_open_count && !dm_task_no_open_count(dmt))
900 log_error("Failed to disable open_count");
901
3e8c6b73
AK
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
f3ef15ef
ZK
910/* Check if all parent nodes of given node have open_count == 0 */
911static 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
f16aea9e
PR
948static int _deactivate_node(const char *name, uint32_t major, uint32_t minor,
949 uint32_t *cookie, uint16_t udev_flags)
3e8c6b73
AK
950{
951 struct dm_task *dmt;
bd90c6b2 952 int r = 0;
3e8c6b73
AK
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);
bd90c6b2 963 goto out;
3e8c6b73
AK
964 }
965
966 if (!dm_task_no_open_count(dmt))
967 log_error("Failed to disable open_count");
968
f16aea9e 969 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
bd90c6b2
AK
970 goto out;
971
3e8c6b73
AK
972 r = dm_task_run(dmt);
973
165e4a11 974 /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
cda69e17
PR
975 rm_dev_node(name, dmt->cookie_set &&
976 !(udev_flags & DM_UDEV_DISABLE_DM_RULES_FLAG));
165e4a11 977
db208f51
AK
978 /* FIXME Remove node from tree or mark invalid? */
979
bd90c6b2 980out:
db208f51
AK
981 dm_task_destroy(dmt);
982
983 return r;
984}
985
bd90c6b2 986static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
f16aea9e 987 uint32_t minor, uint32_t *cookie, uint16_t udev_flags)
165e4a11
AK
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
b4f1578f
AK
1004 if (!dm_task_set_newname(dmt, new_name))
1005 goto_out;
165e4a11
AK
1006
1007 if (!dm_task_no_open_count(dmt))
1008 log_error("Failed to disable open_count");
1009
f16aea9e 1010 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
bd90c6b2
AK
1011 goto out;
1012
165e4a11
AK
1013 r = dm_task_run(dmt);
1014
1015out:
1016 dm_task_destroy(dmt);
1017
1018 return r;
1019}
1020
165e4a11
AK
1021/* FIXME Merge with _suspend_node? */
1022static int _resume_node(const char *name, uint32_t major, uint32_t minor,
52b84409 1023 uint32_t read_ahead, uint32_t read_ahead_flags,
f16aea9e
PR
1024 struct dm_info *newinfo, uint32_t *cookie,
1025 uint16_t udev_flags)
165e4a11
AK
1026{
1027 struct dm_task *dmt;
bd90c6b2 1028 int r = 0;
165e4a11
AK
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
0b7d16bc
AK
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);
bd90c6b2 1040 goto out;
0b7d16bc
AK
1041 }
1042
165e4a11
AK
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);
bd90c6b2 1045 goto out;
165e4a11
AK
1046 }
1047
1048 if (!dm_task_no_open_count(dmt))
1049 log_error("Failed to disable open_count");
1050
52b84409
AK
1051 if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
1052 log_error("Failed to set read ahead");
1053
f16aea9e 1054 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
bd90c6b2
AK
1055 goto out;
1056
165e4a11
AK
1057 if ((r = dm_task_run(dmt)))
1058 r = dm_task_get_info(dmt, newinfo);
1059
bd90c6b2 1060out:
165e4a11
AK
1061 dm_task_destroy(dmt);
1062
1063 return r;
1064}
1065
db208f51 1066static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
b9ffd32c 1067 int skip_lockfs, int no_flush, struct dm_info *newinfo)
db208f51
AK
1068{
1069 struct dm_task *dmt;
1070 int r;
1071
b9ffd32c
AK
1072 log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
1073 name, major, minor,
1074 skip_lockfs ? "" : " with filesystem sync",
6e1898a5 1075 no_flush ? "" : " with device flush");
db208f51
AK
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
c55b1410
AK
1091 if (skip_lockfs && !dm_task_skip_lockfs(dmt))
1092 log_error("Failed to set skip_lockfs flag.");
1093
b9ffd32c
AK
1094 if (no_flush && !dm_task_no_flush(dmt))
1095 log_error("Failed to set no_flush flag.");
1096
db208f51
AK
1097 if ((r = dm_task_run(dmt)))
1098 r = dm_task_get_info(dmt, newinfo);
1099
3e8c6b73
AK
1100 dm_task_destroy(dmt);
1101
1102 return r;
1103}
1104
18e0f934
AK
1105/*
1106 * FIXME Don't attempt to deactivate known internal dependencies.
1107 */
1108static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
1109 const char *uuid_prefix,
1110 size_t uuid_prefix_len,
1111 unsigned level)
3e8c6b73 1112{
b7eb2ad0 1113 int r = 1;
3e8c6b73 1114 void *handle = NULL;
b4f1578f 1115 struct dm_tree_node *child = dnode;
3e8c6b73
AK
1116 struct dm_info info;
1117 const struct dm_info *dinfo;
1118 const char *name;
1119 const char *uuid;
1120
b4f1578f
AK
1121 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1122 if (!(dinfo = dm_tree_node_get_info(child))) {
3e8c6b73
AK
1123 stack;
1124 continue;
1125 }
1126
b4f1578f 1127 if (!(name = dm_tree_node_get_name(child))) {
3e8c6b73
AK
1128 stack;
1129 continue;
1130 }
1131
b4f1578f 1132 if (!(uuid = dm_tree_node_get_uuid(child))) {
3e8c6b73
AK
1133 stack;
1134 continue;
1135 }
1136
1137 /* Ignore if it doesn't belong to this VG */
2b69db1f 1138 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
3e8c6b73 1139 continue;
3e8c6b73
AK
1140
1141 /* Refresh open_count */
db208f51 1142 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
f55021f4 1143 !info.exists)
3e8c6b73
AK
1144 continue;
1145
f3ef15ef
ZK
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))) {
18e0f934
AK
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 }
f55021f4
AK
1158 continue;
1159 }
1160
76d1aec8
ZK
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
f16aea9e 1166 if (!_deactivate_node(name, info.major, info.minor,
584d1fb7 1167 &child->dtree->cookie, child->udev_flags)) {
3e8c6b73
AK
1168 log_error("Unable to deactivate %s (%" PRIu32
1169 ":%" PRIu32 ")", name, info.major,
1170 info.minor);
b7eb2ad0 1171 r = 0;
3e8c6b73
AK
1172 continue;
1173 }
1174
18e0f934
AK
1175 if (dm_tree_node_num_children(child, 0)) {
1176 if (!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
b7eb2ad0 1177 return_0;
18e0f934 1178 }
3e8c6b73
AK
1179 }
1180
b7eb2ad0 1181 return r;
3e8c6b73 1182}
db208f51 1183
18e0f934
AK
1184int 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
c55b1410
AK
1191void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
1192{
1193 dnode->dtree->skip_lockfs = 1;
1194}
1195
b9ffd32c
AK
1196void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
1197{
1198 dnode->dtree->no_flush = 1;
1199}
1200
b4f1578f 1201int dm_tree_suspend_children(struct dm_tree_node *dnode,
08e64ce5
ZK
1202 const char *uuid_prefix,
1203 size_t uuid_prefix_len)
db208f51 1204{
68085c93 1205 int r = 1;
db208f51 1206 void *handle = NULL;
b4f1578f 1207 struct dm_tree_node *child = dnode;
db208f51
AK
1208 struct dm_info info, newinfo;
1209 const struct dm_info *dinfo;
1210 const char *name;
1211 const char *uuid;
1212
690a5da2 1213 /* Suspend nodes at this level of the tree */
b4f1578f
AK
1214 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1215 if (!(dinfo = dm_tree_node_get_info(child))) {
db208f51
AK
1216 stack;
1217 continue;
1218 }
1219
b4f1578f 1220 if (!(name = dm_tree_node_get_name(child))) {
db208f51
AK
1221 stack;
1222 continue;
1223 }
1224
b4f1578f 1225 if (!(uuid = dm_tree_node_get_uuid(child))) {
db208f51
AK
1226 stack;
1227 continue;
1228 }
1229
1230 /* Ignore if it doesn't belong to this VG */
2b69db1f 1231 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
db208f51
AK
1232 continue;
1233
690a5da2
AK
1234 /* Ensure immediate parents are already suspended */
1235 if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
1236 continue;
1237
db208f51 1238 if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
b700541f 1239 !info.exists || info.suspended)
db208f51
AK
1240 continue;
1241
c55b1410 1242 if (!_suspend_node(name, info.major, info.minor,
b9ffd32c
AK
1243 child->dtree->skip_lockfs,
1244 child->dtree->no_flush, &newinfo)) {
db208f51
AK
1245 log_error("Unable to suspend %s (%" PRIu32
1246 ":%" PRIu32 ")", name, info.major,
1247 info.minor);
68085c93 1248 r = 0;
db208f51
AK
1249 continue;
1250 }
1251
1252 /* Update cached info */
1253 child->info = newinfo;
690a5da2
AK
1254 }
1255
1256 /* Then suspend any child nodes */
1257 handle = NULL;
1258
b4f1578f
AK
1259 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1260 if (!(uuid = dm_tree_node_get_uuid(child))) {
690a5da2
AK
1261 stack;
1262 continue;
1263 }
1264
1265 /* Ignore if it doesn't belong to this VG */
87f98002 1266 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
690a5da2 1267 continue;
db208f51 1268
b4f1578f 1269 if (dm_tree_node_num_children(child, 0))
68085c93
MS
1270 if (!dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
1271 return_0;
db208f51
AK
1272 }
1273
68085c93 1274 return r;
db208f51
AK
1275}
1276
b4f1578f 1277int dm_tree_activate_children(struct dm_tree_node *dnode,
db208f51
AK
1278 const char *uuid_prefix,
1279 size_t uuid_prefix_len)
1280{
2ca6b865 1281 int r = 1;
db208f51 1282 void *handle = NULL;
b4f1578f 1283 struct dm_tree_node *child = dnode;
165e4a11
AK
1284 struct dm_info newinfo;
1285 const char *name;
db208f51 1286 const char *uuid;
56c28292 1287 int priority;
db208f51 1288
165e4a11 1289 /* Activate children first */
b4f1578f
AK
1290 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1291 if (!(uuid = dm_tree_node_get_uuid(child))) {
165e4a11
AK
1292 stack;
1293 continue;
db208f51
AK
1294 }
1295
908db078
AK
1296 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1297 continue;
db208f51 1298
b4f1578f 1299 if (dm_tree_node_num_children(child, 0))
2ca6b865
MS
1300 if (!dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len))
1301 return_0;
56c28292 1302 }
165e4a11 1303
56c28292 1304 handle = NULL;
165e4a11 1305
aa6f4e51 1306 for (priority = 0; priority < 3; priority++) {
56c28292
AK
1307 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1308 if (!(uuid = dm_tree_node_get_uuid(child))) {
1309 stack;
1310 continue;
165e4a11 1311 }
165e4a11 1312
56c28292
AK
1313 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1314 continue;
165e4a11 1315
56c28292
AK
1316 if (priority != child->activation_priority)
1317 continue;
165e4a11 1318
56c28292
AK
1319 if (!(name = dm_tree_node_get_name(child))) {
1320 stack;
1321 continue;
1322 }
1323
1324 /* Rename? */
1325 if (child->props.new_name) {
bd90c6b2 1326 if (!_rename_node(name, child->props.new_name, child->info.major,
f16aea9e
PR
1327 child->info.minor, &child->dtree->cookie,
1328 child->udev_flags)) {
56c28292
AK
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
bafa2f39 1341 if (!_resume_node(child->name, child->info.major, child->info.minor,
bd90c6b2 1342 child->props.read_ahead, child->props.read_ahead_flags,
f16aea9e 1343 &newinfo, &child->dtree->cookie, child->udev_flags)) {
56c28292 1344 log_error("Unable to resume %s (%" PRIu32
bafa2f39 1345 ":%" PRIu32 ")", child->name, child->info.major,
56c28292 1346 child->info.minor);
2ca6b865 1347 r = 0;
56c28292
AK
1348 continue;
1349 }
1350
1351 /* Update cached info */
1352 child->info = newinfo;
1353 }
db208f51
AK
1354 }
1355
165e4a11
AK
1356 handle = NULL;
1357
2ca6b865 1358 return r;
165e4a11
AK
1359}
1360
b4f1578f 1361static int _create_node(struct dm_tree_node *dnode)
165e4a11
AK
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
1401out:
1402 dm_task_destroy(dmt);
1403
1404 return r;
1405}
1406
1407
b4f1578f 1408static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
165e4a11
AK
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
ffa9b6a5
ZK
1420/* simplify string emiting code */
1421#define EMIT_PARAMS(p, str...)\
7b6c011c
AK
1422do {\
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)
ffa9b6a5 1430
3c74075f
JEB
1431/*
1432 * _emit_areas_line
1433 *
1434 * Returns: 1 on success, 0 on failure
1435 */
08f1ddea 1436static int _emit_areas_line(struct dm_task *dmt __attribute__((unused)),
4dcaa230
AK
1437 struct load_segment *seg, char *params,
1438 size_t paramsize, int *pos)
165e4a11
AK
1439{
1440 struct seg_area *area;
7d7d93ac 1441 char devbuf[DM_FORMAT_DEV_BUFSIZE];
609faae9 1442 unsigned first_time = 1;
db3c1ac1 1443 const char *logtype, *synctype;
b262f3e1 1444 unsigned log_parm_count;
165e4a11 1445
2c44337b 1446 dm_list_iterate_items(area, &seg->areas) {
b4f1578f
AK
1447 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1448 return_0;
165e4a11 1449
b262f3e1
ZK
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
db3c1ac1
AK
1476 synctype = (area->flags & DM_NOSYNC) ?
1477 " nosync" : (area->flags & DM_FORCESYNC) ?
1478 " sync" : NULL;
b262f3e1 1479
db3c1ac1
AK
1480 if (synctype)
1481 EMIT_PARAMS(*pos, "%s", synctype);
b262f3e1
ZK
1482 }
1483 break;
1484 default:
1485 EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
1486 devbuf, area->offset);
1487 }
609faae9
AK
1488
1489 first_time = 0;
165e4a11
AK
1490 }
1491
1492 return 1;
1493}
1494
b262f3e1
ZK
1495static 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
3c74075f 1531/*
3c74075f
JEB
1532 * Returns: 1 on success, 0 on failure
1533 */
536f0e08
AK
1534static 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)
165e4a11 1538{
8f26e18c
JEB
1539 int r;
1540 int block_on_error = 0;
1541 int handle_errors = 0;
1542 int dm_log_userspace = 0;
1543 struct utsname uts;
dbcb64b8 1544 unsigned log_parm_count;
ffa9b6a5 1545 int pos = 0;
7d7d93ac 1546 char logbuf[DM_FORMAT_DEV_BUFSIZE];
dbcb64b8 1547 const char *logtype;
ba61f848 1548 unsigned kmaj, kmin, krel;
165e4a11 1549
30a65310
ZK
1550 if (uname(&uts) == -1 || sscanf(uts.release, "%u.%u.%u", &kmaj, &kmin, &krel) != 3) {
1551 log_error("Cannot read kernel release version");
1552 return 0;
1553 }
67b25ed4 1554
8f26e18c
JEB
1555 if ((seg->flags & DM_BLOCK_ON_ERROR)) {
1556 /*
1557 * Originally, block_on_error was an argument to the log
1558 * portion of the mirror CTR table. It was renamed to
1559 * "handle_errors" and now resides in the 'features'
1560 * section of the mirror CTR table (i.e. at the end).
1561 *
1562 * We can identify whether to use "block_on_error" or
1563 * "handle_errors" by the dm-mirror module's version
1564 * number (>= 1.12) or by the kernel version (>= 2.6.22).
1565 */
ba61f848 1566 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 22))
8f26e18c
JEB
1567 handle_errors = 1;
1568 else
1569 block_on_error = 1;
1570 }
1571
1572 if (seg->clustered) {
1573 /* Cluster mirrors require a UUID */
1574 if (!seg->uuid)
1575 return_0;
1576
1577 /*
1578 * Cluster mirrors used to have their own log
1579 * types. Now they are accessed through the
1580 * userspace log type.
1581 *
1582 * The dm-log-userspace module was added to the
1583 * 2.6.31 kernel.
1584 */
ba61f848 1585 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 31))
8f26e18c
JEB
1586 dm_log_userspace = 1;
1587 }
1588
1589 /* Region size */
1590 log_parm_count = 1;
1591
1592 /* [no]sync, block_on_error etc. */
1593 log_parm_count += hweight32(seg->flags);
311d6d81 1594
8f26e18c
JEB
1595 /* "handle_errors" is a feature arg now */
1596 if (handle_errors)
1597 log_parm_count--;
1598
1599 /* DM_CORELOG does not count in the param list */
1600 if (seg->flags & DM_CORELOG)
1601 log_parm_count--;
1602
1603 if (seg->clustered) {
1604 log_parm_count++; /* For UUID */
1605
1606 if (!dm_log_userspace)
ffa9b6a5 1607 EMIT_PARAMS(pos, "clustered-");
49b95a5e
JEB
1608 else
1609 /* For clustered-* type field inserted later */
1610 log_parm_count++;
8f26e18c 1611 }
dbcb64b8 1612
8f26e18c
JEB
1613 if (!seg->log)
1614 logtype = "core";
1615 else {
1616 logtype = "disk";
1617 log_parm_count++;
1618 if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
1619 return_0;
1620 }
dbcb64b8 1621
8f26e18c
JEB
1622 if (dm_log_userspace)
1623 EMIT_PARAMS(pos, "userspace %u %s clustered-%s",
1624 log_parm_count, seg->uuid, logtype);
1625 else
ffa9b6a5 1626 EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count);
dbcb64b8 1627
8f26e18c
JEB
1628 if (seg->log)
1629 EMIT_PARAMS(pos, " %s", logbuf);
1630
1631 EMIT_PARAMS(pos, " %u", seg->region_size);
dbcb64b8 1632
8f26e18c
JEB
1633 if (seg->clustered && !dm_log_userspace)
1634 EMIT_PARAMS(pos, " %s", seg->uuid);
67b25ed4 1635
8f26e18c
JEB
1636 if ((seg->flags & DM_NOSYNC))
1637 EMIT_PARAMS(pos, " nosync");
1638 else if ((seg->flags & DM_FORCESYNC))
1639 EMIT_PARAMS(pos, " sync");
dbcb64b8 1640
8f26e18c
JEB
1641 if (block_on_error)
1642 EMIT_PARAMS(pos, " block_on_error");
1643
1644 EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
1645
3c74075f
JEB
1646 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0)
1647 return_0;
dbcb64b8 1648
8f26e18c
JEB
1649 if (handle_errors)
1650 EMIT_PARAMS(pos, " 1 handle_errors");
ffa9b6a5 1651
3c74075f 1652 return 1;
8f26e18c
JEB
1653}
1654
1655static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
1656 uint32_t minor, struct load_segment *seg,
1657 uint64_t *seg_start, char *params,
1658 size_t paramsize)
1659{
1660 int pos = 0;
1661 int r;
1662 char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
dbcb64b8 1663
8f26e18c
JEB
1664 switch(seg->type) {
1665 case SEG_ERROR:
1666 case SEG_ZERO:
1667 case SEG_LINEAR:
1668 break;
1669 case SEG_MIRRORED:
1670 /* Mirrors are pretty complicated - now in separate function */
536f0e08
AK
1671 r = _mirror_emit_segment_line(dmt, major, minor, seg, seg_start,
1672 params, paramsize);
3c74075f
JEB
1673 if (!r)
1674 return_0;
165e4a11 1675 break;
b262f3e1
ZK
1676 case SEG_REPLICATOR:
1677 if ((r = _replicator_emit_segment_line(seg, params, paramsize,
1678 &pos)) <= 0) {
1679 stack;
1680 return r;
1681 }
1682 break;
1683 case SEG_REPLICATOR_DEV:
1684 if (!seg->replicator || !_build_dev_string(originbuf,
1685 sizeof(originbuf),
1686 seg->replicator))
1687 return_0;
1688
1689 EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
1690 break;
165e4a11 1691 case SEG_SNAPSHOT:
aa6f4e51 1692 case SEG_SNAPSHOT_MERGE:
b4f1578f
AK
1693 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1694 return_0;
1695 if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
1696 return_0;
ffa9b6a5
ZK
1697 EMIT_PARAMS(pos, "%s %s %c %d", originbuf, cowbuf,
1698 seg->persistent ? 'P' : 'N', seg->chunk_size);
165e4a11
AK
1699 break;
1700 case SEG_SNAPSHOT_ORIGIN:
b4f1578f
AK
1701 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1702 return_0;
ffa9b6a5 1703 EMIT_PARAMS(pos, "%s", originbuf);
165e4a11
AK
1704 break;
1705 case SEG_STRIPED:
609faae9 1706 EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
165e4a11 1707 break;
12ca060e 1708 case SEG_CRYPT:
609faae9 1709 EMIT_PARAMS(pos, "%s%s%s%s%s %s %" PRIu64 " ", seg->cipher,
12ca060e
MB
1710 seg->chainmode ? "-" : "", seg->chainmode ?: "",
1711 seg->iv ? "-" : "", seg->iv ?: "", seg->key,
1712 seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
1713 seg->iv_offset : *seg_start);
1714 break;
165e4a11
AK
1715 }
1716
1717 switch(seg->type) {
1718 case SEG_ERROR:
b262f3e1 1719 case SEG_REPLICATOR:
165e4a11
AK
1720 case SEG_SNAPSHOT:
1721 case SEG_SNAPSHOT_ORIGIN:
aa6f4e51 1722 case SEG_SNAPSHOT_MERGE:
165e4a11
AK
1723 case SEG_ZERO:
1724 break;
12ca060e 1725 case SEG_CRYPT:
165e4a11 1726 case SEG_LINEAR:
b262f3e1 1727 case SEG_REPLICATOR_DEV:
165e4a11
AK
1728 case SEG_STRIPED:
1729 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
1730 stack;
1731 return r;
1732 }
1733 break;
1734 }
1735
4b2cae46
AK
1736 log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64
1737 " %" PRIu64 " %s %s", major, minor,
165e4a11
AK
1738 *seg_start, seg->size, dm_segtypes[seg->type].target, params);
1739
b4f1578f
AK
1740 if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))
1741 return_0;
165e4a11
AK
1742
1743 *seg_start += seg->size;
1744
1745 return 1;
1746}
1747
ffa9b6a5
ZK
1748#undef EMIT_PARAMS
1749
4b2cae46
AK
1750static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
1751 struct load_segment *seg, uint64_t *seg_start)
165e4a11
AK
1752{
1753 char *params;
1754 size_t paramsize = 4096;
1755 int ret;
1756
1757 do {
1758 if (!(params = dm_malloc(paramsize))) {
1759 log_error("Insufficient space for target parameters.");
1760 return 0;
1761 }
1762
12ea7cb1 1763 params[0] = '\0';
4b2cae46
AK
1764 ret = _emit_segment_line(dmt, major, minor, seg, seg_start,
1765 params, paramsize);
165e4a11
AK
1766 dm_free(params);
1767
1768 if (!ret)
1769 stack;
1770
1771 if (ret >= 0)
1772 return ret;
1773
1774 log_debug("Insufficient space in params[%" PRIsize_t
1775 "] for target parameters.", paramsize);
1776
1777 paramsize *= 2;
1778 } while (paramsize < MAX_TARGET_PARAMSIZE);
1779
1780 log_error("Target parameter size too big. Aborting.");
1781 return 0;
1782}
1783
b4f1578f 1784static int _load_node(struct dm_tree_node *dnode)
165e4a11
AK
1785{
1786 int r = 0;
1787 struct dm_task *dmt;
1788 struct load_segment *seg;
1789 uint64_t seg_start = 0;
1790
4b2cae46
AK
1791 log_verbose("Loading %s table (%" PRIu32 ":%" PRIu32 ")", dnode->name,
1792 dnode->info.major, dnode->info.minor);
165e4a11
AK
1793
1794 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
1795 log_error("Reload dm_task creation failed for %s", dnode->name);
1796 return 0;
1797 }
1798
1799 if (!dm_task_set_major(dmt, dnode->info.major) ||
1800 !dm_task_set_minor(dmt, dnode->info.minor)) {
1801 log_error("Failed to set device number for %s reload.", dnode->name);
1802 goto out;
1803 }
1804
1805 if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1806 log_error("Failed to set read only flag for %s", dnode->name);
1807 goto out;
1808 }
1809
1810 if (!dm_task_no_open_count(dmt))
1811 log_error("Failed to disable open_count");
1812
2c44337b 1813 dm_list_iterate_items(seg, &dnode->props.segs)
4b2cae46
AK
1814 if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor,
1815 seg, &seg_start))
b4f1578f 1816 goto_out;
165e4a11 1817
ec289b64
AK
1818 if (!dm_task_suppress_identical_reload(dmt))
1819 log_error("Failed to suppress reload of identical tables.");
1820
1821 if ((r = dm_task_run(dmt))) {
165e4a11 1822 r = dm_task_get_info(dmt, &dnode->info);
ec289b64
AK
1823 if (r && !dnode->info.inactive_table)
1824 log_verbose("Suppressed %s identical table reload.",
1825 dnode->name);
bb875bb9
AK
1826
1827 if ((dnode->props.size_changed =
1828 (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
1829 log_debug("Table size changed from %" PRIu64 " to %"
1830 PRIu64 " for %s",
1831 dm_task_get_existing_table_size(dmt),
1832 seg_start, dnode->name);
ec289b64 1833 }
165e4a11
AK
1834
1835 dnode->props.segment_count = 0;
1836
1837out:
1838 dm_task_destroy(dmt);
1839
1840 return r;
165e4a11
AK
1841}
1842
b4f1578f 1843int dm_tree_preload_children(struct dm_tree_node *dnode,
bb875bb9
AK
1844 const char *uuid_prefix,
1845 size_t uuid_prefix_len)
165e4a11 1846{
2ca6b865 1847 int r = 1;
165e4a11 1848 void *handle = NULL;
b4f1578f 1849 struct dm_tree_node *child;
165e4a11 1850 struct dm_info newinfo;
566515c0 1851 int update_devs_flag = 0;
165e4a11
AK
1852
1853 /* Preload children first */
b4f1578f 1854 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
165e4a11
AK
1855 /* Skip existing non-device-mapper devices */
1856 if (!child->info.exists && child->info.major)
1857 continue;
1858
1859 /* Ignore if it doesn't belong to this VG */
87f98002
AK
1860 if (child->info.exists &&
1861 !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
165e4a11
AK
1862 continue;
1863
b4f1578f 1864 if (dm_tree_node_num_children(child, 0))
2ca6b865
MS
1865 if (!dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len))
1866 return_0;
165e4a11 1867
165e4a11
AK
1868 /* FIXME Cope if name exists with no uuid? */
1869 if (!child->info.exists) {
1870 if (!_create_node(child)) {
1871 stack;
1872 return 0;
1873 }
1874 }
1875
1876 if (!child->info.inactive_table && child->props.segment_count) {
1877 if (!_load_node(child)) {
1878 stack;
1879 return 0;
1880 }
1881 }
1882
eb91c4ee
MB
1883 /* Propagate device size change change */
1884 if (child->props.size_changed)
1885 dnode->props.size_changed = 1;
1886
bb875bb9 1887 /* Resume device immediately if it has parents and its size changed */
3776c494 1888 if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
165e4a11
AK
1889 continue;
1890
7707ea90
AK
1891 if (!child->info.inactive_table && !child->info.suspended)
1892 continue;
1893
fc795d87 1894 if (!_resume_node(child->name, child->info.major, child->info.minor,
bd90c6b2 1895 child->props.read_ahead, child->props.read_ahead_flags,
f16aea9e 1896 &newinfo, &child->dtree->cookie, child->udev_flags)) {
165e4a11 1897 log_error("Unable to resume %s (%" PRIu32
fc795d87 1898 ":%" PRIu32 ")", child->name, child->info.major,
165e4a11 1899 child->info.minor);
2ca6b865 1900 r = 0;
165e4a11
AK
1901 continue;
1902 }
1903
1904 /* Update cached info */
1905 child->info = newinfo;
566515c0
PR
1906
1907 /*
1908 * Prepare for immediate synchronization with udev and flush all stacked
1909 * dev node operations if requested by immediate_dev_node property. But
1910 * finish processing current level in the tree first.
1911 */
1912 if (child->props.immediate_dev_node)
1913 update_devs_flag = 1;
1914
165e4a11
AK
1915 }
1916
1917 handle = NULL;
1918
566515c0
PR
1919 if (update_devs_flag) {
1920 if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
1921 stack;
1922 dm_tree_set_cookie(dnode, 0);
1923 dm_task_update_nodes();
1924 }
1925
2ca6b865 1926 return r;
165e4a11
AK
1927}
1928
165e4a11
AK
1929/*
1930 * Returns 1 if unsure.
1931 */
b4f1578f 1932int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
165e4a11
AK
1933 const char *uuid_prefix,
1934 size_t uuid_prefix_len)
1935{
1936 void *handle = NULL;
b4f1578f 1937 struct dm_tree_node *child = dnode;
165e4a11
AK
1938 const char *uuid;
1939
b4f1578f
AK
1940 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1941 if (!(uuid = dm_tree_node_get_uuid(child))) {
1942 log_error("Failed to get uuid for dtree node.");
165e4a11
AK
1943 return 1;
1944 }
1945
87f98002 1946 if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
165e4a11
AK
1947 return 1;
1948
b4f1578f
AK
1949 if (dm_tree_node_num_children(child, 0))
1950 dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
165e4a11
AK
1951 }
1952
1953 return 0;
1954}
1955
1956/*
1957 * Target functions
1958 */
b4f1578f 1959static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
165e4a11
AK
1960{
1961 struct load_segment *seg;
1962
b4f1578f
AK
1963 if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
1964 log_error("dtree node segment allocation failed");
165e4a11
AK
1965 return NULL;
1966 }
1967
1968 seg->type = type;
1969 seg->size = size;
1970 seg->area_count = 0;
2c44337b 1971 dm_list_init(&seg->areas);
165e4a11
AK
1972 seg->stripe_size = 0;
1973 seg->persistent = 0;
1974 seg->chunk_size = 0;
1975 seg->cow = NULL;
1976 seg->origin = NULL;
aa6f4e51 1977 seg->merge = NULL;
165e4a11 1978
2c44337b 1979 dm_list_add(&dnode->props.segs, &seg->list);
165e4a11
AK
1980 dnode->props.segment_count++;
1981
1982 return seg;
1983}
1984
b4f1578f 1985int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
165e4a11
AK
1986 uint64_t size,
1987 const char *origin_uuid)
1988{
1989 struct load_segment *seg;
b4f1578f 1990 struct dm_tree_node *origin_node;
165e4a11 1991
b4f1578f
AK
1992 if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
1993 return_0;
165e4a11 1994
b4f1578f 1995 if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
165e4a11
AK
1996 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
1997 return 0;
1998 }
1999
2000 seg->origin = origin_node;
b4f1578f
AK
2001 if (!_link_tree_nodes(dnode, origin_node))
2002 return_0;
165e4a11 2003
56c28292
AK
2004 /* Resume snapshot origins after new snapshots */
2005 dnode->activation_priority = 1;
2006
165e4a11
AK
2007 return 1;
2008}
2009
aa6f4e51
MS
2010static int _add_snapshot_target(struct dm_tree_node *node,
2011 uint64_t size,
2012 const char *origin_uuid,
2013 const char *cow_uuid,
2014 const char *merge_uuid,
2015 int persistent,
2016 uint32_t chunk_size)
165e4a11
AK
2017{
2018 struct load_segment *seg;
aa6f4e51
MS
2019 struct dm_tree_node *origin_node, *cow_node, *merge_node;
2020 unsigned seg_type;
2021
2022 seg_type = !merge_uuid ? SEG_SNAPSHOT : SEG_SNAPSHOT_MERGE;
165e4a11 2023
aa6f4e51 2024 if (!(seg = _add_segment(node, seg_type, size)))
b4f1578f 2025 return_0;
165e4a11 2026
b4f1578f 2027 if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
165e4a11
AK
2028 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
2029 return 0;
2030 }
2031
2032 seg->origin = origin_node;
b4f1578f
AK
2033 if (!_link_tree_nodes(node, origin_node))
2034 return_0;
165e4a11 2035
b4f1578f 2036 if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
aa6f4e51 2037 log_error("Couldn't find snapshot COW device uuid %s.", cow_uuid);
165e4a11
AK
2038 return 0;
2039 }
2040
2041 seg->cow = cow_node;
b4f1578f
AK
2042 if (!_link_tree_nodes(node, cow_node))
2043 return_0;
165e4a11
AK
2044
2045 seg->persistent = persistent ? 1 : 0;
2046 seg->chunk_size = chunk_size;
2047
aa6f4e51
MS
2048 if (merge_uuid) {
2049 if (!(merge_node = dm_tree_find_node_by_uuid(node->dtree, merge_uuid))) {
2050 /* not a pure error, merging snapshot may have been deactivated */
2051 log_verbose("Couldn't find merging snapshot uuid %s.", merge_uuid);
2052 } else {
2053 seg->merge = merge_node;
2054 /* must not link merging snapshot, would undermine activation_priority below */
2055 }
2056
2057 /* Resume snapshot-merge (acting origin) after other snapshots */
2058 node->activation_priority = 1;
2059 if (seg->merge) {
2060 /* Resume merging snapshot after snapshot-merge */
2061 seg->merge->activation_priority = 2;
2062 }
2063 }
2064
165e4a11
AK
2065 return 1;
2066}
2067
aa6f4e51
MS
2068
2069int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
2070 uint64_t size,
2071 const char *origin_uuid,
2072 const char *cow_uuid,
2073 int persistent,
2074 uint32_t chunk_size)
2075{
2076 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2077 NULL, persistent, chunk_size);
2078}
2079
2080int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
2081 uint64_t size,
2082 const char *origin_uuid,
2083 const char *cow_uuid,
2084 const char *merge_uuid,
2085 uint32_t chunk_size)
2086{
2087 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2088 merge_uuid, 1, chunk_size);
2089}
2090
b4f1578f 2091int dm_tree_node_add_error_target(struct dm_tree_node *node,
165e4a11
AK
2092 uint64_t size)
2093{
b4f1578f
AK
2094 if (!_add_segment(node, SEG_ERROR, size))
2095 return_0;
165e4a11
AK
2096
2097 return 1;
2098}
2099
b4f1578f 2100int dm_tree_node_add_zero_target(struct dm_tree_node *node,
165e4a11
AK
2101 uint64_t size)
2102{
b4f1578f
AK
2103 if (!_add_segment(node, SEG_ZERO, size))
2104 return_0;
165e4a11
AK
2105
2106 return 1;
2107}
2108
b4f1578f 2109int dm_tree_node_add_linear_target(struct dm_tree_node *node,
165e4a11
AK
2110 uint64_t size)
2111{
b4f1578f
AK
2112 if (!_add_segment(node, SEG_LINEAR, size))
2113 return_0;
165e4a11
AK
2114
2115 return 1;
2116}
2117
b4f1578f 2118int dm_tree_node_add_striped_target(struct dm_tree_node *node,
165e4a11
AK
2119 uint64_t size,
2120 uint32_t stripe_size)
2121{
2122 struct load_segment *seg;
2123
b4f1578f
AK
2124 if (!(seg = _add_segment(node, SEG_STRIPED, size)))
2125 return_0;
165e4a11
AK
2126
2127 seg->stripe_size = stripe_size;
2128
2129 return 1;
2130}
2131
12ca060e
MB
2132int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
2133 uint64_t size,
2134 const char *cipher,
2135 const char *chainmode,
2136 const char *iv,
2137 uint64_t iv_offset,
2138 const char *key)
2139{
2140 struct load_segment *seg;
2141
2142 if (!(seg = _add_segment(node, SEG_CRYPT, size)))
2143 return_0;
2144
2145 seg->cipher = cipher;
2146 seg->chainmode = chainmode;
2147 seg->iv = iv;
2148 seg->iv_offset = iv_offset;
2149 seg->key = key;
2150
2151 return 1;
2152}
2153
b4f1578f 2154int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
165e4a11 2155 uint32_t region_size,
08e64ce5 2156 unsigned clustered,
165e4a11 2157 const char *log_uuid,
ce7ed2c0
AK
2158 unsigned area_count,
2159 uint32_t flags)
165e4a11 2160{
908db078 2161 struct dm_tree_node *log_node = NULL;
165e4a11
AK
2162 struct load_segment *seg;
2163
2164 if (!node->props.segment_count) {
b8175c33 2165 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
165e4a11
AK
2166 return 0;
2167 }
2168
2c44337b 2169 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
165e4a11 2170
24b026e3 2171 if (log_uuid) {
67b25ed4
AK
2172 if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
2173 log_error("log uuid pool_strdup failed");
2174 return 0;
2175 }
9723090c
AK
2176 if (!(flags & DM_CORELOG)) {
2177 if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
2178 log_error("Couldn't find mirror log uuid %s.", log_uuid);
2179 return 0;
2180 }
2181
566515c0
PR
2182 if (clustered)
2183 log_node->props.immediate_dev_node = 1;
2184
9723090c
AK
2185 if (!_link_tree_nodes(node, log_node))
2186 return_0;
2187 }
165e4a11
AK
2188 }
2189
2190 seg->log = log_node;
165e4a11
AK
2191 seg->region_size = region_size;
2192 seg->clustered = clustered;
2193 seg->mirror_area_count = area_count;
dbcb64b8 2194 seg->flags = flags;
165e4a11
AK
2195
2196 return 1;
2197}
2198
b4f1578f 2199int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
165e4a11
AK
2200 uint64_t size)
2201{
cbecd3cd 2202 if (!_add_segment(node, SEG_MIRRORED, size))
b4f1578f 2203 return_0;
165e4a11
AK
2204
2205 return 1;
2206}
2207
b262f3e1
ZK
2208int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
2209 uint64_t size,
2210 const char *rlog_uuid,
2211 const char *rlog_type,
2212 unsigned rsite_index,
2213 dm_replicator_mode_t mode,
2214 uint32_t async_timeout,
2215 uint64_t fall_behind_data,
2216 uint32_t fall_behind_ios)
2217{
2218 struct load_segment *rseg;
2219 struct replicator_site *rsite;
2220
2221 /* Local site0 - adds replicator segment and links rlog device */
2222 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2223 if (node->props.segment_count) {
2224 log_error(INTERNAL_ERROR "Attempt to add replicator segment to already used node.");
2225 return 0;
2226 }
2227
2228 if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
2229 return_0;
2230
2231 if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
2232 log_error("Missing replicator log uuid %s.", rlog_uuid);
2233 return 0;
2234 }
2235
2236 if (!_link_tree_nodes(node, rseg->log))
2237 return_0;
2238
2239 if (strcmp(rlog_type, "ringbuffer") != 0) {
2240 log_error("Unsupported replicator log type %s.", rlog_type);
2241 return 0;
2242 }
2243
2244 if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
2245 return_0;
2246
2247 dm_list_init(&rseg->rsites);
2248 rseg->rdevice_count = 0;
2249 node->activation_priority = 1;
2250 }
2251
2252 /* Add site to segment */
2253 if (mode == DM_REPLICATOR_SYNC
2254 && (async_timeout || fall_behind_ios || fall_behind_data)) {
2255 log_error("Async parameters passed for synchronnous replicator.");
2256 return 0;
2257 }
2258
2259 if (node->props.segment_count != 1) {
2260 log_error(INTERNAL_ERROR "Attempt to add remote site area before setting replicator log.");
2261 return 0;
2262 }
2263
2264 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2265 if (rseg->type != SEG_REPLICATOR) {
2266 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2267 dm_segtypes[rseg->type].target);
2268 return 0;
2269 }
2270
2271 if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof(*rsite)))) {
2272 log_error("Failed to allocate remote site segment.");
2273 return 0;
2274 }
2275
2276 dm_list_add(&rseg->rsites, &rsite->list);
2277 rseg->rsite_count++;
2278
2279 rsite->mode = mode;
2280 rsite->async_timeout = async_timeout;
2281 rsite->fall_behind_data = fall_behind_data;
2282 rsite->fall_behind_ios = fall_behind_ios;
2283 rsite->rsite_index = rsite_index;
2284
2285 return 1;
2286}
2287
2288/* Appends device node to Replicator */
2289int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
2290 uint64_t size,
2291 const char *replicator_uuid,
2292 uint64_t rdevice_index,
2293 const char *rdev_uuid,
2294 unsigned rsite_index,
2295 const char *slog_uuid,
2296 uint32_t slog_flags,
2297 uint32_t slog_region_size)
2298{
2299 struct seg_area *area;
2300 struct load_segment *rseg;
2301 struct load_segment *rep_seg;
2302
2303 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2304 /* Site index for local target */
2305 if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
2306 return_0;
2307
2308 if (!(rseg->replicator = dm_tree_find_node_by_uuid(node->dtree, replicator_uuid))) {
2309 log_error("Missing replicator uuid %s.", replicator_uuid);
2310 return 0;
2311 }
2312
2313 /* Local slink0 for replicator must be always initialized first */
2314 if (rseg->replicator->props.segment_count != 1) {
2315 log_error(INTERNAL_ERROR "Attempt to use non replicator segment.");
2316 return 0;
2317 }
2318
2319 rep_seg = dm_list_item(dm_list_last(&rseg->replicator->props.segs), struct load_segment);
2320 if (rep_seg->type != SEG_REPLICATOR) {
2321 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2322 dm_segtypes[rep_seg->type].target);
2323 return 0;
2324 }
2325 rep_seg->rdevice_count++;
2326
2327 if (!_link_tree_nodes(node, rseg->replicator))
2328 return_0;
2329
2330 rseg->rdevice_index = rdevice_index;
2331 } else {
2332 /* Local slink0 for replicator must be always initialized first */
2333 if (node->props.segment_count != 1) {
2334 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment.");
2335 return 0;
2336 }
2337
2338 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2339 if (rseg->type != SEG_REPLICATOR_DEV) {
2340 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment %s.",
2341 dm_segtypes[rseg->type].target);
2342 return 0;
2343 }
2344 }
2345
2346 if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
2347 log_error("Unspecified sync log uuid.");
2348 return 0;
2349 }
2350
2351 if (!dm_tree_node_add_target_area(node, NULL, rdev_uuid, 0))
2352 return_0;
2353
2354 area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
2355
2356 if (!(slog_flags & DM_CORELOG)) {
2357 if (!(area->slog = dm_tree_find_node_by_uuid(node->dtree, slog_uuid))) {
2358 log_error("Couldn't find sync log uuid %s.", slog_uuid);
2359 return 0;
2360 }
2361
2362 if (!_link_tree_nodes(node, area->slog))
2363 return_0;
2364 }
2365
2366 area->flags = slog_flags;
2367 area->region_size = slog_region_size;
2368 area->rsite_index = rsite_index;
2369
2370 return 1;
2371}
2372
b4f1578f 2373static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
165e4a11
AK
2374{
2375 struct seg_area *area;
2376
b4f1578f 2377 if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
165e4a11
AK
2378 log_error("Failed to allocate target segment area.");
2379 return 0;
2380 }
2381
2382 area->dev_node = dev_node;
2383 area->offset = offset;
2384
2c44337b 2385 dm_list_add(&seg->areas, &area->list);
165e4a11
AK
2386 seg->area_count++;
2387
2388 return 1;
2389}
2390
b4f1578f 2391int dm_tree_node_add_target_area(struct dm_tree_node *node,
165e4a11
AK
2392 const char *dev_name,
2393 const char *uuid,
2394 uint64_t offset)
2395{
2396 struct load_segment *seg;
2397 struct stat info;
b4f1578f 2398 struct dm_tree_node *dev_node;
165e4a11
AK
2399
2400 if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
b4f1578f 2401 log_error("dm_tree_node_add_target_area called without device");
165e4a11
AK
2402 return 0;
2403 }
2404
2405 if (uuid) {
b4f1578f 2406 if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
165e4a11
AK
2407 log_error("Couldn't find area uuid %s.", uuid);
2408 return 0;
2409 }
b4f1578f
AK
2410 if (!_link_tree_nodes(node, dev_node))
2411 return_0;
165e4a11
AK
2412 } else {
2413 if (stat(dev_name, &info) < 0) {
2414 log_error("Device %s not found.", dev_name);
2415 return 0;
2416 }
2417
2418 if (!S_ISBLK(info.st_mode)) {
2419 log_error("Device %s is not a block device.", dev_name);
2420 return 0;
2421 }
2422
2423 /* FIXME Check correct macro use */
cda69e17
PR
2424 if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev),
2425 MINOR(info.st_rdev), 0)))
b4f1578f 2426 return_0;
165e4a11
AK
2427 }
2428
2429 if (!node->props.segment_count) {
b8175c33 2430 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
165e4a11
AK
2431 return 0;
2432 }
2433
2c44337b 2434 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
165e4a11 2435
b4f1578f
AK
2436 if (!_add_area(node, seg, dev_node, offset))
2437 return_0;
165e4a11
AK
2438
2439 return 1;
db208f51 2440}
bd90c6b2
AK
2441
2442void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie)
2443{
2444 node->dtree->cookie = cookie;
2445}
2446
2447uint32_t dm_tree_get_cookie(struct dm_tree_node *node)
2448{
2449 return node->dtree->cookie;
2450}
This page took 0.361001 seconds and 5 git commands to generate.