Home | History | Annotate | Line # | Download | only in metadata
      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 }
    369