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