Hi, lvextend doesn't allocate extents appropriately if the LV is mirrored. Attached patch fixes the problem. If this looks reasonable, please consider to include in LVM2. Details of the problem: Suppose I have 4 PVs with sufficient free space and a 2-sided mirrored LV with size=4MB, I would expect the following LV as a result of "lvextend -L+4MB": # lvs -a -olv_name,seg_size,devices vg4 LV SSize Devices lv0 8.00M lv0_mimage_0(0),lv0_mimage_1(0) [lv0_mimage_0] 8.00M /dev/sda(0) [lv0_mimage_1] 8.00M /dev/sdb(0) [lv0_mlog] 4.00M /dev/sdc(0) However, actual result was following: # lvs -a -olv_name,seg_size,devices vg4 LV SSize Devices lv0 8.00M lv0_mimage_0(0),lv0_mimage_1(0) [lv0_mimage_0] 4.00M /dev/sda(0) [lv0_mimage_0] 4.00M /dev/sdd(0) [lv0_mimage_1] 4.00M /dev/sdb(0) [lv0_mimage_1] 4.00M /dev/sda(1) [lv0_mlog] 4.00M /dev/sdc(0) In this case, failure of a PV (/dev/sda) would break whole LV (lv0), which is not what we expect from mirrored LV. The cause of the problem is that _check_contiguous() doesn't care layered LV and cannot find out contiguousness between PV areas. Thanks, -- Jun'ichi Nomura, NEC Corporation of America
Finding contiguous PV segment for mirrored LV. Check areas[] boundary in _check_contiguous(). Applicable to LVM2 2.02.09. Steps to reproduce the problem: # pvcreate /dev/sd[abcd] # vgcreate vg4 /dev/sd[abcd] # lvcreate -l1 -m1 -nlv0 vg4 # lvchange -an vg4/lv0 # lvextend -l+1 vg4/lv0 # lvs -a -olv_name,seg_size,devices vg4 --- LVM2/lib/metadata/lv_manip.c 2006-08-23 04:26:43.000000000 -0400 +++ LVM2.fix/lib/metadata/lv_manip.c 2006-08-23 04:29:37.000000000 -0400 @@ -642,12 +642,24 @@ static int _comp_area(const void *l, con */ static int _check_contiguous(struct lv_segment *prev_lvseg, struct physical_volume *pv, struct pv_area *pva, - struct pv_area **areas) + struct pv_area **areas, uint32_t areas_size) { struct pv_segment *prev_pvseg; uint32_t s; - for (s = 0; s < prev_lvseg->area_count; s++) { + for (s = 0; s < prev_lvseg->area_count && s < areas_size; s++) { + if (seg_type(prev_lvseg, s) == AREA_LV) { + struct logical_volume *lv; + struct lv_segment *lastseg; + lv = seg_lv(prev_lvseg, s); + lastseg = list_item(list_last(&lv->segments), + struct lv_segment); + if (_check_contiguous(lastseg, pv, pva, &areas[s], + areas_size - s)) + return 1; + continue; + } + if (seg_type(prev_lvseg, s) != AREA_PV) continue; /* FIXME Broken */ @@ -752,7 +764,8 @@ static int _find_parallel_space(struct a if (prev_lvseg && _check_contiguous(prev_lvseg, pvm->pv, - pva, areas)) { + pva, areas, + areas_size)) { contiguous_count++; goto next_pv; }
_______________________________________________ linux-lvm mailing list linux-lvm@redhat.com https://www.redhat.com/mailman/listinfo/linux-lvm read the LVM HOW-TO at http://tldp.org/HOWTO/LVM-HOWTO/