xref: /dflybsd-src/contrib/lvm2/dist/lib/striped/striped.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*	$NetBSD: striped.c,v 1.1.1.2 2009/12/02 00:26:47 haad Exp $	*/
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino /*
486d7f5d3SJohn Marino  * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
586d7f5d3SJohn Marino  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  * This file is part of LVM2.
886d7f5d3SJohn Marino  *
986d7f5d3SJohn Marino  * This copyrighted material is made available to anyone wishing to use,
1086d7f5d3SJohn Marino  * modify, copy, or redistribute it subject to the terms and conditions
1186d7f5d3SJohn Marino  * of the GNU Lesser General Public License v.2.1.
1286d7f5d3SJohn Marino  *
1386d7f5d3SJohn Marino  * You should have received a copy of the GNU Lesser General Public License
1486d7f5d3SJohn Marino  * along with this program; if not, write to the Free Software Foundation,
1586d7f5d3SJohn Marino  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1686d7f5d3SJohn Marino  */
1786d7f5d3SJohn Marino 
1886d7f5d3SJohn Marino #include "lib.h"
1986d7f5d3SJohn Marino #include "toolcontext.h"
2086d7f5d3SJohn Marino #include "segtype.h"
2186d7f5d3SJohn Marino #include "display.h"
2286d7f5d3SJohn Marino #include "text_export.h"
2386d7f5d3SJohn Marino #include "text_import.h"
2486d7f5d3SJohn Marino #include "config.h"
2586d7f5d3SJohn Marino #include "str_list.h"
2686d7f5d3SJohn Marino #include "targets.h"
2786d7f5d3SJohn Marino #include "lvm-string.h"
2886d7f5d3SJohn Marino #include "activate.h"
2986d7f5d3SJohn Marino #include "pv_alloc.h"
3086d7f5d3SJohn Marino #include "metadata.h"
3186d7f5d3SJohn Marino 
_striped_name(const struct lv_segment * seg)3286d7f5d3SJohn Marino static const char *_striped_name(const struct lv_segment *seg)
3386d7f5d3SJohn Marino {
3486d7f5d3SJohn Marino 	return (seg->area_count == 1) ? "linear" : seg->segtype->name;
3586d7f5d3SJohn Marino }
3686d7f5d3SJohn Marino 
_striped_display(const struct lv_segment * seg)3786d7f5d3SJohn Marino static void _striped_display(const struct lv_segment *seg)
3886d7f5d3SJohn Marino {
3986d7f5d3SJohn Marino 	uint32_t s;
4086d7f5d3SJohn Marino 
4186d7f5d3SJohn Marino 	if (seg->area_count == 1)
4286d7f5d3SJohn Marino 		display_stripe(seg, 0, "  ");
4386d7f5d3SJohn Marino 	else {
4486d7f5d3SJohn Marino 		log_print("  Stripes\t\t%u", seg->area_count);
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino 		if (seg->lv->vg->cmd->si_unit_consistency)
4786d7f5d3SJohn Marino 			log_print("  Stripe size\t\t%s",
4886d7f5d3SJohn Marino 				  display_size(seg->lv->vg->cmd,
4986d7f5d3SJohn Marino 					       (uint64_t) seg->stripe_size));
5086d7f5d3SJohn Marino 		else
5186d7f5d3SJohn Marino 			log_print("  Stripe size\t\t%u KB",
5286d7f5d3SJohn Marino 				  seg->stripe_size / 2);
5386d7f5d3SJohn Marino 
5486d7f5d3SJohn Marino 		for (s = 0; s < seg->area_count; s++) {
5586d7f5d3SJohn Marino 			log_print("  Stripe %d:", s);
5686d7f5d3SJohn Marino 			display_stripe(seg, s, "    ");
5786d7f5d3SJohn Marino 		}
5886d7f5d3SJohn Marino 	}
5986d7f5d3SJohn Marino 	log_print(" ");
6086d7f5d3SJohn Marino }
6186d7f5d3SJohn Marino 
_striped_text_import_area_count(struct config_node * sn,uint32_t * area_count)6286d7f5d3SJohn Marino static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
6386d7f5d3SJohn Marino {
6486d7f5d3SJohn Marino 	if (!get_config_uint32(sn, "stripe_count", area_count)) {
6586d7f5d3SJohn Marino 		log_error("Couldn't read 'stripe_count' for "
6686d7f5d3SJohn Marino 			  "segment '%s'.", config_parent_name(sn));
6786d7f5d3SJohn Marino 		return 0;
6886d7f5d3SJohn Marino 	}
6986d7f5d3SJohn Marino 
7086d7f5d3SJohn Marino 	return 1;
7186d7f5d3SJohn Marino }
7286d7f5d3SJohn Marino 
_striped_text_import(struct lv_segment * seg,const struct config_node * sn,struct dm_hash_table * pv_hash)7386d7f5d3SJohn Marino static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
7486d7f5d3SJohn Marino 			struct dm_hash_table *pv_hash)
7586d7f5d3SJohn Marino {
7686d7f5d3SJohn Marino 	struct config_node *cn;
7786d7f5d3SJohn Marino 
7886d7f5d3SJohn Marino 	if ((seg->area_count != 1) &&
7986d7f5d3SJohn Marino 	    !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) {
8086d7f5d3SJohn Marino 		log_error("Couldn't read stripe_size for segment %s "
8186d7f5d3SJohn Marino 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
8286d7f5d3SJohn Marino 		return 0;
8386d7f5d3SJohn Marino 	}
8486d7f5d3SJohn Marino 
8586d7f5d3SJohn Marino 	if (!(cn = find_config_node(sn, "stripes"))) {
8686d7f5d3SJohn Marino 		log_error("Couldn't find stripes array for segment %s "
8786d7f5d3SJohn Marino 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
8886d7f5d3SJohn Marino 		return 0;
8986d7f5d3SJohn Marino 	}
9086d7f5d3SJohn Marino 
9186d7f5d3SJohn Marino 	seg->area_len /= seg->area_count;
9286d7f5d3SJohn Marino 
9386d7f5d3SJohn Marino 	return text_import_areas(seg, sn, cn, pv_hash, 0);
9486d7f5d3SJohn Marino }
9586d7f5d3SJohn Marino 
_striped_text_export(const struct lv_segment * seg,struct formatter * f)9686d7f5d3SJohn Marino static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
9786d7f5d3SJohn Marino {
9886d7f5d3SJohn Marino 
9986d7f5d3SJohn Marino 	outf(f, "stripe_count = %u%s", seg->area_count,
10086d7f5d3SJohn Marino 	     (seg->area_count == 1) ? "\t# linear" : "");
10186d7f5d3SJohn Marino 
10286d7f5d3SJohn Marino 	if (seg->area_count > 1)
10386d7f5d3SJohn Marino 		out_size(f, (uint64_t) seg->stripe_size,
10486d7f5d3SJohn Marino 			 "stripe_size = %u", seg->stripe_size);
10586d7f5d3SJohn Marino 
10686d7f5d3SJohn Marino 	return out_areas(f, seg, "stripe");
10786d7f5d3SJohn Marino }
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino /*
11086d7f5d3SJohn Marino  * Test whether two segments could be merged by the current merging code
11186d7f5d3SJohn Marino  */
_striped_segments_compatible(struct lv_segment * first,struct lv_segment * second)11286d7f5d3SJohn Marino static int _striped_segments_compatible(struct lv_segment *first,
11386d7f5d3SJohn Marino 				struct lv_segment *second)
11486d7f5d3SJohn Marino {
11586d7f5d3SJohn Marino 	uint32_t width;
11686d7f5d3SJohn Marino 	unsigned s;
11786d7f5d3SJohn Marino 
11886d7f5d3SJohn Marino 	if ((first->area_count != second->area_count) ||
11986d7f5d3SJohn Marino 	    (first->stripe_size != second->stripe_size))
12086d7f5d3SJohn Marino 		return 0;
12186d7f5d3SJohn Marino 
12286d7f5d3SJohn Marino 	for (s = 0; s < first->area_count; s++) {
12386d7f5d3SJohn Marino 
12486d7f5d3SJohn Marino 		/* FIXME Relax this to first area type != second area type */
12586d7f5d3SJohn Marino 		/*       plus the additional AREA_LV checks needed */
12686d7f5d3SJohn Marino 		if ((seg_type(first, s) != AREA_PV) ||
12786d7f5d3SJohn Marino 		    (seg_type(second, s) != AREA_PV))
12886d7f5d3SJohn Marino 			return 0;
12986d7f5d3SJohn Marino 
13086d7f5d3SJohn Marino 		width = first->area_len;
13186d7f5d3SJohn Marino 
13286d7f5d3SJohn Marino 		if ((seg_pv(first, s) !=
13386d7f5d3SJohn Marino 		     seg_pv(second, s)) ||
13486d7f5d3SJohn Marino 		    (seg_pe(first, s) + width !=
13586d7f5d3SJohn Marino 		     seg_pe(second, s)))
13686d7f5d3SJohn Marino 			return 0;
13786d7f5d3SJohn Marino 	}
13886d7f5d3SJohn Marino 
13986d7f5d3SJohn Marino 	if (!str_list_lists_equal(&first->tags, &second->tags))
14086d7f5d3SJohn Marino 		return 0;
14186d7f5d3SJohn Marino 
14286d7f5d3SJohn Marino 	return 1;
14386d7f5d3SJohn Marino }
14486d7f5d3SJohn Marino 
_striped_merge_segments(struct lv_segment * seg1,struct lv_segment * seg2)14586d7f5d3SJohn Marino static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
14686d7f5d3SJohn Marino {
14786d7f5d3SJohn Marino 	uint32_t s;
14886d7f5d3SJohn Marino 
14986d7f5d3SJohn Marino 	if (!_striped_segments_compatible(seg1, seg2))
15086d7f5d3SJohn Marino 		return 0;
15186d7f5d3SJohn Marino 
15286d7f5d3SJohn Marino 	seg1->len += seg2->len;
15386d7f5d3SJohn Marino 	seg1->area_len += seg2->area_len;
15486d7f5d3SJohn Marino 
15586d7f5d3SJohn Marino 	for (s = 0; s < seg1->area_count; s++)
15686d7f5d3SJohn Marino 		if (seg_type(seg1, s) == AREA_PV)
15786d7f5d3SJohn Marino 			merge_pv_segments(seg_pvseg(seg1, s),
15886d7f5d3SJohn Marino 					  seg_pvseg(seg2, s));
15986d7f5d3SJohn Marino 
16086d7f5d3SJohn Marino 	return 1;
16186d7f5d3SJohn Marino }
16286d7f5d3SJohn Marino 
16386d7f5d3SJohn Marino #ifdef DEVMAPPER_SUPPORT
_striped_add_target_line(struct dev_manager * dm,struct dm_pool * mem __attribute ((unused)),struct cmd_context * cmd __attribute ((unused)),void ** target_state __attribute ((unused)),struct lv_segment * seg,struct dm_tree_node * node,uint64_t len,uint32_t * pvmove_mirror_count __attribute ((unused)))16486d7f5d3SJohn Marino static int _striped_add_target_line(struct dev_manager *dm,
16586d7f5d3SJohn Marino 				struct dm_pool *mem __attribute((unused)),
16686d7f5d3SJohn Marino 				struct cmd_context *cmd __attribute((unused)),
16786d7f5d3SJohn Marino 				void **target_state __attribute((unused)),
16886d7f5d3SJohn Marino 				struct lv_segment *seg,
16986d7f5d3SJohn Marino 				struct dm_tree_node *node, uint64_t len,
17086d7f5d3SJohn Marino 				uint32_t *pvmove_mirror_count __attribute((unused)))
17186d7f5d3SJohn Marino {
17286d7f5d3SJohn Marino 	if (!seg->area_count) {
17386d7f5d3SJohn Marino 		log_error("Internal error: striped add_target_line called "
17486d7f5d3SJohn Marino 			  "with no areas for %s.", seg->lv->name);
17586d7f5d3SJohn Marino 		return 0;
17686d7f5d3SJohn Marino 	}
17786d7f5d3SJohn Marino 	if (seg->area_count == 1) {
17886d7f5d3SJohn Marino 		if (!dm_tree_node_add_linear_target(node, len))
17986d7f5d3SJohn Marino 			return_0;
18086d7f5d3SJohn Marino 	} else if (!dm_tree_node_add_striped_target(node, len,
18186d7f5d3SJohn Marino 						  seg->stripe_size))
18286d7f5d3SJohn Marino 		return_0;
18386d7f5d3SJohn Marino 
18486d7f5d3SJohn Marino 	return add_areas_line(dm, seg, node, 0u, seg->area_count);
18586d7f5d3SJohn Marino }
18686d7f5d3SJohn Marino 
_striped_target_present(struct cmd_context * cmd,const struct lv_segment * seg __attribute ((unused)),unsigned * attributes __attribute ((unused)))18786d7f5d3SJohn Marino static int _striped_target_present(struct cmd_context *cmd,
18886d7f5d3SJohn Marino 				   const struct lv_segment *seg __attribute((unused)),
18986d7f5d3SJohn Marino 				   unsigned *attributes __attribute((unused)))
19086d7f5d3SJohn Marino {
19186d7f5d3SJohn Marino 	static int _striped_checked = 0;
19286d7f5d3SJohn Marino 	static int _striped_present = 0;
19386d7f5d3SJohn Marino 
19486d7f5d3SJohn Marino 	if (!_striped_checked)
19586d7f5d3SJohn Marino 		_striped_present = target_present(cmd, "linear", 0) &&
19686d7f5d3SJohn Marino 			  target_present(cmd, "striped", 0);
19786d7f5d3SJohn Marino 
19886d7f5d3SJohn Marino 	_striped_checked = 1;
19986d7f5d3SJohn Marino 
20086d7f5d3SJohn Marino 	return _striped_present;
20186d7f5d3SJohn Marino }
20286d7f5d3SJohn Marino #endif
20386d7f5d3SJohn Marino 
_striped_destroy(const struct segment_type * segtype)20486d7f5d3SJohn Marino static void _striped_destroy(const struct segment_type *segtype)
20586d7f5d3SJohn Marino {
20686d7f5d3SJohn Marino 	dm_free((void *)segtype);
20786d7f5d3SJohn Marino }
20886d7f5d3SJohn Marino 
20986d7f5d3SJohn Marino static struct segtype_handler _striped_ops = {
21086d7f5d3SJohn Marino 	.name = _striped_name,
21186d7f5d3SJohn Marino 	.display = _striped_display,
21286d7f5d3SJohn Marino 	.text_import_area_count = _striped_text_import_area_count,
21386d7f5d3SJohn Marino 	.text_import = _striped_text_import,
21486d7f5d3SJohn Marino 	.text_export = _striped_text_export,
21586d7f5d3SJohn Marino 	.merge_segments = _striped_merge_segments,
21686d7f5d3SJohn Marino #ifdef DEVMAPPER_SUPPORT
21786d7f5d3SJohn Marino 	.add_target_line = _striped_add_target_line,
21886d7f5d3SJohn Marino 	.target_present = _striped_target_present,
21986d7f5d3SJohn Marino #endif
22086d7f5d3SJohn Marino 	.destroy = _striped_destroy,
22186d7f5d3SJohn Marino };
22286d7f5d3SJohn Marino 
init_striped_segtype(struct cmd_context * cmd)22386d7f5d3SJohn Marino struct segment_type *init_striped_segtype(struct cmd_context *cmd)
22486d7f5d3SJohn Marino {
22586d7f5d3SJohn Marino 	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
22686d7f5d3SJohn Marino 
22786d7f5d3SJohn Marino 	if (!segtype)
22886d7f5d3SJohn Marino 		return_NULL;
22986d7f5d3SJohn Marino 
23086d7f5d3SJohn Marino 	segtype->cmd = cmd;
23186d7f5d3SJohn Marino 	segtype->ops = &_striped_ops;
23286d7f5d3SJohn Marino 	segtype->name = "striped";
23386d7f5d3SJohn Marino 	segtype->private = NULL;
23486d7f5d3SJohn Marino 	segtype->flags =
23586d7f5d3SJohn Marino 	    SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
23686d7f5d3SJohn Marino 
23786d7f5d3SJohn Marino 	log_very_verbose("Initialised segtype: %s", segtype->name);
23886d7f5d3SJohn Marino 
23986d7f5d3SJohn Marino 	return segtype;
24086d7f5d3SJohn Marino }
241