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
19 #include "toolcontext.h"
22 #include "text_export.h"
23 #include "text_import.h"
27 #include "lvm-string.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
)
41 if (seg
->area_count
== 1)
42 display_stripe(seg
, 0, " ");
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
));
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
, " ");
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
));
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
);
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
);
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
)
118 if ((first
->area_count
!= second
->area_count
) ||
119 (first
->stripe_size
!= second
->stripe_size
))
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
))
130 width
= first
->area_len
;
132 if ((seg_pv(first
, s
) !=
133 seg_pv(second
, s
)) ||
134 (seg_pe(first
, s
) + width
!=
139 if (!str_list_lists_equal(&first
->tags
, &second
->tags
))
145 static int _striped_merge_segments(struct lv_segment
*seg1
, struct lv_segment
*seg2
)
149 if (!_striped_segments_compatible(seg1
, seg2
))
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
),
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
);
177 if (seg
->area_count
== 1) {
178 if (!dm_tree_node_add_linear_target(node
, len
))
180 } else if (!dm_tree_node_add_striped_target(node
, len
,
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
;
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
,
220 .destroy
= _striped_destroy
,
223 struct segment_type
*init_striped_segtype(struct cmd_context
*cmd
)
225 struct segment_type
*segtype
= dm_malloc(sizeof(*segtype
));
231 segtype
->ops
= &_striped_ops
;
232 segtype
->name
= "striped";
233 segtype
->private = NULL
;
235 SEG_CAN_SPLIT
| SEG_AREAS_STRIPED
| SEG_FORMAT1_SUPPORT
;
237 log_very_verbose("Initialised segtype: %s", segtype
->name
);