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(¤t->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 } 369