Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / contrib / lvm2 / dist / lib / metadata / merge.c
1 /*      $NetBSD: merge.c,v 1.1.1.1 2008/12/22 00:18:07 haad Exp $       */
2
3 /*
4  * Copyright (C) 2001-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 "metadata.h"
20 #include "toolcontext.h"
21 #include "lv_alloc.h"
22 #include "pv_alloc.h"
23 #include "str_list.h"
24 #include "segtype.h"
25
26 /*
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.
31  */
32 static int _merge(struct lv_segment *first, struct lv_segment *second)
33 {
34         if (!first || !second || first->segtype != second->segtype ||
35             !first->segtype->ops->merge_segments) return 0;
36
37         return first->segtype->ops->merge_segments(first, second);
38 }
39
40 int lv_merge_segments(struct logical_volume *lv)
41 {
42         struct dm_list *segh, *t;
43         struct lv_segment *current, *prev = NULL;
44
45         if (lv->status & LOCKED || lv->status & PVMOVE)
46                 return 1;
47
48         dm_list_iterate_safe(segh, t, &lv->segments) {
49                 current = dm_list_item(segh, struct lv_segment);
50
51                 if (_merge(prev, current))
52                         dm_list_del(&current->list);
53                 else
54                         prev = current;
55         }
56
57         return 1;
58 }
59
60 /*
61  * Verify that an LV's segments are consecutive, complete and don't overlap.
62  */
63 int check_lv_segments(struct logical_volume *lv, int complete_vg)
64 {
65         struct lv_segment *seg, *seg2;
66         uint32_t le = 0;
67         unsigned seg_count = 0, seg_found;
68         int r = 1;
69         uint32_t area_multiplier, s;
70         struct seg_list *sl;
71
72         dm_list_iterate_items(seg, &lv->segments) {
73                 seg_count++;
74                 if (seg->le != le) {
75                         log_error("LV %s invalid: segment %u should begin at "
76                                   "LE %" PRIu32 " (found %" PRIu32 ").",
77                                   lv->name, seg_count, le, seg->le);
78                         r = 0;
79                 }
80
81                 area_multiplier = segtype_is_striped(seg->segtype) ?
82                                         seg->area_count : 1;
83
84                 if (seg->area_len * area_multiplier != seg->len) {
85                         log_error("LV %s: segment %u has inconsistent "
86                                   "area_len %u",
87                                   lv->name, seg_count, seg->area_len);
88                         r = 0;
89                 }
90
91                 if (complete_vg && seg->log_lv) {
92                         if (!seg_is_mirrored(seg)) {
93                                 log_error("LV %s: segment %u has log LV but "
94                                           "is not mirrored",
95                                           lv->name, seg_count);
96                                 r = 0;
97                         }
98
99                         if (!(seg->log_lv->status & MIRROR_LOG)) {
100                                 log_error("LV %s: segment %u log LV %s is not "
101                                           "a mirror log",
102                                            lv->name, seg_count, seg->log_lv->name);
103                                 r = 0;
104                         }
105
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);
111                                 r = 0;
112                         }
113                 }
114
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 "
119                                           "is not mirrored",
120                                           lv->name, seg_count);
121                                 r = 0;
122                         }
123                 }
124
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);
130                                 r = 0;
131                         }
132                 }
133
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 "
137                                           "area %u.",
138                                           lv->name, seg_count, s);
139                                 r = 0;
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);
147                                         r = 0;
148                                 }
149                         } else {
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);
156                                         r = 0;
157                                 }
158
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),
162                                                             seg_le(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);
167                                         r = 0;
168                                 }
169
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 "
174                                                   "size",
175                                                   lv->name, seg_count, s);
176                                         r = 0;
177                                 }
178  */
179                                 seg_found = 0;
180                                 dm_list_iterate_items(sl, &seg_lv(seg, s)->segs_using_this_lv)
181                                         if (sl->seg == seg)
182                                                 seg_found++;
183                                 if (!seg_found) {
184                                         log_error("LV %s segment %d uses LV %s,"
185                                                   " but missing ptr from %s to %s",
186                                                   lv->name, seg_count,
187                                                   seg_lv(seg, s)->name,
188                                                   seg_lv(seg, s)->name, lv->name);
189                                         r = 0;
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);
195                                         r = 0;
196                                 }
197                         }
198                 }
199
200                 le += seg->len;
201         }
202
203         dm_list_iterate_items(sl, &lv->segs_using_this_lv) {
204                 seg = sl->seg;
205                 seg_found = 0;
206                 for (s = 0; s < seg->area_count; s++) {
207                         if (seg_type(seg, s) != AREA_LV)
208                                 continue;
209                         if (lv == seg_lv(seg, s))
210                                 seg_found++;
211                 }
212                 if (seg->log_lv == lv)
213                         seg_found++;
214                 if (!seg_found) {
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);
220                         r = 0;
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);
227                         r = 0;
228                 }
229
230                 seg_found = 0;
231                 dm_list_iterate_items(seg2, &seg->lv->segments)
232                         if (sl->seg == seg2) {
233                                 seg_found++;
234                                 break;
235                         }
236                 if (!seg_found) {
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,
240                                   lv->name);
241                         r = 0;
242                 }
243         }
244
245         if (le != lv->le_count) {
246                 log_error("LV %s: inconsistent LE count %u != %u",
247                           lv->name, le, lv->le_count);
248                 r = 0;
249         }
250
251         return r;
252 }
253
254 /*
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.
257  */
258 static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
259                              uint32_t le)
260 {
261         struct lv_segment *split_seg;
262         uint32_t s;
263         uint32_t offset = le - seg->le;
264         uint32_t area_offset;
265
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);
269                 return 0;
270         }
271
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,
276                                            seg->log_lv,
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.");
281                 return 0;
282         }
283
284         if (!str_list_dup(lv->vg->cmd->mem, &split_seg->tags, &seg->tags)) {
285                 log_error("LV segment tags duplication failed");
286                 return 0;
287         }
288
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;
293
294         split_seg->area_len -= area_offset;
295         seg->area_len = area_offset;
296
297         split_seg->len -= offset;
298         seg->len = offset;
299
300         split_seg->le = seg->le + seg->len;
301
302         /* Adjust the PV mapping */
303         for (s = 0; s < seg->area_count; s++) {
304                 seg_type(split_seg, s) = seg_type(seg, s);
305
306                 /* Split area at the offset */
307                 switch (seg_type(seg, s)) {
308                 case AREA_LV:
309                         if (!set_lv_segment_area_lv(split_seg, s, seg_lv(seg, s),
310                                                     seg_le(seg, s) + seg->area_len, 0))
311                                 return_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));
315                         break;
316
317                 case AREA_PV:
318                         if (!(seg_pvseg(split_seg, s) =
319                              assign_peg_to_lvseg(seg_pv(seg, s),
320                                                  seg_pe(seg, s) +
321                                                      seg->area_len,
322                                                  seg_pvseg(seg, s)->len -
323                                                      seg->area_len,
324                                                  split_seg, s)))
325                                 return_0;
326                         log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
327                                   seg->le, s, le,
328                                   dev_name(seg_dev(seg, s)),
329                                   seg_pe(split_seg, s));
330                         break;
331
332                 case AREA_UNASSIGNED:
333                         log_error("Unassigned area %u found in segment", s);
334                         return 0;
335                 }
336         }
337
338         /* Add split off segment to the list _after_ the original one */
339         dm_list_add_h(&seg->list, &split_seg->list);
340
341         return 1;
342 }
343
344 /*
345  * Ensure there's a segment boundary at the given logical extent
346  */
347 int lv_split_segment(struct logical_volume *lv, uint32_t le)
348 {
349         struct lv_segment *seg;
350
351         if (!(seg = find_seg_by_le(lv, le))) {
352                 log_error("Segment with extent %" PRIu32 " in LV %s not found",
353                           le, lv->name);
354                 return 0;
355         }
356
357         /* This is a segment start already */
358         if (le == seg->le)
359                 return 1;
360
361         if (!_lv_split_segment(lv, seg, le))
362                 return_0;
363
364         if (!vg_validate(lv->vg))
365                 return_0;
366
367         return 1;
368 }