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