1 1.1 haad /* $NetBSD: text_label.c,v 1.1.1.2 2009/12/02 00:26:28 haad Exp $ */ 2 1.1 haad 3 1.1 haad /* 4 1.1 haad * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. 5 1.1 haad * Copyright (C) 2004-2006 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 "format-text.h" 20 1.1 haad #include "layout.h" 21 1.1 haad #include "label.h" 22 1.1 haad #include "xlate.h" 23 1.1 haad #include "lvmcache.h" 24 1.1 haad 25 1.1 haad #include <sys/stat.h> 26 1.1 haad #include <fcntl.h> 27 1.1 haad 28 1.1 haad static int _text_can_handle(struct labeller *l __attribute((unused)), 29 1.1 haad void *buf, 30 1.1 haad uint64_t sector __attribute((unused))) 31 1.1 haad { 32 1.1 haad struct label_header *lh = (struct label_header *) buf; 33 1.1 haad 34 1.1 haad if (!strncmp((char *)lh->type, LVM2_LABEL, sizeof(lh->type))) 35 1.1 haad return 1; 36 1.1 haad 37 1.1 haad return 0; 38 1.1 haad } 39 1.1 haad 40 1.1 haad static int _text_write(struct label *label, void *buf) 41 1.1 haad { 42 1.1 haad struct label_header *lh = (struct label_header *) buf; 43 1.1 haad struct pv_header *pvhdr; 44 1.1 haad struct lvmcache_info *info; 45 1.1 haad struct disk_locn *pvh_dlocn_xl; 46 1.1 haad struct metadata_area *mda; 47 1.1 haad struct mda_context *mdac; 48 1.1 haad struct data_area_list *da; 49 1.1.1.2 haad char buffer[64] __attribute((aligned(8))); 50 1.1.1.2 haad int da1, mda1, mda2; 51 1.1 haad 52 1.1 haad /* FIXME Move to where label is created */ 53 1.1 haad strncpy(label->type, LVM2_LABEL, sizeof(label->type)); 54 1.1 haad 55 1.1 haad strncpy((char *)lh->type, label->type, sizeof(label->type)); 56 1.1 haad 57 1.1 haad pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); 58 1.1 haad info = (struct lvmcache_info *) label->info; 59 1.1 haad pvhdr->device_size_xl = xlate64(info->device_size); 60 1.1 haad memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id)); 61 1.1.1.2 haad if (!id_write_format((const struct id *)pvhdr->pv_uuid, buffer, 62 1.1.1.2 haad sizeof(buffer))) { 63 1.1.1.2 haad stack; 64 1.1.1.2 haad buffer[0] = '\0'; 65 1.1.1.2 haad } 66 1.1 haad 67 1.1 haad pvh_dlocn_xl = &pvhdr->disk_areas_xl[0]; 68 1.1 haad 69 1.1 haad /* List of data areas (holding PEs) */ 70 1.1 haad dm_list_iterate_items(da, &info->das) { 71 1.1 haad pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset); 72 1.1 haad pvh_dlocn_xl->size = xlate64(da->disk_locn.size); 73 1.1 haad pvh_dlocn_xl++; 74 1.1 haad } 75 1.1 haad 76 1.1 haad /* NULL-termination */ 77 1.1 haad pvh_dlocn_xl->offset = xlate64(UINT64_C(0)); 78 1.1 haad pvh_dlocn_xl->size = xlate64(UINT64_C(0)); 79 1.1 haad pvh_dlocn_xl++; 80 1.1 haad 81 1.1 haad /* List of metadata area header locations */ 82 1.1 haad dm_list_iterate_items(mda, &info->mdas) { 83 1.1 haad mdac = (struct mda_context *) mda->metadata_locn; 84 1.1 haad 85 1.1 haad if (mdac->area.dev != info->dev) 86 1.1 haad continue; 87 1.1 haad 88 1.1 haad pvh_dlocn_xl->offset = xlate64(mdac->area.start); 89 1.1 haad pvh_dlocn_xl->size = xlate64(mdac->area.size); 90 1.1 haad pvh_dlocn_xl++; 91 1.1 haad } 92 1.1 haad 93 1.1 haad /* NULL-termination */ 94 1.1 haad pvh_dlocn_xl->offset = xlate64(UINT64_C(0)); 95 1.1 haad pvh_dlocn_xl->size = xlate64(UINT64_C(0)); 96 1.1 haad 97 1.1.1.2 haad /* Create debug message with da and mda locations */ 98 1.1.1.2 haad if (xlate64(pvhdr->disk_areas_xl[0].offset) || 99 1.1.1.2 haad xlate64(pvhdr->disk_areas_xl[0].size)) 100 1.1.1.2 haad da1 = 0; 101 1.1.1.2 haad else 102 1.1.1.2 haad da1 = -1; 103 1.1.1.2 haad 104 1.1.1.2 haad mda1 = da1 + 2; 105 1.1.1.2 haad mda2 = mda1 + 1; 106 1.1.1.2 haad 107 1.1.1.2 haad if (!xlate64(pvhdr->disk_areas_xl[mda1].offset) && 108 1.1.1.2 haad !xlate64(pvhdr->disk_areas_xl[mda1].size)) 109 1.1.1.2 haad mda1 = mda2 = 0; 110 1.1.1.2 haad else if (!xlate64(pvhdr->disk_areas_xl[mda2].offset) && 111 1.1.1.2 haad !xlate64(pvhdr->disk_areas_xl[mda2].size)) 112 1.1.1.2 haad mda2 = 0; 113 1.1.1.2 haad 114 1.1.1.2 haad log_debug("%s: Preparing PV label header %s size %" PRIu64 " with" 115 1.1.1.2 haad "%s%.*" PRIu64 "%s%.*" PRIu64 "%s" 116 1.1.1.2 haad "%s%.*" PRIu64 "%s%.*" PRIu64 "%s" 117 1.1.1.2 haad "%s%.*" PRIu64 "%s%.*" PRIu64 "%s", 118 1.1.1.2 haad dev_name(info->dev), buffer, info->device_size, 119 1.1.1.2 haad (da1 > -1) ? " da1 (" : "", 120 1.1.1.2 haad (da1 > -1) ? 1 : 0, 121 1.1.1.2 haad (da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].offset) >> SECTOR_SHIFT : 0, 122 1.1.1.2 haad (da1 > -1) ? "s, " : "", 123 1.1.1.2 haad (da1 > -1) ? 1 : 0, 124 1.1.1.2 haad (da1 > -1) ? xlate64(pvhdr->disk_areas_xl[da1].size) >> SECTOR_SHIFT : 0, 125 1.1.1.2 haad (da1 > -1) ? "s)" : "", 126 1.1.1.2 haad mda1 ? " mda1 (" : "", 127 1.1.1.2 haad mda1 ? 1 : 0, 128 1.1.1.2 haad mda1 ? xlate64(pvhdr->disk_areas_xl[mda1].offset) >> SECTOR_SHIFT : 0, 129 1.1.1.2 haad mda1 ? "s, " : "", 130 1.1.1.2 haad mda1 ? 1 : 0, 131 1.1.1.2 haad mda1 ? xlate64(pvhdr->disk_areas_xl[mda1].size) >> SECTOR_SHIFT : 0, 132 1.1.1.2 haad mda1 ? "s)" : "", 133 1.1.1.2 haad mda2 ? " mda2 (" : "", 134 1.1.1.2 haad mda2 ? 1 : 0, 135 1.1.1.2 haad mda2 ? xlate64(pvhdr->disk_areas_xl[mda2].offset) >> SECTOR_SHIFT : 0, 136 1.1.1.2 haad mda2 ? "s, " : "", 137 1.1.1.2 haad mda2 ? 1 : 0, 138 1.1.1.2 haad mda2 ? xlate64(pvhdr->disk_areas_xl[mda2].size) >> SECTOR_SHIFT : 0, 139 1.1.1.2 haad mda2 ? "s)" : ""); 140 1.1.1.2 haad 141 1.1.1.2 haad if (da1 < 0) { 142 1.1.1.2 haad log_error("Internal error: %s label header currently requires " 143 1.1.1.2 haad "a data area.", dev_name(info->dev)); 144 1.1.1.2 haad return 0; 145 1.1.1.2 haad } 146 1.1.1.2 haad 147 1.1 haad return 1; 148 1.1 haad } 149 1.1 haad 150 1.1 haad int add_da(struct dm_pool *mem, struct dm_list *das, 151 1.1 haad uint64_t start, uint64_t size) 152 1.1 haad { 153 1.1 haad struct data_area_list *dal; 154 1.1 haad 155 1.1 haad if (!mem) { 156 1.1 haad if (!(dal = dm_malloc(sizeof(*dal)))) { 157 1.1 haad log_error("struct data_area_list allocation failed"); 158 1.1 haad return 0; 159 1.1 haad } 160 1.1 haad } else { 161 1.1 haad if (!(dal = dm_pool_alloc(mem, sizeof(*dal)))) { 162 1.1 haad log_error("struct data_area_list allocation failed"); 163 1.1 haad return 0; 164 1.1 haad } 165 1.1 haad } 166 1.1 haad 167 1.1 haad dal->disk_locn.offset = start; 168 1.1 haad dal->disk_locn.size = size; 169 1.1 haad 170 1.1 haad dm_list_add(das, &dal->list); 171 1.1 haad 172 1.1 haad return 1; 173 1.1 haad } 174 1.1 haad 175 1.1 haad void del_das(struct dm_list *das) 176 1.1 haad { 177 1.1 haad struct dm_list *dah, *tmp; 178 1.1 haad struct data_area_list *da; 179 1.1 haad 180 1.1 haad dm_list_iterate_safe(dah, tmp, das) { 181 1.1 haad da = dm_list_item(dah, struct data_area_list); 182 1.1 haad dm_list_del(&da->list); 183 1.1 haad dm_free(da); 184 1.1 haad } 185 1.1 haad } 186 1.1 haad 187 1.1 haad int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct dm_list *mdas, 188 1.1 haad struct device *dev, uint64_t start, uint64_t size) 189 1.1 haad { 190 1.1 haad /* FIXME List size restricted by pv_header SECTOR_SIZE */ 191 1.1 haad struct metadata_area *mdal; 192 1.1 haad struct mda_lists *mda_lists = (struct mda_lists *) fmt->private; 193 1.1 haad struct mda_context *mdac; 194 1.1 haad 195 1.1 haad if (!mem) { 196 1.1 haad if (!(mdal = dm_malloc(sizeof(struct metadata_area)))) { 197 1.1 haad log_error("struct mda_list allocation failed"); 198 1.1 haad return 0; 199 1.1 haad } 200 1.1 haad 201 1.1 haad if (!(mdac = dm_malloc(sizeof(struct mda_context)))) { 202 1.1 haad log_error("struct mda_context allocation failed"); 203 1.1 haad dm_free(mdal); 204 1.1 haad return 0; 205 1.1 haad } 206 1.1 haad } else { 207 1.1 haad if (!(mdal = dm_pool_alloc(mem, sizeof(struct metadata_area)))) { 208 1.1 haad log_error("struct mda_list allocation failed"); 209 1.1 haad return 0; 210 1.1 haad } 211 1.1 haad 212 1.1 haad if (!(mdac = dm_pool_alloc(mem, sizeof(struct mda_context)))) { 213 1.1 haad log_error("struct mda_context allocation failed"); 214 1.1 haad return 0; 215 1.1 haad } 216 1.1 haad } 217 1.1 haad 218 1.1 haad mdal->ops = mda_lists->raw_ops; 219 1.1 haad mdal->metadata_locn = mdac; 220 1.1 haad 221 1.1 haad mdac->area.dev = dev; 222 1.1 haad mdac->area.start = start; 223 1.1 haad mdac->area.size = size; 224 1.1 haad mdac->free_sectors = UINT64_C(0); 225 1.1 haad memset(&mdac->rlocn, 0, sizeof(mdac->rlocn)); 226 1.1 haad 227 1.1 haad dm_list_add(mdas, &mdal->list); 228 1.1 haad return 1; 229 1.1 haad } 230 1.1 haad 231 1.1 haad void del_mdas(struct dm_list *mdas) 232 1.1 haad { 233 1.1 haad struct dm_list *mdah, *tmp; 234 1.1 haad struct metadata_area *mda; 235 1.1 haad 236 1.1 haad dm_list_iterate_safe(mdah, tmp, mdas) { 237 1.1 haad mda = dm_list_item(mdah, struct metadata_area); 238 1.1 haad dm_free(mda->metadata_locn); 239 1.1 haad dm_list_del(&mda->list); 240 1.1 haad dm_free(mda); 241 1.1 haad } 242 1.1 haad } 243 1.1 haad 244 1.1 haad static int _text_initialise_label(struct labeller *l __attribute((unused)), 245 1.1 haad struct label *label) 246 1.1 haad { 247 1.1 haad strncpy(label->type, LVM2_LABEL, sizeof(label->type)); 248 1.1 haad 249 1.1 haad return 1; 250 1.1 haad } 251 1.1 haad 252 1.1 haad static int _text_read(struct labeller *l, struct device *dev, void *buf, 253 1.1 haad struct label **label) 254 1.1 haad { 255 1.1 haad struct label_header *lh = (struct label_header *) buf; 256 1.1 haad struct pv_header *pvhdr; 257 1.1 haad struct lvmcache_info *info; 258 1.1 haad struct disk_locn *dlocn_xl; 259 1.1 haad uint64_t offset; 260 1.1 haad struct metadata_area *mda; 261 1.1 haad struct id vgid; 262 1.1 haad struct mda_context *mdac; 263 1.1 haad const char *vgname; 264 1.1 haad uint32_t vgstatus; 265 1.1 haad char *creation_host; 266 1.1 haad 267 1.1 haad pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); 268 1.1 haad 269 1.1 haad if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev, 270 1.1 haad FMT_TEXT_ORPHAN_VG_NAME, 271 1.1 haad FMT_TEXT_ORPHAN_VG_NAME, 0))) 272 1.1 haad return_0; 273 1.1 haad *label = info->label; 274 1.1 haad 275 1.1 haad info->device_size = xlate64(pvhdr->device_size_xl); 276 1.1 haad 277 1.1 haad if (info->das.n) 278 1.1 haad del_das(&info->das); 279 1.1 haad dm_list_init(&info->das); 280 1.1 haad 281 1.1 haad if (info->mdas.n) 282 1.1 haad del_mdas(&info->mdas); 283 1.1 haad dm_list_init(&info->mdas); 284 1.1 haad 285 1.1 haad /* Data areas holding the PEs */ 286 1.1 haad dlocn_xl = pvhdr->disk_areas_xl; 287 1.1 haad while ((offset = xlate64(dlocn_xl->offset))) { 288 1.1 haad add_da(NULL, &info->das, offset, 289 1.1 haad xlate64(dlocn_xl->size)); 290 1.1 haad dlocn_xl++; 291 1.1 haad } 292 1.1 haad 293 1.1 haad /* Metadata area headers */ 294 1.1 haad dlocn_xl++; 295 1.1 haad while ((offset = xlate64(dlocn_xl->offset))) { 296 1.1 haad add_mda(info->fmt, NULL, &info->mdas, dev, offset, 297 1.1 haad xlate64(dlocn_xl->size)); 298 1.1 haad dlocn_xl++; 299 1.1 haad } 300 1.1 haad 301 1.1 haad dm_list_iterate_items(mda, &info->mdas) { 302 1.1 haad mdac = (struct mda_context *) mda->metadata_locn; 303 1.1 haad if ((vgname = vgname_from_mda(info->fmt, &mdac->area, 304 1.1 haad &vgid, &vgstatus, &creation_host, 305 1.1 haad &mdac->free_sectors)) && 306 1.1 haad !lvmcache_update_vgname_and_id(info, vgname, 307 1.1 haad (char *) &vgid, vgstatus, 308 1.1 haad creation_host)) 309 1.1 haad return_0; 310 1.1 haad } 311 1.1 haad 312 1.1 haad info->status &= ~CACHE_INVALID; 313 1.1 haad 314 1.1 haad return 1; 315 1.1 haad } 316 1.1 haad 317 1.1 haad static void _text_destroy_label(struct labeller *l __attribute((unused)), 318 1.1 haad struct label *label) 319 1.1 haad { 320 1.1 haad struct lvmcache_info *info = (struct lvmcache_info *) label->info; 321 1.1 haad 322 1.1 haad if (info->mdas.n) 323 1.1 haad del_mdas(&info->mdas); 324 1.1 haad if (info->das.n) 325 1.1 haad del_das(&info->das); 326 1.1 haad } 327 1.1 haad 328 1.1 haad static void _fmt_text_destroy(struct labeller *l) 329 1.1 haad { 330 1.1 haad dm_free(l); 331 1.1 haad } 332 1.1 haad 333 1.1 haad struct label_ops _text_ops = { 334 1.1 haad .can_handle = _text_can_handle, 335 1.1 haad .write = _text_write, 336 1.1 haad .read = _text_read, 337 1.1 haad .verify = _text_can_handle, 338 1.1 haad .initialise_label = _text_initialise_label, 339 1.1 haad .destroy_label = _text_destroy_label, 340 1.1 haad .destroy = _fmt_text_destroy, 341 1.1 haad }; 342 1.1 haad 343 1.1 haad struct labeller *text_labeller_create(const struct format_type *fmt) 344 1.1 haad { 345 1.1 haad struct labeller *l; 346 1.1 haad 347 1.1 haad if (!(l = dm_malloc(sizeof(*l)))) { 348 1.1.1.2 haad log_error("Couldn't allocate labeller object."); 349 1.1 haad return NULL; 350 1.1 haad } 351 1.1 haad 352 1.1 haad l->ops = &_text_ops; 353 1.1 haad l->private = (const void *) fmt; 354 1.1 haad 355 1.1 haad return l; 356 1.1 haad } 357