1 /* $NetBSD: import-extents.c,v 1.1.1.2 2009/12/02 00:26:49 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 "disk-rep.h" 21 #include "lv_alloc.h" 22 #include "display.h" 23 #include "segtype.h" 24 25 /* 26 * After much thought I have decided it is easier, 27 * and probably no less efficient, to convert the 28 * pe->le map to a full le->pe map, and then 29 * process this to get the segments form that 30 * we're after. Any code which goes directly from 31 * the pe->le map to segments would be gladly 32 * accepted, if it is less complicated than this 33 * file. 34 */ 35 struct pe_specifier { 36 struct physical_volume *pv; 37 uint32_t pe; 38 }; 39 40 struct lv_map { 41 struct logical_volume *lv; 42 uint32_t stripes; 43 uint32_t stripe_size; 44 struct pe_specifier *map; 45 }; 46 47 static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem, 48 struct volume_group *vg) 49 { 50 struct dm_hash_table *maps = dm_hash_create(32); 51 struct lv_list *ll; 52 struct lv_map *lvm; 53 54 if (!maps) { 55 log_error("Unable to create hash table for holding " 56 "extent maps."); 57 return NULL; 58 } 59 60 dm_list_iterate_items(ll, &vg->lvs) { 61 if (ll->lv->status & SNAPSHOT) 62 continue; 63 64 if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) 65 goto_bad; 66 67 lvm->lv = ll->lv; 68 if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map) 69 * ll->lv->le_count))) 70 goto_bad; 71 72 if (!dm_hash_insert(maps, ll->lv->name, lvm)) 73 goto_bad; 74 } 75 76 return maps; 77 78 bad: 79 dm_hash_destroy(maps); 80 return NULL; 81 } 82 83 static int _fill_lv_array(struct lv_map **lvs, 84 struct dm_hash_table *maps, struct disk_list *dl) 85 { 86 struct lvd_list *ll; 87 struct lv_map *lvm; 88 89 memset(lvs, 0, sizeof(*lvs) * MAX_LV); 90 91 dm_list_iterate_items(ll, &dl->lvds) { 92 if (!(lvm = dm_hash_lookup(maps, strrchr((char *)ll->lvd.lv_name, '/') 93 + 1))) { 94 log_error("Physical volume (%s) contains an " 95 "unknown logical volume (%s).", 96 dev_name(dl->dev), ll->lvd.lv_name); 97 return 0; 98 } 99 100 lvm->stripes = ll->lvd.lv_stripes; 101 lvm->stripe_size = ll->lvd.lv_stripesize; 102 103 lvs[ll->lvd.lv_number] = lvm; 104 } 105 106 return 1; 107 } 108 109 static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg, 110 struct dm_list *pvds) 111 { 112 struct disk_list *dl; 113 struct physical_volume *pv; 114 struct lv_map *lvms[MAX_LV], *lvm; 115 struct pe_disk *e; 116 uint32_t i, lv_num, le; 117 118 dm_list_iterate_items(dl, pvds) { 119 pv = find_pv(vg, dl->dev); 120 e = dl->extents; 121 122 /* build an array of lv's for this pv */ 123 if (!_fill_lv_array(lvms, maps, dl)) 124 return_0; 125 126 for (i = 0; i < dl->pvd.pe_total; i++) { 127 lv_num = e[i].lv_num; 128 129 if (lv_num == UNMAPPED_EXTENT) 130 continue; 131 132 else { 133 lv_num--; 134 lvm = lvms[lv_num]; 135 136 if (!lvm) { 137 log_error("Invalid LV in extent map " 138 "(PV %s, PE %" PRIu32 139 ", LV %" PRIu32 140 ", LE %" PRIu32 ")", 141 dev_name(pv->dev), i, 142 lv_num, e[i].le_num); 143 return 0; 144 } 145 146 le = e[i].le_num; 147 148 if (le >= lvm->lv->le_count) { 149 log_error("logical extent number " 150 "out of bounds"); 151 return 0; 152 } 153 154 if (lvm->map[le].pv) { 155 log_error("logical extent (%u) " 156 "already mapped.", le); 157 return 0; 158 } 159 160 lvm->map[le].pv = pv; 161 lvm->map[le].pe = i; 162 } 163 } 164 } 165 166 return 1; 167 } 168 169 static int _check_single_map(struct lv_map *lvm) 170 { 171 uint32_t i; 172 173 for (i = 0; i < lvm->lv->le_count; i++) { 174 if (!lvm->map[i].pv) { 175 log_error("Logical volume (%s) contains an incomplete " 176 "mapping table.", lvm->lv->name); 177 return 0; 178 } 179 } 180 181 return 1; 182 } 183 184 static int _check_maps_are_complete(struct dm_hash_table *maps) 185 { 186 struct dm_hash_node *n; 187 struct lv_map *lvm; 188 189 for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) { 190 lvm = (struct lv_map *) dm_hash_get_data(maps, n); 191 192 if (!_check_single_map(lvm)) 193 return_0; 194 } 195 return 1; 196 } 197 198 static uint32_t _area_length(struct lv_map *lvm, uint32_t le) 199 { 200 uint32_t len = 0; 201 202 do 203 len++; 204 while ((lvm->map[le + len].pv == lvm->map[le].pv) && 205 (lvm->map[le].pv && 206 lvm->map[le + len].pe == lvm->map[le].pe + len)); 207 208 return len; 209 } 210 211 static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm) 212 { 213 uint32_t le = 0, len; 214 struct lv_segment *seg; 215 struct segment_type *segtype; 216 217 if (!(segtype = get_segtype_from_string(cmd, "striped"))) 218 return_0; 219 220 while (le < lvm->lv->le_count) { 221 len = _area_length(lvm, le); 222 223 if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le, 224 len, 0, 0, NULL, 1, len, 0, 0, 0))) { 225 log_error("Failed to allocate linear segment."); 226 return 0; 227 } 228 229 if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv, 230 lvm->map[le].pe)) 231 return_0; 232 233 dm_list_add(&lvm->lv->segments, &seg->list); 234 235 le += seg->len; 236 } 237 238 return 1; 239 } 240 241 static int _check_stripe(struct lv_map *lvm, uint32_t area_count, 242 uint32_t area_len, uint32_t base_le, 243 uint32_t total_area_len) 244 { 245 uint32_t st; 246 247 /* 248 * Is the next physical extent in every stripe adjacent to the last? 249 */ 250 for (st = 0; st < area_count; st++) 251 if ((lvm->map[base_le + st * total_area_len + area_len].pv != 252 lvm->map[base_le + st * total_area_len].pv) || 253 (lvm->map[base_le + st * total_area_len].pv && 254 lvm->map[base_le + st * total_area_len + area_len].pe != 255 lvm->map[base_le + st * total_area_len].pe + area_len)) 256 return 0; 257 258 return 1; 259 } 260 261 static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm) 262 { 263 uint32_t st, first_area_le = 0, total_area_len; 264 uint32_t area_len; 265 struct lv_segment *seg; 266 struct segment_type *segtype; 267 268 /* 269 * Work out overall striped length 270 */ 271 if (lvm->lv->le_count % lvm->stripes) { 272 log_error("Number of stripes (%u) incompatible " 273 "with logical extent count (%u) for %s", 274 lvm->stripes, lvm->lv->le_count, lvm->lv->name); 275 } 276 277 total_area_len = lvm->lv->le_count / lvm->stripes; 278 279 if (!(segtype = get_segtype_from_string(cmd, "striped"))) 280 return_0; 281 282 while (first_area_le < total_area_len) { 283 area_len = 1; 284 285 /* 286 * Find how many extents are contiguous in all stripes 287 * and so can form part of this segment 288 */ 289 while (_check_stripe(lvm, lvm->stripes, 290 area_len, first_area_le, total_area_len)) 291 area_len++; 292 293 if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, 294 lvm->stripes * first_area_le, 295 lvm->stripes * area_len, 296 0, lvm->stripe_size, NULL, 297 lvm->stripes, 298 area_len, 0, 0, 0))) { 299 log_error("Failed to allocate striped segment."); 300 return 0; 301 } 302 303 /* 304 * Set up start positions of each stripe in this segment 305 */ 306 for (st = 0; st < seg->area_count; st++) 307 if (!set_lv_segment_area_pv(seg, st, 308 lvm->map[first_area_le + st * total_area_len].pv, 309 lvm->map[first_area_le + st * total_area_len].pe)) 310 return_0; 311 312 dm_list_add(&lvm->lv->segments, &seg->list); 313 314 first_area_le += area_len; 315 } 316 317 return 1; 318 } 319 320 static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm) 321 { 322 return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) : 323 _read_linear(cmd, lvm)); 324 } 325 326 static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps) 327 { 328 struct dm_hash_node *n; 329 struct lv_map *lvm; 330 331 for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) { 332 lvm = (struct lv_map *) dm_hash_get_data(maps, n); 333 if (!_build_segments(cmd, lvm)) 334 return_0; 335 } 336 337 return 1; 338 } 339 340 int import_extents(struct cmd_context *cmd, struct volume_group *vg, 341 struct dm_list *pvds) 342 { 343 int r = 0; 344 struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024); 345 struct dm_hash_table *maps; 346 347 if (!scratch) 348 return_0; 349 350 if (!(maps = _create_lv_maps(scratch, vg))) { 351 log_error("Couldn't allocate logical volume maps."); 352 goto out; 353 } 354 355 if (!_fill_maps(maps, vg, pvds)) { 356 log_error("Couldn't fill logical volume maps."); 357 goto out; 358 } 359 360 if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG)) 361 goto_out; 362 363 if (!_build_all_segments(cmd, maps)) { 364 log_error("Couldn't build extent segments."); 365 goto out; 366 } 367 r = 1; 368 369 out: 370 if (maps) 371 dm_hash_destroy(maps); 372 dm_pool_destroy(scratch); 373 return r; 374 } 375