1 /* $NetBSD: layout.c,v 1.1.1.1 2008/12/22 00:18:00 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2006 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 "disk-rep.h" 20 21 /* 22 * Only works with powers of 2. 23 */ 24 static uint32_t _round_up(uint32_t n, uint32_t size) 25 { 26 size--; 27 return (n + size) & ~size; 28 } 29 30 /* Unused. 31 static uint32_t _div_up(uint32_t n, uint32_t size) 32 { 33 return _round_up(n, size) / size; 34 } 35 */ 36 37 /* 38 * Each chunk of metadata should be aligned to 39 * METADATA_ALIGN. 40 */ 41 static uint32_t _next_base(struct data_area *area) 42 { 43 return _round_up(area->base + area->size, METADATA_ALIGN); 44 } 45 46 /* 47 * Quick calculation based on pe_start. 48 */ 49 static int _adjust_pe_on_disk(struct pv_disk *pvd) 50 { 51 uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT; 52 53 if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size) 54 return 0; 55 56 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base; 57 return 1; 58 } 59 60 static void _calc_simple_layout(struct pv_disk *pvd) 61 { 62 pvd->pv_on_disk.base = METADATA_BASE; 63 pvd->pv_on_disk.size = PV_SIZE; 64 65 pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk); 66 pvd->vg_on_disk.size = VG_SIZE; 67 68 pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk); 69 pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN; 70 71 pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk); 72 pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk); 73 74 pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk); 75 pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk); 76 } 77 78 static int _check_vg_limits(struct disk_list *dl) 79 { 80 if (dl->vgd.lv_max > MAX_LV) { 81 log_error("MaxLogicalVolumes of %d exceeds format limit of %d " 82 "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1, 83 dl->pvd.vg_name); 84 return 0; 85 } 86 87 if (dl->vgd.pv_max > MAX_PV) { 88 log_error("MaxPhysicalVolumes of %d exceeds format limit of %d " 89 "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1, 90 dl->pvd.vg_name); 91 return 0; 92 } 93 94 return 1; 95 } 96 97 /* 98 * This assumes pe_count and pe_start have already 99 * been calculated correctly. 100 */ 101 int calculate_layout(struct disk_list *dl) 102 { 103 struct pv_disk *pvd = &dl->pvd; 104 105 _calc_simple_layout(pvd); 106 if (!_adjust_pe_on_disk(pvd)) { 107 log_error("Insufficient space for metadata and PE's."); 108 return 0; 109 } 110 111 if (!_check_vg_limits(dl)) 112 return 0; 113 114 return 1; 115 } 116 117 /* 118 * The number of extents that can fit on a disk is metadata format dependant. 119 * pe_start is any existing value for pe_start 120 */ 121 int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size, 122 uint32_t max_extent_count, uint64_t pe_start) 123 { 124 struct pv_disk *pvd = dm_malloc(sizeof(*pvd)); 125 uint32_t end; 126 127 if (!pvd) 128 return_0; 129 130 /* 131 * Guess how many extents will fit, bearing in mind that 132 * one is going to be knocked off at the start of the 133 * next loop. 134 */ 135 if (max_extent_count) 136 pvd->pe_total = max_extent_count + 1; 137 else 138 pvd->pe_total = (pv->size / extent_size); 139 140 if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) { 141 log_error("Too few extents on %s. Try smaller extent size.", 142 pv_dev_name(pv)); 143 dm_free(pvd); 144 return 0; 145 } 146 147 do { 148 pvd->pe_total--; 149 _calc_simple_layout(pvd); 150 end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size + 151 SECTOR_SIZE - 1) >> SECTOR_SHIFT); 152 153 if (pe_start && end < pe_start) 154 end = pe_start; 155 156 pvd->pe_start = _round_up(end, LVM1_PE_ALIGN); 157 158 } while ((pvd->pe_start + (pvd->pe_total * extent_size)) 159 > pv->size); 160 161 if (pvd->pe_total > MAX_PE_TOTAL) { 162 log_error("Metadata extent limit (%u) exceeded for %s - " 163 "%u required", MAX_PE_TOTAL, pv_dev_name(pv), 164 pvd->pe_total); 165 dm_free(pvd); 166 return 0; 167 } 168 169 pv->pe_count = pvd->pe_total; 170 pv->pe_start = pvd->pe_start; 171 /* We can't set pe_size here without breaking LVM1 compatibility */ 172 dm_free(pvd); 173 return 1; 174 } 175