Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / striped / striped.c
blob02a38b10e1b08e7088ca7039ca25faa097a6ceac
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
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"
32 static const char *_striped_name(const struct lv_segment *seg)
34 return (seg->area_count == 1) ? "linear" : seg->segtype->name;
37 static void _striped_display(const struct lv_segment *seg)
39 uint32_t s;
41 if (seg->area_count == 1)
42 display_stripe(seg, 0, " ");
43 else {
44 log_print(" Stripes\t\t%u", seg->area_count);
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);
54 for (s = 0; s < seg->area_count; s++) {
55 log_print(" Stripe %d:", s);
56 display_stripe(seg, s, " ");
59 log_print(" ");
62 static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
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;
70 return 1;
73 static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
74 struct dm_hash_table *pv_hash)
76 struct config_node *cn;
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;
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;
91 seg->area_len /= seg->area_count;
93 return text_import_areas(seg, sn, cn, pv_hash, 0);
96 static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
99 outf(f, "stripe_count = %u%s", seg->area_count,
100 (seg->area_count == 1) ? "\t# linear" : "");
102 if (seg->area_count > 1)
103 out_size(f, (uint64_t) seg->stripe_size,
104 "stripe_size = %u", seg->stripe_size);
106 return out_areas(f, seg, "stripe");
110 * Test whether two segments could be merged by the current merging code
112 static int _striped_segments_compatible(struct lv_segment *first,
113 struct lv_segment *second)
115 uint32_t width;
116 unsigned s;
118 if ((first->area_count != second->area_count) ||
119 (first->stripe_size != second->stripe_size))
120 return 0;
122 for (s = 0; s < first->area_count; s++) {
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;
130 width = first->area_len;
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;
139 if (!str_list_lists_equal(&first->tags, &second->tags))
140 return 0;
142 return 1;
145 static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
147 uint32_t s;
149 if (!_striped_segments_compatible(seg1, seg2))
150 return 0;
152 seg1->len += seg2->len;
153 seg1->area_len += seg2->area_len;
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));
160 return 1;
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)))
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;
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;
184 return add_areas_line(dm, seg, node, 0u, seg->area_count);
187 static int _striped_target_present(struct cmd_context *cmd,
188 const struct lv_segment *seg __attribute((unused)),
189 unsigned *attributes __attribute((unused)))
191 static int _striped_checked = 0;
192 static int _striped_present = 0;
194 if (!_striped_checked)
195 _striped_present = target_present(cmd, "linear", 0) &&
196 target_present(cmd, "striped", 0);
198 _striped_checked = 1;
200 return _striped_present;
202 #endif
204 static void _striped_destroy(const struct segment_type *segtype)
206 dm_free((void *)segtype);
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,
223 struct segment_type *init_striped_segtype(struct cmd_context *cmd)
225 struct segment_type *segtype = dm_malloc(sizeof(*segtype));
227 if (!segtype)
228 return_NULL;
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;
237 log_very_verbose("Initialised segtype: %s", segtype->name);
239 return segtype;