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