xref: /netbsd-src/external/gpl2/lvm2/dist/lib/striped/striped.c (revision 7c604eea85b4f330dc75ffe65e947f4d73758aa0)
1*7c604eeaShaad /*	$NetBSD: striped.c,v 1.1.1.2 2009/12/02 00:26:47 haad Exp $	*/
256a34939Shaad 
356a34939Shaad /*
456a34939Shaad  * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
656a34939Shaad  *
756a34939Shaad  * This file is part of LVM2.
856a34939Shaad  *
956a34939Shaad  * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad  * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad  * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad  *
1356a34939Shaad  * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad  * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1656a34939Shaad  */
1756a34939Shaad 
1856a34939Shaad #include "lib.h"
1956a34939Shaad #include "toolcontext.h"
2056a34939Shaad #include "segtype.h"
2156a34939Shaad #include "display.h"
2256a34939Shaad #include "text_export.h"
2356a34939Shaad #include "text_import.h"
2456a34939Shaad #include "config.h"
2556a34939Shaad #include "str_list.h"
2656a34939Shaad #include "targets.h"
2756a34939Shaad #include "lvm-string.h"
2856a34939Shaad #include "activate.h"
2956a34939Shaad #include "pv_alloc.h"
3056a34939Shaad #include "metadata.h"
3156a34939Shaad 
_striped_name(const struct lv_segment * seg)3256a34939Shaad static const char *_striped_name(const struct lv_segment *seg)
3356a34939Shaad {
3456a34939Shaad 	return (seg->area_count == 1) ? "linear" : seg->segtype->name;
3556a34939Shaad }
3656a34939Shaad 
_striped_display(const struct lv_segment * seg)3756a34939Shaad static void _striped_display(const struct lv_segment *seg)
3856a34939Shaad {
3956a34939Shaad 	uint32_t s;
4056a34939Shaad 
4156a34939Shaad 	if (seg->area_count == 1)
4256a34939Shaad 		display_stripe(seg, 0, "  ");
4356a34939Shaad 	else {
4456a34939Shaad 		log_print("  Stripes\t\t%u", seg->area_count);
45*7c604eeaShaad 
46*7c604eeaShaad 		if (seg->lv->vg->cmd->si_unit_consistency)
47*7c604eeaShaad 			log_print("  Stripe size\t\t%s",
48*7c604eeaShaad 				  display_size(seg->lv->vg->cmd,
49*7c604eeaShaad 					       (uint64_t) seg->stripe_size));
50*7c604eeaShaad 		else
51*7c604eeaShaad 			log_print("  Stripe size\t\t%u KB",
52*7c604eeaShaad 				  seg->stripe_size / 2);
5356a34939Shaad 
5456a34939Shaad 		for (s = 0; s < seg->area_count; s++) {
5556a34939Shaad 			log_print("  Stripe %d:", s);
5656a34939Shaad 			display_stripe(seg, s, "    ");
5756a34939Shaad 		}
5856a34939Shaad 	}
5956a34939Shaad 	log_print(" ");
6056a34939Shaad }
6156a34939Shaad 
_striped_text_import_area_count(struct config_node * sn,uint32_t * area_count)6256a34939Shaad static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
6356a34939Shaad {
6456a34939Shaad 	if (!get_config_uint32(sn, "stripe_count", area_count)) {
6556a34939Shaad 		log_error("Couldn't read 'stripe_count' for "
66*7c604eeaShaad 			  "segment '%s'.", config_parent_name(sn));
6756a34939Shaad 		return 0;
6856a34939Shaad 	}
6956a34939Shaad 
7056a34939Shaad 	return 1;
7156a34939Shaad }
7256a34939Shaad 
_striped_text_import(struct lv_segment * seg,const struct config_node * sn,struct dm_hash_table * pv_hash)7356a34939Shaad static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
7456a34939Shaad 			struct dm_hash_table *pv_hash)
7556a34939Shaad {
7656a34939Shaad 	struct config_node *cn;
7756a34939Shaad 
7856a34939Shaad 	if ((seg->area_count != 1) &&
7956a34939Shaad 	    !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) {
80*7c604eeaShaad 		log_error("Couldn't read stripe_size for segment %s "
81*7c604eeaShaad 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
8256a34939Shaad 		return 0;
8356a34939Shaad 	}
8456a34939Shaad 
8556a34939Shaad 	if (!(cn = find_config_node(sn, "stripes"))) {
86*7c604eeaShaad 		log_error("Couldn't find stripes array for segment %s "
87*7c604eeaShaad 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
8856a34939Shaad 		return 0;
8956a34939Shaad 	}
9056a34939Shaad 
9156a34939Shaad 	seg->area_len /= seg->area_count;
9256a34939Shaad 
9356a34939Shaad 	return text_import_areas(seg, sn, cn, pv_hash, 0);
9456a34939Shaad }
9556a34939Shaad 
_striped_text_export(const struct lv_segment * seg,struct formatter * f)9656a34939Shaad static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
9756a34939Shaad {
9856a34939Shaad 
9956a34939Shaad 	outf(f, "stripe_count = %u%s", seg->area_count,
10056a34939Shaad 	     (seg->area_count == 1) ? "\t# linear" : "");
10156a34939Shaad 
10256a34939Shaad 	if (seg->area_count > 1)
10356a34939Shaad 		out_size(f, (uint64_t) seg->stripe_size,
10456a34939Shaad 			 "stripe_size = %u", seg->stripe_size);
10556a34939Shaad 
10656a34939Shaad 	return out_areas(f, seg, "stripe");
10756a34939Shaad }
10856a34939Shaad 
10956a34939Shaad /*
11056a34939Shaad  * Test whether two segments could be merged by the current merging code
11156a34939Shaad  */
_striped_segments_compatible(struct lv_segment * first,struct lv_segment * second)11256a34939Shaad static int _striped_segments_compatible(struct lv_segment *first,
11356a34939Shaad 				struct lv_segment *second)
11456a34939Shaad {
11556a34939Shaad 	uint32_t width;
11656a34939Shaad 	unsigned s;
11756a34939Shaad 
11856a34939Shaad 	if ((first->area_count != second->area_count) ||
11956a34939Shaad 	    (first->stripe_size != second->stripe_size))
12056a34939Shaad 		return 0;
12156a34939Shaad 
12256a34939Shaad 	for (s = 0; s < first->area_count; s++) {
12356a34939Shaad 
12456a34939Shaad 		/* FIXME Relax this to first area type != second area type */
12556a34939Shaad 		/*       plus the additional AREA_LV checks needed */
12656a34939Shaad 		if ((seg_type(first, s) != AREA_PV) ||
12756a34939Shaad 		    (seg_type(second, s) != AREA_PV))
12856a34939Shaad 			return 0;
12956a34939Shaad 
13056a34939Shaad 		width = first->area_len;
13156a34939Shaad 
13256a34939Shaad 		if ((seg_pv(first, s) !=
13356a34939Shaad 		     seg_pv(second, s)) ||
13456a34939Shaad 		    (seg_pe(first, s) + width !=
13556a34939Shaad 		     seg_pe(second, s)))
13656a34939Shaad 			return 0;
13756a34939Shaad 	}
13856a34939Shaad 
13956a34939Shaad 	if (!str_list_lists_equal(&first->tags, &second->tags))
14056a34939Shaad 		return 0;
14156a34939Shaad 
14256a34939Shaad 	return 1;
14356a34939Shaad }
14456a34939Shaad 
_striped_merge_segments(struct lv_segment * seg1,struct lv_segment * seg2)14556a34939Shaad static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
14656a34939Shaad {
14756a34939Shaad 	uint32_t s;
14856a34939Shaad 
14956a34939Shaad 	if (!_striped_segments_compatible(seg1, seg2))
15056a34939Shaad 		return 0;
15156a34939Shaad 
15256a34939Shaad 	seg1->len += seg2->len;
15356a34939Shaad 	seg1->area_len += seg2->area_len;
15456a34939Shaad 
15556a34939Shaad 	for (s = 0; s < seg1->area_count; s++)
15656a34939Shaad 		if (seg_type(seg1, s) == AREA_PV)
15756a34939Shaad 			merge_pv_segments(seg_pvseg(seg1, s),
15856a34939Shaad 					  seg_pvseg(seg2, s));
15956a34939Shaad 
16056a34939Shaad 	return 1;
16156a34939Shaad }
16256a34939Shaad 
16356a34939Shaad #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)))16456a34939Shaad static int _striped_add_target_line(struct dev_manager *dm,
16556a34939Shaad 				struct dm_pool *mem __attribute((unused)),
16656a34939Shaad 				struct cmd_context *cmd __attribute((unused)),
16756a34939Shaad 				void **target_state __attribute((unused)),
16856a34939Shaad 				struct lv_segment *seg,
16956a34939Shaad 				struct dm_tree_node *node, uint64_t len,
17056a34939Shaad 				uint32_t *pvmove_mirror_count __attribute((unused)))
17156a34939Shaad {
17256a34939Shaad 	if (!seg->area_count) {
17356a34939Shaad 		log_error("Internal error: striped add_target_line called "
17456a34939Shaad 			  "with no areas for %s.", seg->lv->name);
17556a34939Shaad 		return 0;
17656a34939Shaad 	}
17756a34939Shaad 	if (seg->area_count == 1) {
17856a34939Shaad 		if (!dm_tree_node_add_linear_target(node, len))
17956a34939Shaad 			return_0;
18056a34939Shaad 	} else if (!dm_tree_node_add_striped_target(node, len,
18156a34939Shaad 						  seg->stripe_size))
18256a34939Shaad 		return_0;
18356a34939Shaad 
18456a34939Shaad 	return add_areas_line(dm, seg, node, 0u, seg->area_count);
18556a34939Shaad }
18656a34939Shaad 
_striped_target_present(struct cmd_context * cmd,const struct lv_segment * seg __attribute ((unused)),unsigned * attributes __attribute ((unused)))187*7c604eeaShaad static int _striped_target_present(struct cmd_context *cmd,
188*7c604eeaShaad 				   const struct lv_segment *seg __attribute((unused)),
18956a34939Shaad 				   unsigned *attributes __attribute((unused)))
19056a34939Shaad {
19156a34939Shaad 	static int _striped_checked = 0;
19256a34939Shaad 	static int _striped_present = 0;
19356a34939Shaad 
19456a34939Shaad 	if (!_striped_checked)
195*7c604eeaShaad 		_striped_present = target_present(cmd, "linear", 0) &&
196*7c604eeaShaad 			  target_present(cmd, "striped", 0);
19756a34939Shaad 
19856a34939Shaad 	_striped_checked = 1;
19956a34939Shaad 
20056a34939Shaad 	return _striped_present;
20156a34939Shaad }
20256a34939Shaad #endif
20356a34939Shaad 
_striped_destroy(const struct segment_type * segtype)20456a34939Shaad static void _striped_destroy(const struct segment_type *segtype)
20556a34939Shaad {
20656a34939Shaad 	dm_free((void *)segtype);
20756a34939Shaad }
20856a34939Shaad 
20956a34939Shaad static struct segtype_handler _striped_ops = {
21056a34939Shaad 	.name = _striped_name,
21156a34939Shaad 	.display = _striped_display,
21256a34939Shaad 	.text_import_area_count = _striped_text_import_area_count,
21356a34939Shaad 	.text_import = _striped_text_import,
21456a34939Shaad 	.text_export = _striped_text_export,
21556a34939Shaad 	.merge_segments = _striped_merge_segments,
21656a34939Shaad #ifdef DEVMAPPER_SUPPORT
21756a34939Shaad 	.add_target_line = _striped_add_target_line,
21856a34939Shaad 	.target_present = _striped_target_present,
21956a34939Shaad #endif
22056a34939Shaad 	.destroy = _striped_destroy,
22156a34939Shaad };
22256a34939Shaad 
init_striped_segtype(struct cmd_context * cmd)22356a34939Shaad struct segment_type *init_striped_segtype(struct cmd_context *cmd)
22456a34939Shaad {
22556a34939Shaad 	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
22656a34939Shaad 
22756a34939Shaad 	if (!segtype)
22856a34939Shaad 		return_NULL;
22956a34939Shaad 
23056a34939Shaad 	segtype->cmd = cmd;
23156a34939Shaad 	segtype->ops = &_striped_ops;
23256a34939Shaad 	segtype->name = "striped";
23356a34939Shaad 	segtype->private = NULL;
23456a34939Shaad 	segtype->flags =
23556a34939Shaad 	    SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
23656a34939Shaad 
23756a34939Shaad 	log_very_verbose("Initialised segtype: %s", segtype->name);
23856a34939Shaad 
23956a34939Shaad 	return segtype;
24056a34939Shaad }
241