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