xref: /netbsd-src/external/gpl2/lvm2/dist/lib/activate/dev_manager.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /*	$NetBSD: dev_manager.c,v 1.1.1.2 2009/02/18 11:16:50 haad Exp $	*/
2 
3 /*
4  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
6  *
7  * This file is part of LVM2.
8  *
9  * This copyrighted material is made available to anyone wishing to use,
10  * modify, copy, or redistribute it subject to the terms and conditions
11  * of the GNU Lesser General Public License v.2.1.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 
18 #include "lib.h"
19 #include "str_list.h"
20 #include "dev_manager.h"
21 #include "lvm-string.h"
22 #include "fs.h"
23 #include "defaults.h"
24 #include "segtype.h"
25 #include "display.h"
26 #include "toolcontext.h"
27 #include "targets.h"
28 #include "config.h"
29 #include "filter.h"
30 #include "activate.h"
31 
32 #include <limits.h>
33 #include <dirent.h>
34 
35 #define MAX_TARGET_PARAMSIZE 50000
36 #define UUID_PREFIX "LVM-"
37 
38 typedef enum {
39 	PRELOAD,
40 	ACTIVATE,
41 	DEACTIVATE,
42 	SUSPEND,
43 	SUSPEND_WITH_LOCKFS,
44 	CLEAN
45 } action_t;
46 
47 struct dev_manager {
48 	struct dm_pool *mem;
49 
50 	struct cmd_context *cmd;
51 
52 	void *target_state;
53 	uint32_t pvmove_mirror_count;
54 
55 	char *vg_name;
56 };
57 
58 struct lv_layer {
59 	struct logical_volume *lv;
60 	const char *old_name;
61 };
62 
63 static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *layer)
64 {
65 	char *dlid;
66 	size_t len;
67 
68 	if (!layer)
69 		layer = "";
70 
71 	len = sizeof(UUID_PREFIX) + sizeof(union lvid) + strlen(layer);
72 
73 	if (!(dlid = dm_pool_alloc(mem, len))) {
74 		log_error("_build_dlid: pool allocation failed for %" PRIsize_t
75 			  " %s %s.", len, lvid, layer);
76 		return NULL;
77 	}
78 
79 	sprintf(dlid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer);
80 
81 	return dlid;
82 }
83 
84 char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
85 {
86 	return _build_dlid(dm->mem, lvid, layer);
87 }
88 
89 static int _read_only_lv(struct logical_volume *lv)
90 {
91 	return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
92 }
93 
94 /*
95  * Low level device-layer operations.
96  */
97 static struct dm_task *_setup_task(const char *name, const char *uuid,
98 				   uint32_t *event_nr, int task,
99 				   uint32_t major, uint32_t minor)
100 {
101 	struct dm_task *dmt;
102 
103 	if (!(dmt = dm_task_create(task)))
104 		return_NULL;
105 
106 	if (name)
107 		dm_task_set_name(dmt, name);
108 
109 	if (uuid && *uuid)
110 		dm_task_set_uuid(dmt, uuid);
111 
112 	if (event_nr)
113 		dm_task_set_event_nr(dmt, *event_nr);
114 
115 	if (major) {
116 		dm_task_set_major(dmt, major);
117 		dm_task_set_minor(dmt, minor);
118 	}
119 
120 	return dmt;
121 }
122 
123 static int _info_run(const char *name, const char *dlid, struct dm_info *info,
124 		     uint32_t *read_ahead, int mknodes, int with_open_count,
125 		     int with_read_ahead, uint32_t major, uint32_t minor)
126 {
127 	int r = 0;
128 	struct dm_task *dmt;
129 	int dmtask;
130 
131 	dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
132 
133 	if (!(dmt = _setup_task(name, dlid, 0, dmtask, major, minor)))
134 		return_0;
135 
136 	if (!with_open_count)
137 		if (!dm_task_no_open_count(dmt))
138 			log_error("Failed to disable open_count");
139 
140 	if (!dm_task_run(dmt))
141 		goto_out;
142 
143 	if (!dm_task_get_info(dmt, info))
144 		goto_out;
145 
146 	if (with_read_ahead) {
147 		if (!dm_task_get_read_ahead(dmt, read_ahead))
148 			goto_out;
149 	} else if (read_ahead)
150 		*read_ahead = DM_READ_AHEAD_NONE;
151 
152 	r = 1;
153 
154       out:
155 	dm_task_destroy(dmt);
156 	return r;
157 }
158 
159 int device_is_usable(dev_t dev)
160 {
161 	struct dm_task *dmt;
162 	struct dm_info info;
163 	const char *name;
164 	uint64_t start, length;
165 	char *target_type = NULL;
166 	char *params;
167 	void *next = NULL;
168 	int r = 0;
169 
170 	if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
171 		log_error("Failed to allocate dm_task struct to check dev status");
172 		return 0;
173 	}
174 
175 	if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
176 		goto_out;
177 
178 	if (!dm_task_run(dmt)) {
179 		log_error("Failed to get state of mapped device");
180 		goto out;
181 	}
182 
183 	if (!dm_task_get_info(dmt, &info))
184 		goto_out;
185 
186 	if (!info.exists || info.suspended)
187 		goto out;
188 
189 	name = dm_task_get_name(dmt);
190 
191 	/* FIXME Also check for mirror block_on_error and mpath no paths */
192 	/* For now, we exclude all mirrors */
193 
194 	do {
195 		next = dm_get_next_target(dmt, next, &start, &length,
196 					  &target_type, &params);
197 		/* Skip if target type doesn't match */
198 		if (target_type && !strcmp(target_type, "mirror"))
199 			goto out;
200 	} while (next);
201 
202 	/* FIXME Also check dependencies? */
203 
204 	r = 1;
205 
206       out:
207 	dm_task_destroy(dmt);
208 	return r;
209 }
210 
211 static int _info(const char *name, const char *dlid, int mknodes,
212 		 int with_open_count, int with_read_ahead,
213 		 struct dm_info *info, uint32_t *read_ahead)
214 {
215 	if (!mknodes && dlid && *dlid) {
216 		if (_info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
217 			      with_read_ahead, 0, 0) &&
218 	    	    info->exists)
219 			return 1;
220 		else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
221 				   read_ahead, 0, with_open_count,
222 				   with_read_ahead, 0, 0) &&
223 			 info->exists)
224 			return 1;
225 	}
226 
227 	if (name)
228 		return _info_run(name, NULL, info, read_ahead, mknodes,
229 				 with_open_count, with_read_ahead, 0, 0);
230 
231 	return 0;
232 }
233 
234 static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
235 {
236 	return _info_run(NULL, NULL, info, NULL, 0, 0, 0, major, minor);
237 }
238 
239 int dev_manager_info(struct dm_pool *mem, const char *name,
240 		     const struct logical_volume *lv, int with_mknodes,
241 		     int with_open_count, int with_read_ahead,
242 		     struct dm_info *info, uint32_t *read_ahead)
243 {
244 	const char *dlid;
245 
246 	if (!(dlid = _build_dlid(mem, lv->lvid.s, NULL))) {
247 		log_error("dlid build failed for %s", lv->name);
248 		return 0;
249 	}
250 
251 	return _info(name, dlid, with_mknodes, with_open_count, with_read_ahead,
252 		     info, read_ahead);
253 }
254 
255 /* FIXME Interface must cope with multiple targets */
256 static int _status_run(const char *name, const char *uuid,
257 		       unsigned long long *s, unsigned long long *l,
258 		       char **t, uint32_t t_size, char **p, uint32_t p_size)
259 {
260 	int r = 0;
261 	struct dm_task *dmt;
262 	struct dm_info info;
263 	void *next = NULL;
264 	uint64_t start, length;
265 	char *type = NULL;
266 	char *params = NULL;
267 
268 	if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS, 0, 0)))
269 		return_0;
270 
271 	if (!dm_task_no_open_count(dmt))
272 		log_error("Failed to disable open_count");
273 
274 	if (!dm_task_run(dmt))
275 		goto_out;
276 
277 	if (!dm_task_get_info(dmt, &info) || !info.exists)
278 		goto_out;
279 
280 	do {
281 		next = dm_get_next_target(dmt, next, &start, &length,
282 					  &type, &params);
283 		if (type) {
284 			*s = start;
285 			*l = length;
286 			/* Make sure things are null terminated */
287 			strncpy(*t, type, t_size);
288 			(*t)[t_size - 1] = '\0';
289 			strncpy(*p, params, p_size);
290 			(*p)[p_size - 1] = '\0';
291 
292 			r = 1;
293 			/* FIXME Cope with multiple targets! */
294 			break;
295 		}
296 
297 	} while (next);
298 
299       out:
300 	dm_task_destroy(dmt);
301 	return r;
302 }
303 
304 static int _status(const char *name, const char *uuid,
305 		   unsigned long long *start, unsigned long long *length,
306 		   char **type, uint32_t type_size, char **params,
307 		   uint32_t param_size) __attribute__ ((unused));
308 
309 static int _status(const char *name, const char *uuid,
310 		   unsigned long long *start, unsigned long long *length,
311 		   char **type, uint32_t type_size, char **params,
312 		   uint32_t param_size)
313 {
314 	if (uuid && *uuid) {
315 		if (_status_run(NULL, uuid, start, length, type,
316 				type_size, params, param_size) &&
317 		    *params)
318 			return 1;
319 		else if (_status_run(NULL, uuid + sizeof(UUID_PREFIX) - 1, start,
320 				     length, type, type_size, params,
321 				     param_size) &&
322 			 *params)
323 			return 1;
324 	}
325 
326 	if (name && _status_run(name, NULL, start, length, type, type_size,
327 				params, param_size))
328 		return 1;
329 
330 	return 0;
331 }
332 
333 static int _percent_run(struct dev_manager *dm, const char *name,
334 			const char *dlid,
335 			const char *target_type, int wait,
336 			struct logical_volume *lv, float *percent,
337 			uint32_t *event_nr)
338 {
339 	int r = 0;
340 	struct dm_task *dmt;
341 	struct dm_info info;
342 	void *next = NULL;
343 	uint64_t start, length;
344 	char *type = NULL;
345 	char *params = NULL;
346 	struct dm_list *segh = &lv->segments;
347 	struct lv_segment *seg = NULL;
348 	struct segment_type *segtype;
349 
350 	uint64_t total_numerator = 0, total_denominator = 0;
351 
352 	*percent = -1;
353 
354 	if (!(dmt = _setup_task(name, dlid, event_nr,
355 				wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0)))
356 		return_0;
357 
358 	if (!dm_task_no_open_count(dmt))
359 		log_error("Failed to disable open_count");
360 
361 	if (!dm_task_run(dmt))
362 		goto_out;
363 
364 	if (!dm_task_get_info(dmt, &info) || !info.exists)
365 		goto_out;
366 
367 	if (event_nr)
368 		*event_nr = info.event_nr;
369 
370 	do {
371 		next = dm_get_next_target(dmt, next, &start, &length, &type,
372 					  &params);
373 		if (lv) {
374 			if (!(segh = dm_list_next(&lv->segments, segh))) {
375 				log_error("Number of segments in active LV %s "
376 					  "does not match metadata", lv->name);
377 				goto out;
378 			}
379 			seg = dm_list_item(segh, struct lv_segment);
380 		}
381 
382 		if (!type || !params || strcmp(type, target_type))
383 			continue;
384 
385 		if (!(segtype = get_segtype_from_string(dm->cmd, type)))
386 			continue;
387 
388 		if (segtype->ops->target_percent &&
389 		    !segtype->ops->target_percent(&dm->target_state, dm->mem,
390 						  dm->cmd, seg, params,
391 						  &total_numerator,
392 						  &total_denominator))
393 			goto_out;
394 
395 	} while (next);
396 
397 	if (lv && (segh = dm_list_next(&lv->segments, segh))) {
398 		log_error("Number of segments in active LV %s does not "
399 			  "match metadata", lv->name);
400 		goto out;
401 	}
402 
403 	if (total_denominator)
404 		*percent = (float) total_numerator *100 / total_denominator;
405 	else
406 		*percent = 100;
407 
408 	log_debug("LV percent: %f", *percent);
409 	r = 1;
410 
411       out:
412 	dm_task_destroy(dmt);
413 	return r;
414 }
415 
416 static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
417 		    const char *target_type, int wait,
418 		    struct logical_volume *lv, float *percent,
419 		    uint32_t *event_nr)
420 {
421 	if (dlid && *dlid) {
422 		if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
423 				 event_nr))
424 			return 1;
425 		else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
426 				      target_type, wait, lv, percent,
427 				      event_nr))
428 			return 1;
429 	}
430 
431 	if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
432 				 event_nr))
433 		return 1;
434 
435 	return 0;
436 }
437 
438 /*
439  * dev_manager implementation.
440  */
441 struct dev_manager *dev_manager_create(struct cmd_context *cmd,
442 				       const char *vg_name)
443 {
444 	struct dm_pool *mem;
445 	struct dev_manager *dm;
446 
447 	if (!(mem = dm_pool_create("dev_manager", 16 * 1024)))
448 		return_NULL;
449 
450 	if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
451 		goto_bad;
452 
453 	dm->cmd = cmd;
454 	dm->mem = mem;
455 
456 	if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
457 		goto_bad;
458 
459 	dm->target_state = NULL;
460 
461 	return dm;
462 
463       bad:
464 	dm_pool_destroy(mem);
465 	return NULL;
466 }
467 
468 void dev_manager_destroy(struct dev_manager *dm)
469 {
470 	dm_pool_destroy(dm->mem);
471 }
472 
473 void dev_manager_release(void)
474 {
475 	dm_lib_release();
476 }
477 
478 void dev_manager_exit(void)
479 {
480 	dm_lib_exit();
481 }
482 
483 int dev_manager_snapshot_percent(struct dev_manager *dm,
484 				 const struct logical_volume *lv,
485 				 float *percent)
486 {
487 	char *name;
488 	const char *dlid;
489 
490 	/*
491 	 * Build a name for the top layer.
492 	 */
493 	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
494 		return_0;
495 
496 	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
497 		return_0;
498 
499 	/*
500 	 * Try and get some info on this device.
501 	 */
502 	log_debug("Getting device status percentage for %s", name);
503 	if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
504 		       NULL)))
505 		return_0;
506 
507 	/* FIXME dm_pool_free ? */
508 
509 	/* If the snapshot isn't available, percent will be -1 */
510 	return 1;
511 }
512 
513 /* FIXME Merge with snapshot_percent, auto-detecting target type */
514 /* FIXME Cope with more than one target */
515 int dev_manager_mirror_percent(struct dev_manager *dm,
516 			       struct logical_volume *lv, int wait,
517 			       float *percent, uint32_t *event_nr)
518 {
519 	char *name;
520 	const char *dlid;
521 
522 	/*
523 	 * Build a name for the top layer.
524 	 */
525 	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
526 		return_0;
527 
528 	/* FIXME dm_pool_free ? */
529 
530 	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL))) {
531 		log_error("dlid build failed for %s", lv->name);
532 		return 0;
533 	}
534 
535 	log_debug("Getting device mirror status percentage for %s", name);
536 	if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
537 		       event_nr)))
538 		return_0;
539 
540 	return 1;
541 }
542 
543 #if 0
544 	log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
545 
546 	log_verbose("Loading %s", dl->name);
547 			log_very_verbose("Activating %s read-only", dl->name);
548 	log_very_verbose("Activated %s %s %03u:%03u", dl->name,
549 			 dl->dlid, dl->info.major, dl->info.minor);
550 
551 	if (_get_flag(dl, VISIBLE))
552 		log_verbose("Removing %s", dl->name);
553 	else
554 		log_very_verbose("Removing %s", dl->name);
555 
556 	log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
557 		  extent_size * seg->le, extent_size * seg->len, target, params);
558 
559 	log_debug("Adding target: 0 %" PRIu64 " snapshot-origin %s",
560 		  dl->lv->size, params);
561 	log_debug("Adding target: 0 %" PRIu64 " snapshot %s", size, params);
562 	log_debug("Getting device info for %s", dl->name);
563 
564 	/* Rename? */
565 		if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-')))
566 			suffix++;
567 		new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name,
568 					suffix);
569 
570 static int _belong_to_vg(const char *vgname, const char *name)
571 {
572 	const char *v = vgname, *n = name;
573 
574 	while (*v) {
575 		if ((*v != *n) || (*v == '-' && *(++n) != '-'))
576 			return 0;
577 		v++, n++;
578 	}
579 
580 	if (*n == '-' && *(n + 1) != '-')
581 		return 1;
582 	else
583 		return 0;
584 }
585 
586 	if (!(snap_seg = find_cow(lv)))
587 		return 1;
588 
589 	old_origin = snap_seg->origin;
590 
591 	/* Was this the last active snapshot with this origin? */
592 	dm_list_iterate_items(lvl, active_head) {
593 		active = lvl->lv;
594 		if ((snap_seg = find_cow(active)) &&
595 		    snap_seg->origin == old_origin) {
596 			return 1;
597 		}
598 	}
599 
600 #endif
601 
602 /*************************/
603 /*  NEW CODE STARTS HERE */
604 /*************************/
605 
606 int dev_manager_lv_mknodes(const struct logical_volume *lv)
607 {
608 	char *name;
609 
610 	if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name,
611 				   lv->name, NULL)))
612 		return_0;
613 
614 	return fs_add_lv(lv, name);
615 }
616 
617 int dev_manager_lv_rmnodes(const struct logical_volume *lv)
618 {
619 	return fs_del_lv(lv);
620 }
621 
622 static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
623 			       struct logical_volume *lv, const char *layer)
624 {
625 	char *dlid, *name;
626 	struct dm_info info, info2;
627 
628 	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
629 		return_0;
630 
631 	if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
632 		return_0;
633 
634 	log_debug("Getting device info for %s [%s]", name, dlid);
635 	if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
636 		log_error("Failed to get info for %s [%s].", name, dlid);
637 		return 0;
638 	}
639 
640 	/*
641 	 * For top level volumes verify that existing device match
642 	 * requested major/minor and that major/minor pair is available for use
643 	 */
644 	if (!layer && lv->major != -1 && lv->minor != -1) {
645 		if (info.exists && (info.major != lv->major || info.minor != lv->minor)) {
646 			log_error("Volume %s (%" PRIu32 ":%" PRIu32")"
647 				  " differs from already active device "
648 				  "(%" PRIu32 ":%" PRIu32")",
649 				  lv->name, lv->major, lv->minor, info.major, info.minor);
650 			return 0;
651 		}
652 		if (!info.exists && _info_by_dev(lv->major, lv->minor, &info2) &&
653 		    info2.exists) {
654 			log_error("The requested major:minor pair "
655 				  "(%" PRIu32 ":%" PRIu32") is already used",
656 				  lv->major, lv->minor);
657 			return 0;
658 		}
659 	}
660 
661 	if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
662 		log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
663 			  info.major, info.minor);
664 		return 0;
665 	}
666 
667 	return 1;
668 }
669 
670 /*
671  * Add LV and any known dependencies
672  */
673 static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv)
674 {
675 	if (!_add_dev_to_dtree(dm, dtree, lv, NULL))
676 		return_0;
677 
678 	/* FIXME Can we avoid doing this every time? */
679 	if (!_add_dev_to_dtree(dm, dtree, lv, "real"))
680 		return_0;
681 
682 	if (!_add_dev_to_dtree(dm, dtree, lv, "cow"))
683 		return_0;
684 
685 	if (!_add_dev_to_dtree(dm, dtree, lv, "_mlog"))
686 		return_0;
687 
688 	return 1;
689 }
690 
691 static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv)
692 {
693 	struct dm_tree *dtree;
694 	struct dm_list *snh, *snht;
695 	struct lv_segment *seg;
696 	uint32_t s;
697 
698 	if (!(dtree = dm_tree_create())) {
699 		log_error("Partial dtree creation failed for %s.", lv->name);
700 		return NULL;
701 	}
702 
703 	if (!_add_lv_to_dtree(dm, dtree, lv))
704 		goto_bad;
705 
706 	/* Add any snapshots of this LV */
707 	dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
708 		if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow))
709 			goto_bad;
710 
711 	/* Add any LVs used by segments in this LV */
712 	dm_list_iterate_items(seg, &lv->segments)
713 		for (s = 0; s < seg->area_count; s++)
714 			if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
715 				if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
716 					goto_bad;
717 			}
718 
719 	return dtree;
720 
721 bad:
722 	dm_tree_free(dtree);
723 	return NULL;
724 }
725 
726 static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
727 			       struct lv_segment *seg, int s)
728 {
729 	char *id, *name;
730 	char errid[32];
731 	struct dm_tree_node *node;
732 	struct lv_segment *seg_i;
733 	int segno = -1, i = 0;;
734 	uint64_t size = seg->len * seg->lv->vg->extent_size;
735 
736 	dm_list_iterate_items(seg_i, &seg->lv->segments) {
737 		if (seg == seg_i)
738 			segno = i;
739 		++i;
740 	}
741 
742 	if (segno < 0) {
743 		log_error("_add_error_device called with bad segment");
744 		return_NULL;
745 	}
746 
747 	sprintf(errid, "missing_%d_%d", segno, s);
748 
749 	if (!(id = build_dlid(dm, seg->lv->lvid.s, errid)))
750 		return_NULL;
751 
752 	if (!(name = build_dm_name(dm->mem, seg->lv->vg->name,
753 				   seg->lv->name, errid)))
754 		return_NULL;
755 	if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0)))
756 		return_NULL;
757 	if (!dm_tree_node_add_error_target(node, size))
758 		return_NULL;
759 
760 	return id;
761 }
762 
763 static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
764 			   struct lv_segment *seg, int s)
765 {
766 	char *dlid;
767 	uint64_t extent_size = seg->lv->vg->extent_size;
768 
769 	if (!strcmp(dm->cmd->stripe_filler, "error")) {
770 		/*
771 		 * FIXME, the tree pointer is first field of dm_tree_node, but
772 		 * we don't have the struct definition available.
773 		 */
774 		struct dm_tree **tree = (struct dm_tree **) node;
775 		dlid = _add_error_device(dm, *tree, seg, s);
776 		if (!dlid)
777 			return_0;
778 		dm_tree_node_add_target_area(node, NULL, dlid,
779 					     extent_size * seg_le(seg, s));
780 	} else
781 		dm_tree_node_add_target_area(node,
782 					     dm->cmd->stripe_filler,
783 					     NULL, UINT64_C(0));
784 
785 	return 1;
786 }
787 
788 int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
789 		   struct dm_tree_node *node, uint32_t start_area,
790 		   uint32_t areas)
791 {
792 	uint64_t extent_size = seg->lv->vg->extent_size;
793 	uint32_t s;
794 	char *dlid;
795 
796 	for (s = start_area; s < areas; s++) {
797 		if ((seg_type(seg, s) == AREA_PV &&
798 		     (!seg_pvseg(seg, s) ||
799 		      !seg_pv(seg, s) ||
800 		      !seg_dev(seg, s))) ||
801 		    (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {
802 			if (!_add_error_area(dm, node, seg, s))
803 				return_0;
804 		} else if (seg_type(seg, s) == AREA_PV)
805 			dm_tree_node_add_target_area(node,
806 							dev_name(seg_dev(seg, s)),
807 							NULL,
808 							(seg_pv(seg, s)->pe_start +
809 							 (extent_size * seg_pe(seg, s))));
810 		else if (seg_type(seg, s) == AREA_LV) {
811 			if (!(dlid = build_dlid(dm,
812 						 seg_lv(seg, s)->lvid.s,
813 						 NULL)))
814 				return_0;
815 			dm_tree_node_add_target_area(node, NULL, dlid,
816 							extent_size * seg_le(seg, s));
817 		} else {
818 			log_error("Internal error: Unassigned area found in LV %s.",
819 				  seg->lv->name);
820 			return 0;
821 		}
822 	}
823 
824 	return 1;
825 }
826 
827 static int _add_origin_target_to_dtree(struct dev_manager *dm,
828 					 struct dm_tree_node *dnode,
829 					 struct logical_volume *lv)
830 {
831 	const char *real_dlid;
832 
833 	if (!(real_dlid = build_dlid(dm, lv->lvid.s, "real")))
834 		return_0;
835 
836 	if (!dm_tree_node_add_snapshot_origin_target(dnode, lv->size, real_dlid))
837 		return_0;
838 
839 	return 1;
840 }
841 
842 static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
843 					   struct dm_tree_node *dnode,
844 					   struct logical_volume *lv)
845 {
846 	const char *origin_dlid;
847 	const char *cow_dlid;
848 	struct lv_segment *snap_seg;
849 	uint64_t size;
850 
851 	if (!(snap_seg = find_cow(lv))) {
852 		log_error("Couldn't find snapshot for '%s'.", lv->name);
853 		return 0;
854 	}
855 
856 	if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real")))
857 		return_0;
858 
859 	if (!(cow_dlid = build_dlid(dm, snap_seg->cow->lvid.s, "cow")))
860 		return_0;
861 
862 	size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
863 
864 	if (!dm_tree_node_add_snapshot_target(dnode, size, origin_dlid, cow_dlid, 1, snap_seg->chunk_size))
865 		return_0;
866 
867 	return 1;
868 }
869 
870 static int _add_target_to_dtree(struct dev_manager *dm,
871 				  struct dm_tree_node *dnode,
872 				  struct lv_segment *seg)
873 {
874 	uint64_t extent_size = seg->lv->vg->extent_size;
875 
876 	if (!seg->segtype->ops->add_target_line) {
877 		log_error("_emit_target: Internal error: Can't handle "
878 			  "segment type %s", seg->segtype->name);
879 		return 0;
880 	}
881 
882 	return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
883 						  &dm->target_state, seg,
884 						  dnode,
885 						  extent_size * seg->len,
886 						  &dm-> pvmove_mirror_count);
887 }
888 
889 static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
890 				  struct logical_volume *lv, const char *layer);
891 
892 static int _add_segment_to_dtree(struct dev_manager *dm,
893 				   struct dm_tree *dtree,
894 				   struct dm_tree_node *dnode,
895 				   struct lv_segment *seg,
896 				   const char *layer)
897 {
898 	uint32_t s;
899 	struct dm_list *snh;
900 	struct lv_segment *seg_present;
901 
902 	/* Ensure required device-mapper targets are loaded */
903 	seg_present = find_cow(seg->lv) ? : seg;
904 
905 	log_debug("Checking kernel supports %s segment type for %s%s%s",
906 		  seg_present->segtype->name, seg->lv->name,
907 		  layer ? "-" : "", layer ? : "");
908 
909 	if (seg_present->segtype->ops->target_present &&
910 	    !seg_present->segtype->ops->target_present(seg_present, NULL)) {
911 		log_error("Can't expand LV %s: %s target support missing "
912 			  "from kernel?", seg->lv->name, seg_present->segtype->name);
913 		return 0;
914 	}
915 
916 	/* Add mirror log */
917 	if (seg->log_lv &&
918 	    !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL))
919 		return_0;
920 
921 	/* If this is a snapshot origin, add real LV */
922 	if (lv_is_origin(seg->lv) && !layer) {
923 		if (vg_is_clustered(seg->lv->vg)) {
924 			log_error("Clustered snapshots are not yet supported");
925 			return 0;
926 		}
927 		if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real"))
928 			return_0;
929 	} else if (lv_is_cow(seg->lv) && !layer) {
930 		if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "cow"))
931 			return_0;
932 	} else {
933 		/* Add any LVs used by this segment */
934 		for (s = 0; s < seg->area_count; s++)
935 			if ((seg_type(seg, s) == AREA_LV) &&
936 			    (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), NULL)))
937 				return_0;
938 	}
939 
940 	/* Now we've added its dependencies, we can add the target itself */
941 	if (lv_is_origin(seg->lv) && !layer) {
942 		if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
943 			return_0;
944 	} else if (lv_is_cow(seg->lv) && !layer) {
945 		if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
946 			return_0;
947 	} else if (!_add_target_to_dtree(dm, dnode, seg))
948 		return_0;
949 
950 	if (lv_is_origin(seg->lv) && !layer)
951 		/* Add any snapshots of this LV */
952 		dm_list_iterate(snh, &seg->lv->snapshot_segs)
953 			if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
954 				return_0;
955 
956 	return 1;
957 }
958 
959 static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
960 				  struct logical_volume *lv, const char *layer)
961 {
962 	struct lv_segment *seg;
963 	struct lv_layer *lvlayer;
964 	struct dm_tree_node *dnode;
965 	char *name, *dlid;
966 	uint32_t max_stripe_size = UINT32_C(0);
967 	uint32_t read_ahead = lv->read_ahead;
968 	uint32_t read_ahead_flags = UINT32_C(0);
969 
970 	if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
971 		return_0;
972 
973 	if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
974 		return_0;
975 
976 	/* We've already processed this node if it already has a context ptr */
977 	if ((dnode = dm_tree_find_node_by_uuid(dtree, dlid)) &&
978 	    dm_tree_node_get_context(dnode))
979 		return 1;
980 
981 	if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
982 		log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
983 		return 0;
984 	}
985 
986 	lvlayer->lv = lv;
987 
988 	/*
989 	 * Add LV to dtree.
990 	 * If we're working with precommitted metadata, clear any
991 	 * existing inactive table left behind.
992 	 * Major/minor settings only apply to the visible layer.
993 	 */
994 	if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
995 					     layer ? UINT32_C(0) : (uint32_t) lv->major,
996 					     layer ? UINT32_C(0) : (uint32_t) lv->minor,
997 					     _read_only_lv(lv),
998 					     (lv->vg->status & PRECOMMITTED) ? 1 : 0,
999 					     lvlayer)))
1000 		return_0;
1001 
1002 	/* Store existing name so we can do rename later */
1003 	lvlayer->old_name = dm_tree_node_get_name(dnode);
1004 
1005 	/* Create table */
1006 	dm->pvmove_mirror_count = 0u;
1007 	dm_list_iterate_items(seg, &lv->segments) {
1008 		if (!_add_segment_to_dtree(dm, dtree, dnode, seg, layer))
1009 			return_0;
1010 		/* These aren't real segments in the LVM2 metadata */
1011 		if (lv_is_origin(lv) && !layer)
1012 			break;
1013 		if (lv_is_cow(lv) && !layer)
1014 			break;
1015 		if (max_stripe_size < seg->stripe_size * seg->area_count)
1016 			max_stripe_size = seg->stripe_size * seg->area_count;
1017 	}
1018 
1019 	if (read_ahead == DM_READ_AHEAD_AUTO) {
1020 		/* we need RA at least twice a whole stripe - see the comment in md/raid0.c */
1021 		read_ahead = max_stripe_size * 2;
1022 		read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
1023 	}
1024 
1025 	dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
1026 
1027 	return 1;
1028 }
1029 
1030 /* FIXME: symlinks should be created/destroyed at the same time
1031  * as the kernel devices but we can't do that from within libdevmapper
1032  * at present so we must walk the tree twice instead. */
1033 
1034 /*
1035  * Create LV symlinks for children of supplied root node.
1036  */
1037 static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
1038 {
1039 	void *handle = NULL;
1040 	struct dm_tree_node *child;
1041 	struct lv_layer *lvlayer;
1042 	char *old_vgname, *old_lvname, *old_layer;
1043 	char *new_vgname, *new_lvname, *new_layer;
1044 	const char *name;
1045 	int r = 1;
1046 
1047 	while ((child = dm_tree_next_child(&handle, root, 0))) {
1048 		if (!(lvlayer = (struct lv_layer *) dm_tree_node_get_context(child)))
1049 			continue;
1050 
1051 		/* Detect rename */
1052 		name = dm_tree_node_get_name(child);
1053 
1054 		if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
1055 			if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &old_vgname, &old_lvname, &old_layer)) {
1056 				log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
1057 				return 0;
1058 			}
1059 			if (!dm_split_lvm_name(dm->mem, name, &new_vgname, &new_lvname, &new_layer)) {
1060 				log_error("_create_lv_symlinks: Couldn't split up new device name %s", name);
1061 				return 0;
1062 			}
1063 			if (!fs_rename_lv(lvlayer->lv, name, old_vgname, old_lvname))
1064 				r = 0;
1065 		} else if (!dev_manager_lv_mknodes(lvlayer->lv))
1066 			r = 0;
1067 	}
1068 
1069 	return r;
1070 }
1071 
1072 /*
1073  * Remove LV symlinks for children of supplied root node.
1074  */
1075 static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root)
1076 {
1077 	void *handle = NULL;
1078 	struct dm_tree_node *child;
1079 	char *vgname, *lvname, *layer;
1080 	int r = 1;
1081 
1082 	while ((child = dm_tree_next_child(&handle, root, 0))) {
1083 		if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
1084 			r = 0;
1085 			continue;
1086 		}
1087 
1088 		if (!*vgname)
1089 			continue;
1090 
1091 		/* only top level layer has symlinks */
1092 		if (*layer)
1093 			continue;
1094 
1095 		fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
1096 	}
1097 
1098 	return r;
1099 }
1100 
1101 static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
1102 {
1103 	void *handle = NULL;
1104 	struct dm_tree_node *child;
1105 	char *vgname, *lvname, *layer;
1106 	const char *name, *uuid;
1107 
1108 	while ((child = dm_tree_next_child(&handle, root, 0))) {
1109 		if (!(name = dm_tree_node_get_name(child)))
1110 			continue;
1111 
1112 		if (!(uuid = dm_tree_node_get_uuid(child)))
1113 			continue;
1114 
1115 		if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
1116 			log_error("_clean_tree: Couldn't split up device name %s.", name);
1117 			return 0;
1118 		}
1119 
1120 		/* Not meant to be top level? */
1121 		if (!*layer)
1122 			continue;
1123 
1124 		if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
1125 			return_0;
1126 	}
1127 
1128 	return 1;
1129 }
1130 
1131 static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, action_t action)
1132 {
1133 	struct dm_tree *dtree;
1134 	struct dm_tree_node *root;
1135 	char *dlid;
1136 	int r = 0;
1137 
1138 	if (!(dtree = _create_partial_dtree(dm, lv)))
1139 		return_0;
1140 
1141 	if (!(root = dm_tree_find_node(dtree, 0, 0))) {
1142 		log_error("Lost dependency tree root node");
1143 		goto out;
1144 	}
1145 
1146 	if (!(dlid = build_dlid(dm, lv->lvid.s, NULL)))
1147 		goto_out;
1148 
1149 	/* Only process nodes with uuid of "LVM-" plus VG id. */
1150 	switch(action) {
1151 	case CLEAN:
1152 		/* Deactivate any unused non-toplevel nodes */
1153 		if (!_clean_tree(dm, root))
1154 			goto_out;
1155 		break;
1156 	case DEACTIVATE:
1157  		/* Deactivate LV and all devices it references that nothing else has open. */
1158 		if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
1159 			goto_out;
1160 		if (!_remove_lv_symlinks(dm, root))
1161 			log_error("Failed to remove all device symlinks associated with %s.", lv->name);
1162 		break;
1163 	case SUSPEND:
1164 		dm_tree_skip_lockfs(root);
1165 		if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
1166 			dm_tree_use_no_flush_suspend(root);
1167 	case SUSPEND_WITH_LOCKFS:
1168 		if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
1169 			goto_out;
1170 		break;
1171 	case PRELOAD:
1172 	case ACTIVATE:
1173 		/* Add all required new devices to tree */
1174 		if (!_add_new_lv_to_dtree(dm, dtree, lv, NULL))
1175 			goto_out;
1176 
1177 		/* Preload any devices required before any suspensions */
1178 		if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
1179 			goto_out;
1180 
1181 		if ((action == ACTIVATE) &&
1182 		    !dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
1183 			goto_out;
1184 
1185 		if (!_create_lv_symlinks(dm, root)) {
1186 			log_error("Failed to create symlinks for %s.", lv->name);
1187 			goto out;
1188 		}
1189 		break;
1190 	default:
1191 		log_error("_tree_action: Action %u not supported.", action);
1192 		goto out;
1193 	}
1194 
1195 	r = 1;
1196 
1197 out:
1198 	dm_tree_free(dtree);
1199 
1200 	return r;
1201 }
1202 
1203 int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
1204 {
1205 	if (!_tree_action(dm, lv, ACTIVATE))
1206 		return_0;
1207 
1208 	return _tree_action(dm, lv, CLEAN);
1209 }
1210 
1211 int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
1212 {
1213 	/* FIXME Update the pvmove implementation! */
1214 	if ((lv->status & PVMOVE) || (lv->status & LOCKED))
1215 		return 1;
1216 
1217 	return _tree_action(dm, lv, PRELOAD);
1218 }
1219 
1220 int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
1221 {
1222 	int r;
1223 
1224 	r = _tree_action(dm, lv, DEACTIVATE);
1225 
1226 	fs_del_lv(lv);
1227 
1228 	return r;
1229 }
1230 
1231 int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
1232 			int lockfs)
1233 {
1234 	return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
1235 }
1236 
1237 /*
1238  * Does device use VG somewhere in its construction?
1239  * Returns 1 if uncertain.
1240  */
1241 int dev_manager_device_uses_vg(struct device *dev,
1242 			       struct volume_group *vg)
1243 {
1244 	struct dm_tree *dtree;
1245 	struct dm_tree_node *root;
1246 	char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1] __attribute((aligned(8)));
1247 	int r = 1;
1248 
1249 	if (!(dtree = dm_tree_create())) {
1250 		log_error("partial dtree creation failed");
1251 		return r;
1252 	}
1253 
1254 	if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
1255 		log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
1256 			  dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
1257 		goto out;
1258 	}
1259 
1260 	memcpy(dlid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
1261 	memcpy(dlid + sizeof(UUID_PREFIX) - 1, &vg->id.uuid[0], sizeof(vg->id));
1262 
1263 	if (!(root = dm_tree_find_node(dtree, 0, 0))) {
1264 		log_error("Lost dependency tree root node");
1265 		goto out;
1266 	}
1267 
1268 	if (dm_tree_children_use_uuid(root, dlid, sizeof(UUID_PREFIX) + sizeof(vg->id) - 1))
1269 		goto_out;
1270 
1271 	r = 0;
1272 
1273 out:
1274 	dm_tree_free(dtree);
1275 	return r;
1276 }
1277