Home | History | Annotate | Line # | Download | only in striped
      1 /*	$NetBSD: striped.c,v 1.1.1.2 2009/12/02 00:26:47 haad Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2003-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 "toolcontext.h"
     20 #include "segtype.h"
     21 #include "display.h"
     22 #include "text_export.h"
     23 #include "text_import.h"
     24 #include "config.h"
     25 #include "str_list.h"
     26 #include "targets.h"
     27 #include "lvm-string.h"
     28 #include "activate.h"
     29 #include "pv_alloc.h"
     30 #include "metadata.h"
     31 
     32 static const char *_striped_name(const struct lv_segment *seg)
     33 {
     34 	return (seg->area_count == 1) ? "linear" : seg->segtype->name;
     35 }
     36 
     37 static void _striped_display(const struct lv_segment *seg)
     38 {
     39 	uint32_t s;
     40 
     41 	if (seg->area_count == 1)
     42 		display_stripe(seg, 0, "  ");
     43 	else {
     44 		log_print("  Stripes\t\t%u", seg->area_count);
     45 
     46 		if (seg->lv->vg->cmd->si_unit_consistency)
     47 			log_print("  Stripe size\t\t%s",
     48 				  display_size(seg->lv->vg->cmd,
     49 					       (uint64_t) seg->stripe_size));
     50 		else
     51 			log_print("  Stripe size\t\t%u KB",
     52 				  seg->stripe_size / 2);
     53 
     54 		for (s = 0; s < seg->area_count; s++) {
     55 			log_print("  Stripe %d:", s);
     56 			display_stripe(seg, s, "    ");
     57 		}
     58 	}
     59 	log_print(" ");
     60 }
     61 
     62 static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
     63 {
     64 	if (!get_config_uint32(sn, "stripe_count", area_count)) {
     65 		log_error("Couldn't read 'stripe_count' for "
     66 			  "segment '%s'.", config_parent_name(sn));
     67 		return 0;
     68 	}
     69 
     70 	return 1;
     71 }
     72 
     73 static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
     74 			struct dm_hash_table *pv_hash)
     75 {
     76 	struct config_node *cn;
     77 
     78 	if ((seg->area_count != 1) &&
     79 	    !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) {
     80 		log_error("Couldn't read stripe_size for segment %s "
     81 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
     82 		return 0;
     83 	}
     84 
     85 	if (!(cn = find_config_node(sn, "stripes"))) {
     86 		log_error("Couldn't find stripes array for segment %s "
     87 			  "of logical volume %s.", config_parent_name(sn), seg->lv->name);
     88 		return 0;
     89 	}
     90 
     91 	seg->area_len /= seg->area_count;
     92 
     93 	return text_import_areas(seg, sn, cn, pv_hash, 0);
     94 }
     95 
     96 static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
     97 {
     98 
     99 	outf(f, "stripe_count = %u%s", seg->area_count,
    100 	     (seg->area_count == 1) ? "\t# linear" : "");
    101 
    102 	if (seg->area_count > 1)
    103 		out_size(f, (uint64_t) seg->stripe_size,
    104 			 "stripe_size = %u", seg->stripe_size);
    105 
    106 	return out_areas(f, seg, "stripe");
    107 }
    108 
    109 /*
    110  * Test whether two segments could be merged by the current merging code
    111  */
    112 static int _striped_segments_compatible(struct lv_segment *first,
    113 				struct lv_segment *second)
    114 {
    115 	uint32_t width;
    116 	unsigned s;
    117 
    118 	if ((first->area_count != second->area_count) ||
    119 	    (first->stripe_size != second->stripe_size))
    120 		return 0;
    121 
    122 	for (s = 0; s < first->area_count; s++) {
    123 
    124 		/* FIXME Relax this to first area type != second area type */
    125 		/*       plus the additional AREA_LV checks needed */
    126 		if ((seg_type(first, s) != AREA_PV) ||
    127 		    (seg_type(second, s) != AREA_PV))
    128 			return 0;
    129 
    130 		width = first->area_len;
    131 
    132 		if ((seg_pv(first, s) !=
    133 		     seg_pv(second, s)) ||
    134 		    (seg_pe(first, s) + width !=
    135 		     seg_pe(second, s)))
    136 			return 0;
    137 	}
    138 
    139 	if (!str_list_lists_equal(&first->tags, &second->tags))
    140 		return 0;
    141 
    142 	return 1;
    143 }
    144 
    145 static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
    146 {
    147 	uint32_t s;
    148 
    149 	if (!_striped_segments_compatible(seg1, seg2))
    150 		return 0;
    151 
    152 	seg1->len += seg2->len;
    153 	seg1->area_len += seg2->area_len;
    154 
    155 	for (s = 0; s < seg1->area_count; s++)
    156 		if (seg_type(seg1, s) == AREA_PV)
    157 			merge_pv_segments(seg_pvseg(seg1, s),
    158 					  seg_pvseg(seg2, s));
    159 
    160 	return 1;
    161 }
    162 
    163 #ifdef DEVMAPPER_SUPPORT
    164 static int _striped_add_target_line(struct dev_manager *dm,
    165 				struct dm_pool *mem __attribute((unused)),
    166 				struct cmd_context *cmd __attribute((unused)),
    167 				void **target_state __attribute((unused)),
    168 				struct lv_segment *seg,
    169 				struct dm_tree_node *node, uint64_t len,
    170 				uint32_t *pvmove_mirror_count __attribute((unused)))
    171 {
    172 	if (!seg->area_count) {
    173 		log_error("Internal error: striped add_target_line called "
    174 			  "with no areas for %s.", seg->lv->name);
    175 		return 0;
    176 	}
    177 	if (seg->area_count == 1) {
    178 		if (!dm_tree_node_add_linear_target(node, len))
    179 			return_0;
    180 	} else if (!dm_tree_node_add_striped_target(node, len,
    181 						  seg->stripe_size))
    182 		return_0;
    183 
    184 	return add_areas_line(dm, seg, node, 0u, seg->area_count);
    185 }
    186 
    187 static int _striped_target_present(struct cmd_context *cmd,
    188 				   const struct lv_segment *seg __attribute((unused)),
    189 				   unsigned *attributes __attribute((unused)))
    190 {
    191 	static int _striped_checked = 0;
    192 	static int _striped_present = 0;
    193 
    194 	if (!_striped_checked)
    195 		_striped_present = target_present(cmd, "linear", 0) &&
    196 			  target_present(cmd, "striped", 0);
    197 
    198 	_striped_checked = 1;
    199 
    200 	return _striped_present;
    201 }
    202 #endif
    203 
    204 static void _striped_destroy(const struct segment_type *segtype)
    205 {
    206 	dm_free((void *)segtype);
    207 }
    208 
    209 static struct segtype_handler _striped_ops = {
    210 	.name = _striped_name,
    211 	.display = _striped_display,
    212 	.text_import_area_count = _striped_text_import_area_count,
    213 	.text_import = _striped_text_import,
    214 	.text_export = _striped_text_export,
    215 	.merge_segments = _striped_merge_segments,
    216 #ifdef DEVMAPPER_SUPPORT
    217 	.add_target_line = _striped_add_target_line,
    218 	.target_present = _striped_target_present,
    219 #endif
    220 	.destroy = _striped_destroy,
    221 };
    222 
    223 struct segment_type *init_striped_segtype(struct cmd_context *cmd)
    224 {
    225 	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
    226 
    227 	if (!segtype)
    228 		return_NULL;
    229 
    230 	segtype->cmd = cmd;
    231 	segtype->ops = &_striped_ops;
    232 	segtype->name = "striped";
    233 	segtype->private = NULL;
    234 	segtype->flags =
    235 	    SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT;
    236 
    237 	log_very_verbose("Initialised segtype: %s", segtype->name);
    238 
    239 	return segtype;
    240 }
    241