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