4 * Copyright (C) 2001-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
20 #include "toolcontext.h"
27 * Attempt to merge two adjacent segments.
28 * Currently only supports striped segments on AREA_PV.
29 * Returns success if successful, in which case 'first'
30 * gets adjusted to contain both areas.
32 static int _merge(struct lv_segment
*first
, struct lv_segment
*second
)
34 if (!first
|| !second
|| first
->segtype
!= second
->segtype
||
35 !first
->segtype
->ops
->merge_segments
) return 0;
37 return first
->segtype
->ops
->merge_segments(first
, second
);
40 int lv_merge_segments(struct logical_volume
*lv
)
42 struct dm_list
*segh
, *t
;
43 struct lv_segment
*current
, *prev
= NULL
;
45 if (lv
->status
& LOCKED
|| lv
->status
& PVMOVE
)
48 dm_list_iterate_safe(segh
, t
, &lv
->segments
) {
49 current
= dm_list_item(segh
, struct lv_segment
);
51 if (_merge(prev
, current
))
52 dm_list_del(¤t
->list
);
61 * Verify that an LV's segments are consecutive, complete and don't overlap.
63 int check_lv_segments(struct logical_volume
*lv
, int complete_vg
)
65 struct lv_segment
*seg
, *seg2
;
67 unsigned seg_count
= 0, seg_found
;
69 uint32_t area_multiplier
, s
;
72 dm_list_iterate_items(seg
, &lv
->segments
) {
75 log_error("LV %s invalid: segment %u should begin at "
76 "LE %" PRIu32
" (found %" PRIu32
").",
77 lv
->name
, seg_count
, le
, seg
->le
);
81 area_multiplier
= segtype_is_striped(seg
->segtype
) ?
84 if (seg
->area_len
* area_multiplier
!= seg
->len
) {
85 log_error("LV %s: segment %u has inconsistent "
87 lv
->name
, seg_count
, seg
->area_len
);
91 if (complete_vg
&& seg
->log_lv
) {
92 if (!seg_is_mirrored(seg
)) {
93 log_error("LV %s: segment %u has log LV but "
99 if (!(seg
->log_lv
->status
& MIRROR_LOG
)) {
100 log_error("LV %s: segment %u log LV %s is not "
102 lv
->name
, seg_count
, seg
->log_lv
->name
);
106 if (!(seg2
= first_seg(seg
->log_lv
)) ||
107 find_mirror_seg(seg2
) != seg
) {
108 log_error("LV %s: segment %u log LV does not "
109 "point back to mirror segment",
110 lv
->name
, seg_count
);
115 if (complete_vg
&& seg
->status
& MIRROR_IMAGE
) {
116 if (!find_mirror_seg(seg
) ||
117 !seg_is_mirrored(find_mirror_seg(seg
))) {
118 log_error("LV %s: segment %u mirror image "
120 lv
->name
, seg_count
);
125 if (seg_is_snapshot(seg
)) {
126 if (seg
->cow
&& seg
->cow
== seg
->origin
) {
127 log_error("LV %s: segment %u has same LV %s for "
128 "both origin and snapshot",
129 lv
->name
, seg_count
, seg
->cow
->name
);
134 for (s
= 0; s
< seg
->area_count
; s
++) {
135 if (seg_type(seg
, s
) == AREA_UNASSIGNED
) {
136 log_error("LV %s: segment %u has unassigned "
138 lv
->name
, seg_count
, s
);
140 } else if (seg_type(seg
, s
) == AREA_PV
) {
141 if (!seg_pvseg(seg
, s
) ||
142 seg_pvseg(seg
, s
)->lvseg
!= seg
||
143 seg_pvseg(seg
, s
)->lv_area
!= s
) {
144 log_error("LV %s: segment %u has "
145 "inconsistent PV area %u",
146 lv
->name
, seg_count
, s
);
150 if (!seg_lv(seg
, s
) ||
151 seg_lv(seg
, s
)->vg
!= lv
->vg
||
152 seg_lv(seg
, s
) == lv
) {
153 log_error("LV %s: segment %u has "
154 "inconsistent LV area %u",
155 lv
->name
, seg_count
, s
);
159 if (complete_vg
&& seg_lv(seg
, s
) &&
160 (seg_lv(seg
, s
)->status
& MIRROR_IMAGE
) &&
161 (!(seg2
= find_seg_by_le(seg_lv(seg
, s
),
163 find_mirror_seg(seg2
) != seg
)) {
164 log_error("LV %s: segment %u mirror "
165 "image %u missing mirror ptr",
166 lv
->name
, seg_count
, s
);
170 /* FIXME I don't think this ever holds?
171 if (seg_le(seg, s) != le) {
172 log_error("LV %s: segment %u has "
173 "inconsistent LV area %u "
175 lv->name, seg_count, s);
180 dm_list_iterate_items(sl
, &seg_lv(seg
, s
)->segs_using_this_lv
)
184 log_error("LV %s segment %d uses LV %s,"
185 " but missing ptr from %s to %s",
187 seg_lv(seg
, s
)->name
,
188 seg_lv(seg
, s
)->name
, lv
->name
);
190 } else if (seg_found
> 1) {
191 log_error("LV %s has duplicated links "
192 "to LV %s segment %d",
193 seg_lv(seg
, s
)->name
,
194 lv
->name
, seg_count
);
203 dm_list_iterate_items(sl
, &lv
->segs_using_this_lv
) {
206 for (s
= 0; s
< seg
->area_count
; s
++) {
207 if (seg_type(seg
, s
) != AREA_LV
)
209 if (lv
== seg_lv(seg
, s
))
212 if (seg
->log_lv
== lv
)
215 log_error("LV %s is used by LV %s:%" PRIu32
"-%" PRIu32
216 ", but missing ptr from %s to %s",
217 lv
->name
, seg
->lv
->name
, seg
->le
,
218 seg
->le
+ seg
->len
- 1,
219 seg
->lv
->name
, lv
->name
);
221 } else if (seg_found
!= sl
->count
) {
222 log_error("Reference count mismatch: LV %s has %d "
223 "links to LV %s:%" PRIu32
"-%" PRIu32
224 ", which has %d links",
225 lv
->name
, sl
->count
, seg
->lv
->name
, seg
->le
,
226 seg
->le
+ seg
->len
- 1, seg_found
);
231 dm_list_iterate_items(seg2
, &seg
->lv
->segments
)
232 if (sl
->seg
== seg2
) {
237 log_error("LV segment %s:%" PRIu32
"-%" PRIu32
238 "is incorrectly listed as being used by LV %s",
239 seg
->lv
->name
, seg
->le
, seg
->le
+ seg
->len
- 1,
245 if (le
!= lv
->le_count
) {
246 log_error("LV %s: inconsistent LE count %u != %u",
247 lv
->name
, le
, lv
->le_count
);
255 * Split the supplied segment at the supplied logical extent
256 * NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
258 static int _lv_split_segment(struct logical_volume
*lv
, struct lv_segment
*seg
,
261 struct lv_segment
*split_seg
;
263 uint32_t offset
= le
- seg
->le
;
264 uint32_t area_offset
;
266 if (!seg_can_split(seg
)) {
267 log_error("Unable to split the %s segment at LE %" PRIu32
268 " in LV %s", seg
->segtype
->name
, le
, lv
->name
);
272 /* Clone the existing segment */
273 if (!(split_seg
= alloc_lv_segment(lv
->vg
->cmd
->mem
, seg
->segtype
,
274 seg
->lv
, seg
->le
, seg
->len
,
275 seg
->status
, seg
->stripe_size
,
277 seg
->area_count
, seg
->area_len
,
278 seg
->chunk_size
, seg
->region_size
,
279 seg
->extents_copied
))) {
280 log_error("Couldn't allocate cloned LV segment.");
284 if (!str_list_dup(lv
->vg
->cmd
->mem
, &split_seg
->tags
, &seg
->tags
)) {
285 log_error("LV segment tags duplication failed");
289 /* In case of a striped segment, the offset has to be / stripes */
290 area_offset
= offset
;
291 if (seg_is_striped(seg
))
292 area_offset
/= seg
->area_count
;
294 split_seg
->area_len
-= area_offset
;
295 seg
->area_len
= area_offset
;
297 split_seg
->len
-= offset
;
300 split_seg
->le
= seg
->le
+ seg
->len
;
302 /* Adjust the PV mapping */
303 for (s
= 0; s
< seg
->area_count
; s
++) {
304 seg_type(split_seg
, s
) = seg_type(seg
, s
);
306 /* Split area at the offset */
307 switch (seg_type(seg
, s
)) {
309 if (!set_lv_segment_area_lv(split_seg
, s
, seg_lv(seg
, s
),
310 seg_le(seg
, s
) + seg
->area_len
, 0))
312 log_debug("Split %s:%u[%u] at %u: %s LE %u", lv
->name
,
313 seg
->le
, s
, le
, seg_lv(seg
, s
)->name
,
314 seg_le(split_seg
, s
));
318 if (!(seg_pvseg(split_seg
, s
) =
319 assign_peg_to_lvseg(seg_pv(seg
, s
),
322 seg_pvseg(seg
, s
)->len
-
326 log_debug("Split %s:%u[%u] at %u: %s PE %u", lv
->name
,
328 dev_name(seg_dev(seg
, s
)),
329 seg_pe(split_seg
, s
));
332 case AREA_UNASSIGNED
:
333 log_error("Unassigned area %u found in segment", s
);
338 /* Add split off segment to the list _after_ the original one */
339 dm_list_add_h(&seg
->list
, &split_seg
->list
);
345 * Ensure there's a segment boundary at the given logical extent
347 int lv_split_segment(struct logical_volume
*lv
, uint32_t le
)
349 struct lv_segment
*seg
;
351 if (!(seg
= find_seg_by_le(lv
, le
))) {
352 log_error("Segment with extent %" PRIu32
" in LV %s not found",
357 /* This is a segment start already */
361 if (!_lv_split_segment(lv
, seg
, le
))
364 if (!vg_validate(lv
->vg
))