Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is part of LVM2.
6 : : *
7 : : * This copyrighted material is made available to anyone wishing to use,
8 : : * modify, copy, or redistribute it subject to the terms and conditions
9 : : * of the GNU Lesser General Public License v.2.1.
10 : : *
11 : : * You should have received a copy of the GNU Lesser General Public License
12 : : * along with this program; if not, write to the Free Software Foundation,
13 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 : : */
15 : :
16 : : #include "lib.h"
17 : : #include "metadata.h"
18 : : #include "toolcontext.h"
19 : : #include "lv_alloc.h"
20 : : #include "pv_alloc.h"
21 : : #include "str_list.h"
22 : : #include "segtype.h"
23 : :
24 : : /*
25 : : * Attempt to merge two adjacent segments.
26 : : * Currently only supports striped segments on AREA_PV.
27 : : * Returns success if successful, in which case 'first'
28 : : * gets adjusted to contain both areas.
29 : : */
30 : 0 : static int _merge(struct lv_segment *first, struct lv_segment *second)
31 : : {
32 [ # # ][ # # ]: 0 : if (!first || !second || first->segtype != second->segtype ||
[ # # ][ # # ]
33 : 0 : !first->segtype->ops->merge_segments)
34 : 0 : return 0;
35 : :
36 : 0 : return first->segtype->ops->merge_segments(first, second);
37 : : }
38 : :
39 : 0 : int lv_merge_segments(struct logical_volume *lv)
40 : : {
41 : : struct dm_list *segh, *t;
42 : 0 : struct lv_segment *current, *prev = NULL;
43 : :
44 [ # # ][ # # ]: 0 : if (lv->status & LOCKED || lv->status & PVMOVE)
45 : 0 : return 1;
46 : :
47 [ # # ]: 0 : dm_list_iterate_safe(segh, t, &lv->segments) {
48 : 0 : current = dm_list_item(segh, struct lv_segment);
49 : :
50 [ # # ]: 0 : if (_merge(prev, current))
51 : 0 : dm_list_del(¤t->list);
52 : : else
53 : 0 : prev = current;
54 : : }
55 : :
56 : 0 : return 1;
57 : : }
58 : :
59 : : #define ERROR_MAX 100
60 : : #define inc_error_count \
61 : : if (error_count++ > ERROR_MAX) \
62 : : goto out
63 : :
64 : : /*
65 : : * Verify that an LV's segments are consecutive, complete and don't overlap.
66 : : */
67 : 0 : int check_lv_segments(struct logical_volume *lv, int complete_vg)
68 : : {
69 : : struct lv_segment *seg, *seg2;
70 : 0 : uint32_t le = 0;
71 : 0 : unsigned seg_count = 0, seg_found;
72 : : uint32_t area_multiplier, s;
73 : : struct seg_list *sl;
74 : 0 : int error_count = 0;
75 : : struct replicator_site *rsite;
76 : : struct replicator_device *rdev;
77 : :
78 [ # # ]: 0 : dm_list_iterate_items(seg, &lv->segments) {
79 : 0 : seg_count++;
80 [ # # ]: 0 : if (seg->le != le) {
81 : 0 : log_error("LV %s invalid: segment %u should begin at "
82 : : "LE %" PRIu32 " (found %" PRIu32 ").",
83 : : lv->name, seg_count, le, seg->le);
84 [ # # ]: 0 : inc_error_count;
85 : : }
86 : :
87 [ # # ]: 0 : area_multiplier = segtype_is_striped(seg->segtype) ?
88 : : seg->area_count : 1;
89 : :
90 [ # # ]: 0 : if (seg->area_len * area_multiplier != seg->len) {
91 : 0 : log_error("LV %s: segment %u has inconsistent "
92 : : "area_len %u",
93 : : lv->name, seg_count, seg->area_len);
94 [ # # ]: 0 : inc_error_count;
95 : : }
96 : :
97 [ # # ][ # # ]: 0 : if (complete_vg && seg->log_lv) {
98 [ # # ]: 0 : if (!seg_is_mirrored(seg)) {
99 : 0 : log_error("LV %s: segment %u has log LV but "
100 : : "is not mirrored",
101 : : lv->name, seg_count);
102 [ # # ]: 0 : inc_error_count;
103 : : }
104 : :
105 [ # # ]: 0 : if (!(seg->log_lv->status & MIRROR_LOG)) {
106 : 0 : log_error("LV %s: segment %u log LV %s is not "
107 : : "a mirror log",
108 : : lv->name, seg_count, seg->log_lv->name);
109 [ # # ]: 0 : inc_error_count;
110 : : }
111 : :
112 [ # # # # ]: 0 : if (!(seg2 = first_seg(seg->log_lv)) ||
113 : 0 : find_mirror_seg(seg2) != seg) {
114 : 0 : log_error("LV %s: segment %u log LV does not "
115 : : "point back to mirror segment",
116 : : lv->name, seg_count);
117 [ # # ]: 0 : inc_error_count;
118 : : }
119 : : }
120 : :
121 [ # # ][ # # ]: 0 : if (complete_vg && seg->status & MIRROR_IMAGE) {
122 [ # # # # ]: 0 : if (!find_mirror_seg(seg) ||
123 : 0 : !seg_is_mirrored(find_mirror_seg(seg))) {
124 : 0 : log_error("LV %s: segment %u mirror image "
125 : : "is not mirrored",
126 : : lv->name, seg_count);
127 [ # # ]: 0 : inc_error_count;
128 : : }
129 : : }
130 : :
131 [ # # ]: 0 : if (seg_is_snapshot(seg)) {
132 [ # # ][ # # ]: 0 : if (seg->cow && seg->cow == seg->origin) {
133 : 0 : log_error("LV %s: segment %u has same LV %s for "
134 : : "both origin and snapshot",
135 : : lv->name, seg_count, seg->cow->name);
136 [ # # ]: 0 : inc_error_count;
137 : : }
138 : : }
139 : :
140 [ # # ][ # # ]: 0 : if (seg_is_replicator(seg) && !replicator_check_segment(seg))
141 [ # # ]: 0 : inc_error_count;
142 : :
143 [ # # ]: 0 : for (s = 0; s < seg->area_count; s++) {
144 [ # # ]: 0 : if (seg_type(seg, s) == AREA_UNASSIGNED) {
145 : 0 : log_error("LV %s: segment %u has unassigned "
146 : : "area %u.",
147 : : lv->name, seg_count, s);
148 [ # # ]: 0 : inc_error_count;
149 [ # # ]: 0 : } else if (seg_type(seg, s) == AREA_PV) {
150 [ # # ][ # # ]: 0 : if (!seg_pvseg(seg, s) ||
[ # # ]
151 : 0 : seg_pvseg(seg, s)->lvseg != seg ||
152 : 0 : seg_pvseg(seg, s)->lv_area != s) {
153 : 0 : log_error("LV %s: segment %u has "
154 : : "inconsistent PV area %u",
155 : : lv->name, seg_count, s);
156 [ # # ]: 0 : inc_error_count;
157 : : }
158 : : } else {
159 [ # # ][ # # ]: 0 : if (!seg_lv(seg, s) ||
[ # # ]
160 : 0 : seg_lv(seg, s)->vg != lv->vg ||
161 : 0 : seg_lv(seg, s) == lv) {
162 : 0 : log_error("LV %s: segment %u has "
163 : : "inconsistent LV area %u",
164 : : lv->name, seg_count, s);
165 [ # # ]: 0 : inc_error_count;
166 : : }
167 : :
168 [ # # ][ # # ]: 0 : if (complete_vg && seg_lv(seg, s) &&
[ # # # # #
# ]
169 : 0 : (seg_lv(seg, s)->status & MIRROR_IMAGE) &&
170 : 0 : (!(seg2 = find_seg_by_le(seg_lv(seg, s),
171 : 0 : seg_le(seg, s))) ||
172 : 0 : find_mirror_seg(seg2) != seg)) {
173 : 0 : log_error("LV %s: segment %u mirror "
174 : : "image %u missing mirror ptr",
175 : : lv->name, seg_count, s);
176 [ # # ]: 0 : inc_error_count;
177 : : }
178 : :
179 : : /* FIXME I don't think this ever holds?
180 : : if (seg_le(seg, s) != le) {
181 : : log_error("LV %s: segment %u has "
182 : : "inconsistent LV area %u "
183 : : "size",
184 : : lv->name, seg_count, s);
185 : : inc_error_count;
186 : : }
187 : : */
188 : 0 : seg_found = 0;
189 [ # # ]: 0 : dm_list_iterate_items(sl, &seg_lv(seg, s)->segs_using_this_lv)
190 [ # # ]: 0 : if (sl->seg == seg)
191 : 0 : seg_found++;
192 [ # # ]: 0 : if (!seg_found) {
193 : 0 : log_error("LV %s segment %d uses LV %s,"
194 : : " but missing ptr from %s to %s",
195 : : lv->name, seg_count,
196 : : seg_lv(seg, s)->name,
197 : : seg_lv(seg, s)->name, lv->name);
198 [ # # ]: 0 : inc_error_count;
199 [ # # ]: 0 : } else if (seg_found > 1) {
200 : 0 : log_error("LV %s has duplicated links "
201 : : "to LV %s segment %d",
202 : : seg_lv(seg, s)->name,
203 : : lv->name, seg_count);
204 [ # # ]: 0 : inc_error_count;
205 : : }
206 : : }
207 : : }
208 : :
209 : 0 : le += seg->len;
210 : : }
211 : :
212 [ # # ]: 0 : dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
213 : 0 : seg = sl->seg;
214 : 0 : seg_found = 0;
215 [ # # ]: 0 : for (s = 0; s < seg->area_count; s++) {
216 [ # # ]: 0 : if (seg_type(seg, s) != AREA_LV)
217 : 0 : continue;
218 [ # # ]: 0 : if (lv == seg_lv(seg, s))
219 : 0 : seg_found++;
220 : : }
221 [ # # ]: 0 : if (seg_is_replicator_dev(seg)) {
222 [ # # ]: 0 : dm_list_iterate_items(rsite, &seg->replicator->rsites) {
223 [ # # ]: 0 : dm_list_iterate_items(rdev, &rsite->rdevices) {
224 [ # # ][ # # ]: 0 : if (lv == rdev->lv || lv == rdev->slog)
225 : 0 : seg_found++;
226 : : }
227 : : }
228 [ # # ]: 0 : if (lv == seg->replicator)
229 : 0 : seg_found++;
230 : : }
231 [ # # ][ # # ]: 0 : if (seg_is_replicator(seg) && lv == seg->rlog_lv)
232 : 0 : seg_found++;
233 [ # # ]: 0 : if (seg->log_lv == lv)
234 : 0 : seg_found++;
235 [ # # ]: 0 : if (!seg_found) {
236 : 0 : log_error("LV %s is used by LV %s:%" PRIu32 "-%" PRIu32
237 : : ", but missing ptr from %s to %s",
238 : : lv->name, seg->lv->name, seg->le,
239 : : seg->le + seg->len - 1,
240 : : seg->lv->name, lv->name);
241 [ # # ]: 0 : inc_error_count;
242 [ # # ]: 0 : } else if (seg_found != sl->count) {
243 : 0 : log_error("Reference count mismatch: LV %s has %d "
244 : : "links to LV %s:%" PRIu32 "-%" PRIu32
245 : : ", which has %d links",
246 : : lv->name, sl->count, seg->lv->name, seg->le,
247 : : seg->le + seg->len - 1, seg_found);
248 [ # # ]: 0 : inc_error_count;
249 : : }
250 : :
251 : 0 : seg_found = 0;
252 [ # # ]: 0 : dm_list_iterate_items(seg2, &seg->lv->segments)
253 [ # # ]: 0 : if (sl->seg == seg2) {
254 : 0 : seg_found++;
255 : 0 : break;
256 : : }
257 [ # # ]: 0 : if (!seg_found) {
258 : 0 : log_error("LV segment %s:%" PRIu32 "-%" PRIu32
259 : : " is incorrectly listed as being used by LV %s",
260 : : seg->lv->name, seg->le, seg->le + seg->len - 1,
261 : : lv->name);
262 [ # # ]: 0 : inc_error_count;
263 : : }
264 : : }
265 : :
266 [ # # ]: 0 : if (le != lv->le_count) {
267 : 0 : log_error("LV %s: inconsistent LE count %u != %u",
268 : : lv->name, le, lv->le_count);
269 : 0 : inc_error_count;
270 : : }
271 : :
272 : : out:
273 : 0 : return !error_count;
274 : : }
275 : :
276 : : /*
277 : : * Split the supplied segment at the supplied logical extent
278 : : * NB Use LE numbering that works across stripes PV1: 0,2,4 PV2: 1,3,5 etc.
279 : : */
280 : 0 : static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
281 : : uint32_t le)
282 : : {
283 : : struct lv_segment *split_seg;
284 : : uint32_t s;
285 : 0 : uint32_t offset = le - seg->le;
286 : : uint32_t area_offset;
287 : :
288 [ # # ]: 0 : if (!seg_can_split(seg)) {
289 : 0 : log_error("Unable to split the %s segment at LE %" PRIu32
290 : : " in LV %s", seg->segtype->name, le, lv->name);
291 : 0 : return 0;
292 : : }
293 : :
294 : : /* Clone the existing segment */
295 [ # # ]: 0 : if (!(split_seg = alloc_lv_segment(lv->vg->vgmem, seg->segtype,
296 : : seg->lv, seg->le, seg->len,
297 : : seg->status, seg->stripe_size,
298 : : seg->log_lv,
299 : : seg->area_count, seg->area_len,
300 : : seg->chunk_size, seg->region_size,
301 : : seg->extents_copied, seg->pvmove_source_seg))) {
302 : 0 : log_error("Couldn't allocate cloned LV segment.");
303 : 0 : return 0;
304 : : }
305 : :
306 [ # # ]: 0 : if (!str_list_dup(lv->vg->vgmem, &split_seg->tags, &seg->tags)) {
307 : 0 : log_error("LV segment tags duplication failed");
308 : 0 : return 0;
309 : : }
310 : :
311 : : /* In case of a striped segment, the offset has to be / stripes */
312 : 0 : area_offset = offset;
313 [ # # ]: 0 : if (seg_is_striped(seg))
314 : 0 : area_offset /= seg->area_count;
315 : :
316 : 0 : split_seg->area_len -= area_offset;
317 : 0 : seg->area_len = area_offset;
318 : :
319 : 0 : split_seg->len -= offset;
320 : 0 : seg->len = offset;
321 : :
322 : 0 : split_seg->le = seg->le + seg->len;
323 : :
324 : : /* Adjust the PV mapping */
325 [ # # ]: 0 : for (s = 0; s < seg->area_count; s++) {
326 : 0 : seg_type(split_seg, s) = seg_type(seg, s);
327 : :
328 : : /* Split area at the offset */
329 [ # # # # ]: 0 : switch (seg_type(seg, s)) {
330 : : case AREA_LV:
331 [ # # ]: 0 : if (!set_lv_segment_area_lv(split_seg, s, seg_lv(seg, s),
332 : 0 : seg_le(seg, s) + seg->area_len, 0))
333 : 0 : return_0;
334 : 0 : log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
335 : : seg->le, s, le, seg_lv(seg, s)->name,
336 : : seg_le(split_seg, s));
337 : 0 : break;
338 : :
339 : : case AREA_PV:
340 [ # # ]: 0 : if (!(seg_pvseg(split_seg, s) =
341 : 0 : assign_peg_to_lvseg(seg_pv(seg, s),
342 : 0 : seg_pe(seg, s) +
343 : : seg->area_len,
344 : 0 : seg_pvseg(seg, s)->len -
345 : : seg->area_len,
346 : : split_seg, s)))
347 : 0 : return_0;
348 : 0 : log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
349 : : seg->le, s, le,
350 : : dev_name(seg_dev(seg, s)),
351 : : seg_pe(split_seg, s));
352 : 0 : break;
353 : :
354 : : case AREA_UNASSIGNED:
355 : 0 : log_error("Unassigned area %u found in segment", s);
356 : 0 : return 0;
357 : : }
358 : : }
359 : :
360 : : /* Add split off segment to the list _after_ the original one */
361 : 0 : dm_list_add_h(&seg->list, &split_seg->list);
362 : :
363 : 0 : return 1;
364 : : }
365 : :
366 : : /*
367 : : * Ensure there's a segment boundary at the given logical extent
368 : : */
369 : 0 : int lv_split_segment(struct logical_volume *lv, uint32_t le)
370 : : {
371 : : struct lv_segment *seg;
372 : :
373 [ # # ]: 0 : if (!(seg = find_seg_by_le(lv, le))) {
374 : 0 : log_error("Segment with extent %" PRIu32 " in LV %s not found",
375 : : le, lv->name);
376 : 0 : return 0;
377 : : }
378 : :
379 : : /* This is a segment start already */
380 [ # # ]: 0 : if (le == seg->le)
381 : 0 : return 1;
382 : :
383 [ # # ]: 0 : if (!_lv_split_segment(lv, seg, le))
384 : 0 : return_0;
385 : :
386 [ # # ]: 0 : if (!vg_validate(lv->vg))
387 : 0 : return_0;
388 : :
389 : 0 : return 1;
390 : : }
|