Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / format_text / format-text.c
blobfcae511522244a02b1fad42ca67061c235ebc555
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
18 #include "lib.h"
19 #include "format-text.h"
20 #include "import-export.h"
21 #include "device.h"
22 #include "lvm-file.h"
23 #include "config.h"
24 #include "display.h"
25 #include "toolcontext.h"
26 #include "lvm-string.h"
27 #include "uuid.h"
28 #include "layout.h"
29 #include "crc.h"
30 #include "xlate.h"
31 #include "label.h"
32 #include "memlock.h"
33 #include "lvmcache.h"
35 #include <unistd.h>
36 #include <sys/file.h>
37 #include <sys/param.h>
38 #include <limits.h>
39 #include <dirent.h>
40 #include <ctype.h>
42 static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
43 struct device_area *dev_area);
45 static struct format_instance *_text_create_text_instance(const struct format_type
46 *fmt, const char *vgname,
47 const char *vgid,
48 void *context);
50 struct text_fid_context {
51 char *raw_metadata_buf;
52 uint32_t raw_metadata_buf_size;
55 struct dir_list {
56 struct dm_list list;
57 char dir[0];
60 struct raw_list {
61 struct dm_list list;
62 struct device_area dev_area;
65 struct text_context {
66 char *path_live; /* Path to file holding live metadata */
67 char *path_edit; /* Path to file holding edited metadata */
68 char *desc; /* Description placed inside file */
72 * NOTE: Currently there can be only one vg per text file.
75 static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
76 struct volume_group *vg)
78 if (vg->extent_size & (vg->extent_size - 1)) {
79 log_error("Extent size must be power of 2");
80 return 0;
83 return 1;
86 static uint64_t _mda_free_sectors_raw(struct metadata_area *mda)
88 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
90 return mdac->free_sectors;
93 static uint64_t _mda_total_sectors_raw(struct metadata_area *mda)
95 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
97 return mdac->area.size >> SECTOR_SHIFT;
101 * Check if metadata area belongs to vg
103 static int _mda_in_vg_raw(struct format_instance *fid __attribute((unused)),
104 struct volume_group *vg, struct metadata_area *mda)
106 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
107 struct pv_list *pvl;
109 dm_list_iterate_items(pvl, &vg->pvs)
110 if (pvl->pv->dev == mdac->area.dev)
111 return 1;
113 return 0;
117 * For circular region between region_start and region_start + region_size,
118 * back up one SECTOR_SIZE from 'region_ptr' and return the value.
119 * This allows reverse traversal through text metadata area to find old
120 * metadata.
122 * Parameters:
123 * region_start: start of the region (bytes)
124 * region_size: size of the region (bytes)
125 * region_ptr: pointer within the region (bytes)
126 * NOTE: region_start <= region_ptr <= region_start + region_size
128 static uint64_t _get_prev_sector_circular(uint64_t region_start,
129 uint64_t region_size,
130 uint64_t region_ptr)
132 if (region_ptr >= region_start + SECTOR_SIZE)
133 return region_ptr - SECTOR_SIZE;
134 else
135 return (region_start + region_size - SECTOR_SIZE);
139 * Analyze a metadata area for old metadata records in the circular buffer.
140 * This function just looks through and makes a first pass at the data in
141 * the sectors for particular things.
142 * FIXME: do something with each metadata area (try to extract vg, write
143 * raw data to file, etc)
145 static int _pv_analyze_mda_raw (const struct format_type * fmt,
146 struct metadata_area *mda)
148 struct mda_header *mdah;
149 struct raw_locn *rlocn;
150 uint64_t area_start;
151 uint64_t area_size;
152 uint64_t prev_sector, prev_sector2;
153 uint64_t latest_mrec_offset;
154 int i;
155 uint64_t offset;
156 uint64_t offset2;
157 size_t size;
158 size_t size2;
159 char *buf=NULL;
160 struct device_area *area;
161 struct mda_context *mdac;
162 int r=0;
164 mdac = (struct mda_context *) mda->metadata_locn;
166 log_print("Found text metadata area: offset=%" PRIu64 ", size=%"
167 PRIu64, mdac->area.start, mdac->area.size);
168 area = &mdac->area;
170 if (!dev_open(area->dev))
171 return_0;
173 if (!(mdah = _raw_read_mda_header(fmt, area)))
174 goto_out;
176 rlocn = mdah->raw_locns;
179 * The device area includes the metadata header as well as the
180 * records, so remove the metadata header from the start and size
182 area_start = area->start + MDA_HEADER_SIZE;
183 area_size = area->size - MDA_HEADER_SIZE;
184 latest_mrec_offset = rlocn->offset + area->start;
187 * Start searching at rlocn (point of live metadata) and go
188 * backwards.
190 prev_sector = _get_prev_sector_circular(area_start, area_size,
191 latest_mrec_offset);
192 offset = prev_sector;
193 size = SECTOR_SIZE;
194 offset2 = size2 = 0;
195 i = 0;
196 while (prev_sector != latest_mrec_offset) {
197 prev_sector2 = prev_sector;
198 prev_sector = _get_prev_sector_circular(area_start, area_size,
199 prev_sector);
200 if (prev_sector > prev_sector2)
201 goto_out;
203 * FIXME: for some reason, the whole metadata region from
204 * area->start to area->start+area->size is not used.
205 * Only ~32KB seems to contain valid metadata records
206 * (LVM2 format - format_text). As a result, I end up with
207 * "maybe_config_section" returning true when there's no valid
208 * metadata in a sector (sectors with all nulls).
210 if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2)))
211 goto_out;
213 if (!dev_read_circular(area->dev, offset, size,
214 offset2, size2, buf))
215 goto_out;
218 * FIXME: We could add more sophisticated metadata detection
220 if (maybe_config_section(buf, size + size2)) {
221 /* FIXME: Validate region, pull out timestamp?, etc */
222 /* FIXME: Do something with this region */
223 log_verbose ("Found LVM2 metadata record at "
224 "offset=%"PRIu64", size=%"PRIsize_t", "
225 "offset2=%"PRIu64" size2=%"PRIsize_t,
226 offset, size, offset2, size2);
227 offset = prev_sector;
228 size = SECTOR_SIZE;
229 offset2 = size2 = 0;
230 } else {
232 * Not a complete metadata record, assume we have
233 * metadata and just increase the size and offset.
234 * Start the second region if the previous sector is
235 * wrapping around towards the end of the disk.
237 if (prev_sector > offset) {
238 offset2 = prev_sector;
239 size2 += SECTOR_SIZE;
240 } else {
241 offset = prev_sector;
242 size += SECTOR_SIZE;
245 dm_pool_free(fmt->cmd->mem, buf);
246 buf = NULL;
249 r = 1;
250 out:
251 if (buf)
252 dm_pool_free(fmt->cmd->mem, buf);
253 if (!dev_close(area->dev))
254 stack;
255 return r;
260 static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
261 struct logical_volume *lv)
263 /******** FIXME Any LV size restriction?
264 uint64_t max_size = UINT_MAX;
266 if (lv->size > max_size) {
267 char *dummy = display_size(max_size);
268 log_error("logical volumes cannot be larger than %s", dummy);
269 dm_free(dummy);
270 return 0;
274 if (!*lv->lvid.s && !lvid_create(&lv->lvid, &lv->vg->id)) {
275 log_error("Random lvid creation failed for %s/%s.",
276 lv->vg->name, lv->name);
277 return 0;
280 return 1;
283 static void _xlate_mdah(struct mda_header *mdah)
285 struct raw_locn *rl;
287 mdah->version = xlate32(mdah->version);
288 mdah->start = xlate64(mdah->start);
289 mdah->size = xlate64(mdah->size);
291 rl = &mdah->raw_locns[0];
292 while (rl->offset) {
293 rl->checksum = xlate32(rl->checksum);
294 rl->offset = xlate64(rl->offset);
295 rl->size = xlate64(rl->size);
296 rl++;
300 static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
301 struct device_area *dev_area)
303 struct mda_header *mdah;
305 if (!(mdah = dm_pool_alloc(fmt->cmd->mem, MDA_HEADER_SIZE))) {
306 log_error("struct mda_header allocation failed");
307 return NULL;
310 if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah))
311 goto_bad;
313 if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, mdah->magic,
314 MDA_HEADER_SIZE -
315 sizeof(mdah->checksum_xl)))) {
316 log_error("Incorrect metadata area header checksum");
317 goto bad;
320 _xlate_mdah(mdah);
322 if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
323 log_error("Wrong magic number in metadata area header");
324 goto bad;
327 if (mdah->version != FMTT_VERSION) {
328 log_error("Incompatible metadata area header version: %d",
329 mdah->version);
330 goto bad;
333 if (mdah->start != dev_area->start) {
334 log_error("Incorrect start sector in metadata area header: %"
335 PRIu64, mdah->start);
336 goto bad;
339 return mdah;
341 bad:
342 dm_pool_free(fmt->cmd->mem, mdah);
343 return NULL;
346 static int _raw_write_mda_header(const struct format_type *fmt,
347 struct device *dev,
348 uint64_t start_byte, struct mda_header *mdah)
350 strncpy((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic));
351 mdah->version = FMTT_VERSION;
352 mdah->start = start_byte;
354 _xlate_mdah(mdah);
355 mdah->checksum_xl = xlate32(calc_crc(INITIAL_CRC, mdah->magic,
356 MDA_HEADER_SIZE -
357 sizeof(mdah->checksum_xl)));
359 if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah))
360 return_0;
362 return 1;
365 static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
366 struct mda_header *mdah,
367 const char *vgname,
368 int *precommitted)
370 size_t len;
371 char vgnamebuf[NAME_LEN + 2] __attribute((aligned(8)));
372 struct raw_locn *rlocn, *rlocn_precommitted;
373 struct lvmcache_info *info;
375 rlocn = mdah->raw_locns; /* Slot 0 */
376 rlocn_precommitted = rlocn + 1; /* Slot 1 */
378 /* Should we use precommitted metadata? */
379 if (*precommitted && rlocn_precommitted->size &&
380 (rlocn_precommitted->offset != rlocn->offset)) {
381 rlocn = rlocn_precommitted;
382 } else
383 *precommitted = 0;
385 /* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
386 /* FIXME Ignore if checksum incorrect!!! */
387 if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
388 sizeof(vgnamebuf), vgnamebuf))
389 goto_bad;
391 if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
392 (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
393 return rlocn;
396 bad:
397 if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
398 lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
399 FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
401 return NULL;
405 * Determine offset for uncommitted metadata
407 static uint64_t _next_rlocn_offset(struct raw_locn *rlocn,
408 struct mda_header *mdah)
410 if (!rlocn)
411 /* Find an empty slot */
412 /* FIXME Assume only one VG per mdah for now */
413 return MDA_HEADER_SIZE;
415 /* Start of free space - round up to next sector; circular */
416 return ((rlocn->offset + rlocn->size +
417 (SECTOR_SIZE - rlocn->size % SECTOR_SIZE) -
418 MDA_HEADER_SIZE) % (mdah->size - MDA_HEADER_SIZE))
419 + MDA_HEADER_SIZE;
422 static int _raw_holds_vgname(struct format_instance *fid,
423 struct device_area *dev_area, const char *vgname)
425 int r = 0;
426 int noprecommit = 0;
427 struct mda_header *mdah;
429 if (!dev_open(dev_area->dev))
430 return_0;
432 if (!(mdah = _raw_read_mda_header(fid->fmt, dev_area)))
433 return_0;
435 if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit))
436 r = 1;
438 if (!dev_close(dev_area->dev))
439 stack;
441 return r;
444 static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
445 const char *vgname,
446 struct device_area *area,
447 int precommitted)
449 struct volume_group *vg = NULL;
450 struct raw_locn *rlocn;
451 struct mda_header *mdah;
452 time_t when;
453 char *desc;
454 uint32_t wrap = 0;
456 if (!dev_open(area->dev))
457 return_NULL;
459 if (!(mdah = _raw_read_mda_header(fid->fmt, area)))
460 goto_out;
462 if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
463 log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
464 goto out;
467 if (rlocn->offset + rlocn->size > mdah->size)
468 wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
470 if (wrap > rlocn->offset) {
471 log_error("VG %s metadata too large for circular buffer",
472 vg->name);
473 goto out;
476 /* FIXME 64-bit */
477 if (!(vg = text_vg_import_fd(fid, NULL, area->dev,
478 (off_t) (area->start + rlocn->offset),
479 (uint32_t) (rlocn->size - wrap),
480 (off_t) (area->start + MDA_HEADER_SIZE),
481 wrap, calc_crc, rlocn->checksum, &when,
482 &desc)))
483 goto_out;
484 log_debug("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
485 PRIu64, vg->name, precommitted ? "pre-commit " : "",
486 vg->seqno, dev_name(area->dev),
487 area->start + rlocn->offset, rlocn->size);
489 if (precommitted)
490 vg->status |= PRECOMMITTED;
492 out:
493 if (!dev_close(area->dev))
494 stack;
496 return vg;
499 static struct volume_group *_vg_read_raw(struct format_instance *fid,
500 const char *vgname,
501 struct metadata_area *mda)
503 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
505 return _vg_read_raw_area(fid, vgname, &mdac->area, 0);
508 static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
509 const char *vgname,
510 struct metadata_area *mda)
512 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
514 return _vg_read_raw_area(fid, vgname, &mdac->area, 1);
517 static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
518 struct metadata_area *mda)
520 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
521 struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
522 struct raw_locn *rlocn;
523 struct mda_header *mdah;
524 struct pv_list *pvl;
525 int r = 0;
526 uint64_t new_wrap = 0, old_wrap = 0, new_end;
527 int found = 0;
528 int noprecommit = 0;
530 /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
531 dm_list_iterate_items(pvl, &vg->pvs) {
532 if (pvl->pv->dev == mdac->area.dev) {
533 found = 1;
534 break;
538 if (!found)
539 return 1;
541 if (!dev_open(mdac->area.dev))
542 return_0;
544 if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
545 goto_out;
547 rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit);
548 mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
550 if (!fidtc->raw_metadata_buf &&
551 !(fidtc->raw_metadata_buf_size =
552 text_vg_export_raw(vg, "", &fidtc->raw_metadata_buf))) {
553 log_error("VG %s metadata writing failed", vg->name);
554 goto out;
557 mdac->rlocn.size = fidtc->raw_metadata_buf_size;
559 if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size)
560 new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size;
562 if (rlocn && (rlocn->offset + rlocn->size > mdah->size))
563 old_wrap = (rlocn->offset + rlocn->size) - mdah->size;
565 new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE :
566 mdac->rlocn.offset + mdac->rlocn.size;
568 if ((new_wrap && old_wrap) ||
569 (rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset)) ||
570 (mdac->rlocn.size >= mdah->size)) {
571 log_error("VG %s metadata too large for circular buffer",
572 vg->name);
573 goto out;
576 log_debug("Writing %s metadata to %s at %" PRIu64 " len %" PRIu64,
577 vg->name, dev_name(mdac->area.dev), mdac->area.start +
578 mdac->rlocn.offset, mdac->rlocn.size - new_wrap);
580 /* Write text out, circularly */
581 if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
582 (size_t) (mdac->rlocn.size - new_wrap),
583 fidtc->raw_metadata_buf))
584 goto_out;
586 if (new_wrap) {
587 log_debug("Writing metadata to %s at %" PRIu64 " len %" PRIu64,
588 dev_name(mdac->area.dev), mdac->area.start +
589 MDA_HEADER_SIZE, new_wrap);
591 if (!dev_write(mdac->area.dev,
592 mdac->area.start + MDA_HEADER_SIZE,
593 (size_t) new_wrap,
594 fidtc->raw_metadata_buf +
595 mdac->rlocn.size - new_wrap))
596 goto_out;
599 mdac->rlocn.checksum = calc_crc(INITIAL_CRC, fidtc->raw_metadata_buf,
600 (uint32_t) (mdac->rlocn.size -
601 new_wrap));
602 if (new_wrap)
603 mdac->rlocn.checksum = calc_crc(mdac->rlocn.checksum,
604 fidtc->raw_metadata_buf +
605 mdac->rlocn.size -
606 new_wrap, (uint32_t) new_wrap);
608 r = 1;
610 out:
611 if (!r) {
612 if (!dev_close(mdac->area.dev))
613 stack;
615 if (fidtc->raw_metadata_buf) {
616 dm_free(fidtc->raw_metadata_buf);
617 fidtc->raw_metadata_buf = NULL;
621 return r;
624 static int _vg_commit_raw_rlocn(struct format_instance *fid,
625 struct volume_group *vg,
626 struct metadata_area *mda,
627 int precommit)
629 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
630 struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
631 struct mda_header *mdah;
632 struct raw_locn *rlocn;
633 struct pv_list *pvl;
634 int r = 0;
635 int found = 0;
636 int noprecommit = 0;
638 /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
639 dm_list_iterate_items(pvl, &vg->pvs) {
640 if (pvl->pv->dev == mdac->area.dev) {
641 found = 1;
642 break;
646 if (!found)
647 return 1;
649 if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
650 goto_out;
652 if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
653 mdah->raw_locns[0].offset = 0;
654 mdah->raw_locns[0].size = 0;
655 mdah->raw_locns[0].checksum = 0;
656 mdah->raw_locns[1].offset = 0;
657 mdah->raw_locns[1].size = 0;
658 mdah->raw_locns[1].checksum = 0;
659 mdah->raw_locns[2].offset = 0;
660 mdah->raw_locns[2].size = 0;
661 mdah->raw_locns[2].checksum = 0;
662 rlocn = &mdah->raw_locns[0];
665 if (precommit)
666 rlocn++;
667 else {
668 /* If not precommitting, wipe the precommitted rlocn */
669 mdah->raw_locns[1].offset = 0;
670 mdah->raw_locns[1].size = 0;
671 mdah->raw_locns[1].checksum = 0;
674 /* Is there new metadata to commit? */
675 if (mdac->rlocn.size) {
676 rlocn->offset = mdac->rlocn.offset;
677 rlocn->size = mdac->rlocn.size;
678 rlocn->checksum = mdac->rlocn.checksum;
679 log_debug("%sCommitting %s metadata (%u) to %s header at %"
680 PRIu64, precommit ? "Pre-" : "", vg->name, vg->seqno,
681 dev_name(mdac->area.dev), mdac->area.start);
682 } else
683 log_debug("Wiping pre-committed %s metadata from %s "
684 "header at %" PRIu64, vg->name,
685 dev_name(mdac->area.dev), mdac->area.start);
687 if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
688 mdah)) {
689 dm_pool_free(fid->fmt->cmd->mem, mdah);
690 log_error("Failed to write metadata area header");
691 goto out;
694 r = 1;
696 out:
697 if (!precommit) {
698 if (!dev_close(mdac->area.dev))
699 stack;
700 if (fidtc->raw_metadata_buf) {
701 dm_free(fidtc->raw_metadata_buf);
702 fidtc->raw_metadata_buf = NULL;
706 return r;
709 static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
710 struct metadata_area *mda)
712 return _vg_commit_raw_rlocn(fid, vg, mda, 0);
715 static int _vg_precommit_raw(struct format_instance *fid,
716 struct volume_group *vg,
717 struct metadata_area *mda)
719 return _vg_commit_raw_rlocn(fid, vg, mda, 1);
722 /* Close metadata area devices */
723 static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
724 struct metadata_area *mda)
726 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
727 struct pv_list *pvl;
728 int found = 0;
730 /* Ignore any mda on a PV outside the VG. vgsplit relies on this */
731 dm_list_iterate_items(pvl, &vg->pvs) {
732 if (pvl->pv->dev == mdac->area.dev) {
733 found = 1;
734 break;
738 if (!found)
739 return 1;
741 /* Wipe pre-committed metadata */
742 mdac->rlocn.size = 0;
743 return _vg_commit_raw_rlocn(fid, vg, mda, 0);
746 static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
747 struct metadata_area *mda)
749 struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
750 struct mda_header *mdah;
751 struct raw_locn *rlocn;
752 int r = 0;
753 int noprecommit = 0;
755 if (!dev_open(mdac->area.dev))
756 return_0;
758 if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
759 goto_out;
761 if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
762 rlocn = &mdah->raw_locns[0];
763 mdah->raw_locns[1].offset = 0;
766 rlocn->offset = 0;
767 rlocn->size = 0;
768 rlocn->checksum = 0;
770 if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
771 mdah)) {
772 dm_pool_free(fid->fmt->cmd->mem, mdah);
773 log_error("Failed to write metadata area header");
774 goto out;
777 r = 1;
779 out:
780 if (!dev_close(mdac->area.dev))
781 stack;
783 return r;
786 static struct volume_group *_vg_read_file_name(struct format_instance *fid,
787 const char *vgname,
788 const char *read_path)
790 struct volume_group *vg;
791 time_t when;
792 char *desc;
794 if (!(vg = text_vg_import_file(fid, read_path, &when, &desc)))
795 return_NULL;
798 * Currently you can only have a single volume group per
799 * text file (this restriction may remain). We need to
800 * check that it contains the correct volume group.
802 if (vgname && strcmp(vgname, vg->name)) {
803 dm_pool_free(fid->fmt->cmd->mem, vg);
804 log_error("'%s' does not contain volume group '%s'.",
805 read_path, vgname);
806 return NULL;
807 } else
808 log_debug("Read volume group %s from %s", vg->name, read_path);
810 return vg;
813 static struct volume_group *_vg_read_file(struct format_instance *fid,
814 const char *vgname,
815 struct metadata_area *mda)
817 struct text_context *tc = (struct text_context *) mda->metadata_locn;
819 return _vg_read_file_name(fid, vgname, tc->path_live);
822 static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
823 const char *vgname,
824 struct metadata_area *mda)
826 struct text_context *tc = (struct text_context *) mda->metadata_locn;
827 struct volume_group *vg;
829 if ((vg = _vg_read_file_name(fid, vgname, tc->path_edit)))
830 vg->status |= PRECOMMITTED;
831 else
832 vg = _vg_read_file_name(fid, vgname, tc->path_live);
834 return vg;
837 static int _vg_write_file(struct format_instance *fid __attribute((unused)),
838 struct volume_group *vg, struct metadata_area *mda)
840 struct text_context *tc = (struct text_context *) mda->metadata_locn;
842 FILE *fp;
843 int fd;
844 char *slash;
845 char temp_file[PATH_MAX], temp_dir[PATH_MAX];
847 slash = strrchr(tc->path_edit, '/');
849 if (slash == 0)
850 strcpy(temp_dir, ".");
851 else if (slash - tc->path_edit < PATH_MAX) {
852 strncpy(temp_dir, tc->path_edit,
853 (size_t) (slash - tc->path_edit));
854 temp_dir[slash - tc->path_edit] = '\0';
856 } else {
857 log_error("Text format failed to determine directory.");
858 return 0;
861 if (!create_temp_name(temp_dir, temp_file, sizeof(temp_file), &fd,
862 &vg->cmd->rand_seed)) {
863 log_error("Couldn't create temporary text file name.");
864 return 0;
867 if (!(fp = fdopen(fd, "w"))) {
868 log_sys_error("fdopen", temp_file);
869 if (close(fd))
870 log_sys_error("fclose", temp_file);
871 return 0;
874 log_debug("Writing %s metadata to %s", vg->name, temp_file);
876 if (!text_vg_export_file(vg, tc->desc, fp)) {
877 log_error("Failed to write metadata to %s.", temp_file);
878 if (fclose(fp))
879 log_sys_error("fclose", temp_file);
880 return 0;
883 if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
884 log_sys_error("fsync", tc->path_edit);
885 if (fclose(fp))
886 log_sys_error("fclose", tc->path_edit);
887 return 0;
890 if (lvm_fclose(fp, tc->path_edit))
891 return_0;
893 if (rename(temp_file, tc->path_edit)) {
894 log_debug("Renaming %s to %s", temp_file, tc->path_edit);
895 log_error("%s: rename to %s failed: %s", temp_file,
896 tc->path_edit, strerror(errno));
897 return 0;
900 return 1;
903 static int _vg_commit_file_backup(struct format_instance *fid __attribute((unused)),
904 struct volume_group *vg,
905 struct metadata_area *mda)
907 struct text_context *tc = (struct text_context *) mda->metadata_locn;
909 if (test_mode()) {
910 log_verbose("Test mode: Skipping committing %s metadata (%u)",
911 vg->name, vg->seqno);
912 if (unlink(tc->path_edit)) {
913 log_debug("Unlinking %s", tc->path_edit);
914 log_sys_error("unlink", tc->path_edit);
915 return 0;
917 } else {
918 log_debug("Committing %s metadata (%u)", vg->name, vg->seqno);
919 log_debug("Renaming %s to %s", tc->path_edit, tc->path_live);
920 if (rename(tc->path_edit, tc->path_live)) {
921 log_error("%s: rename to %s failed: %s", tc->path_edit,
922 tc->path_live, strerror(errno));
923 return 0;
927 sync_dir(tc->path_edit);
929 return 1;
932 static int _vg_commit_file(struct format_instance *fid, struct volume_group *vg,
933 struct metadata_area *mda)
935 struct text_context *tc = (struct text_context *) mda->metadata_locn;
936 char *slash;
937 char new_name[PATH_MAX];
938 size_t len;
940 if (!_vg_commit_file_backup(fid, vg, mda))
941 return 0;
943 /* vgrename? */
944 if ((slash = strrchr(tc->path_live, '/')))
945 slash = slash + 1;
946 else
947 slash = tc->path_live;
949 if (strcmp(slash, vg->name)) {
950 len = slash - tc->path_live;
951 strncpy(new_name, tc->path_live, len);
952 strcpy(new_name + len, vg->name);
953 log_debug("Renaming %s to %s", tc->path_live, new_name);
954 if (test_mode())
955 log_verbose("Test mode: Skipping rename");
956 else {
957 if (rename(tc->path_live, new_name)) {
958 log_error("%s: rename to %s failed: %s",
959 tc->path_live, new_name,
960 strerror(errno));
961 sync_dir(new_name);
962 return 0;
967 return 1;
970 static int _vg_remove_file(struct format_instance *fid __attribute((unused)),
971 struct volume_group *vg __attribute((unused)),
972 struct metadata_area *mda)
974 struct text_context *tc = (struct text_context *) mda->metadata_locn;
976 if (path_exists(tc->path_edit) && unlink(tc->path_edit)) {
977 log_sys_error("unlink", tc->path_edit);
978 return 0;
981 if (path_exists(tc->path_live) && unlink(tc->path_live)) {
982 log_sys_error("unlink", tc->path_live);
983 return 0;
986 sync_dir(tc->path_live);
988 return 1;
991 static int _scan_file(const struct format_type *fmt)
993 struct dirent *dirent;
994 struct dir_list *dl;
995 struct dm_list *dir_list;
996 char *tmp;
997 DIR *d;
998 struct volume_group *vg;
999 struct format_instance *fid;
1000 char path[PATH_MAX];
1001 char *vgname;
1003 dir_list = &((struct mda_lists *) fmt->private)->dirs;
1005 dm_list_iterate_items(dl, dir_list) {
1006 if (!(d = opendir(dl->dir))) {
1007 log_sys_error("opendir", dl->dir);
1008 continue;
1010 while ((dirent = readdir(d)))
1011 if (strcmp(dirent->d_name, ".") &&
1012 strcmp(dirent->d_name, "..") &&
1013 (!(tmp = strstr(dirent->d_name, ".tmp")) ||
1014 tmp != dirent->d_name + strlen(dirent->d_name)
1015 - 4)) {
1016 vgname = dirent->d_name;
1017 if (dm_snprintf(path, PATH_MAX, "%s/%s",
1018 dl->dir, vgname) < 0) {
1019 log_error("Name too long %s/%s",
1020 dl->dir, vgname);
1021 break;
1024 /* FIXME stat file to see if it's changed */
1025 fid = _text_create_text_instance(fmt, NULL, NULL,
1026 NULL);
1027 if ((vg = _vg_read_file_name(fid, vgname,
1028 path)))
1029 /* FIXME Store creation host in vg */
1030 lvmcache_update_vg(vg, 0);
1033 if (closedir(d))
1034 log_sys_error("closedir", dl->dir);
1037 return 1;
1040 const char *vgname_from_mda(const struct format_type *fmt,
1041 struct device_area *dev_area, struct id *vgid,
1042 uint32_t *vgstatus, char **creation_host,
1043 uint64_t *mda_free_sectors)
1045 struct raw_locn *rlocn;
1046 struct mda_header *mdah;
1047 uint32_t wrap = 0;
1048 const char *vgname = NULL;
1049 unsigned int len = 0;
1050 char buf[NAME_LEN + 1] __attribute((aligned(8)));
1051 char uuid[64] __attribute((aligned(8)));
1052 uint64_t buffer_size, current_usage;
1054 if (mda_free_sectors)
1055 *mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT;
1057 if (!dev_open(dev_area->dev))
1058 return_NULL;
1060 if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
1061 goto_out;
1063 /* FIXME Cope with returning a list */
1064 rlocn = mdah->raw_locns;
1067 * If no valid offset, do not try to search for vgname
1069 if (!rlocn->offset)
1070 goto out;
1072 /* Do quick check for a vgname */
1073 if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
1074 NAME_LEN, buf))
1075 goto_out;
1077 while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
1078 len < (NAME_LEN - 1))
1079 len++;
1081 buf[len] = '\0';
1083 /* Ignore this entry if the characters aren't permissible */
1084 if (!validate_name(buf))
1085 goto_out;
1087 /* We found a VG - now check the metadata */
1088 if (rlocn->offset + rlocn->size > mdah->size)
1089 wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
1091 if (wrap > rlocn->offset) {
1092 log_error("%s: metadata too large for circular buffer",
1093 dev_name(dev_area->dev));
1094 goto out;
1097 /* FIXME 64-bit */
1098 if (!(vgname = text_vgname_import(fmt, dev_area->dev,
1099 (off_t) (dev_area->start +
1100 rlocn->offset),
1101 (uint32_t) (rlocn->size - wrap),
1102 (off_t) (dev_area->start +
1103 MDA_HEADER_SIZE),
1104 wrap, calc_crc, rlocn->checksum,
1105 vgid, vgstatus, creation_host)))
1106 goto_out;
1108 /* Ignore this entry if the characters aren't permissible */
1109 if (!validate_name(vgname)) {
1110 vgname = NULL;
1111 goto_out;
1114 if (!id_write_format(vgid, uuid, sizeof(uuid))) {
1115 vgname = NULL;
1116 goto_out;
1119 log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
1120 " (in area at %" PRIu64 " size %" PRIu64
1121 ") for %s (%s)",
1122 dev_name(dev_area->dev), dev_area->start + rlocn->offset,
1123 rlocn->size, dev_area->start, dev_area->size, vgname, uuid);
1125 if (mda_free_sectors) {
1126 current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
1127 (rlocn->size + SECTOR_SIZE - UINT64_C(1)) % SECTOR_SIZE;
1128 buffer_size = mdah->size - MDA_HEADER_SIZE;
1130 if (current_usage * 2 >= buffer_size)
1131 *mda_free_sectors = UINT64_C(0);
1132 else
1133 *mda_free_sectors = ((buffer_size - 2 * current_usage) / 2) >> SECTOR_SHIFT;
1136 out:
1137 if (!dev_close(dev_area->dev))
1138 stack;
1140 return vgname;
1143 static int _scan_raw(const struct format_type *fmt)
1145 struct raw_list *rl;
1146 struct dm_list *raw_list;
1147 const char *vgname;
1148 struct volume_group *vg;
1149 struct format_instance fid;
1150 struct id vgid;
1151 uint32_t vgstatus;
1153 raw_list = &((struct mda_lists *) fmt->private)->raws;
1155 fid.fmt = fmt;
1156 dm_list_init(&fid.metadata_areas);
1158 dm_list_iterate_items(rl, raw_list) {
1159 /* FIXME We're reading mdah twice here... */
1160 if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
1161 NULL, NULL))) {
1162 if ((vg = _vg_read_raw_area(&fid, vgname,
1163 &rl->dev_area, 0)))
1164 lvmcache_update_vg(vg, 0);
1168 return 1;
1171 static int _text_scan(const struct format_type *fmt)
1173 return (_scan_file(fmt) & _scan_raw(fmt));
1176 /* For orphan, creates new mdas according to policy.
1177 Always have an mda between end-of-label and pe_align() boundary */
1178 static int _mda_setup(const struct format_type *fmt,
1179 uint64_t pe_start, uint64_t pe_end,
1180 int pvmetadatacopies,
1181 uint64_t pvmetadatasize, struct dm_list *mdas,
1182 struct physical_volume *pv,
1183 struct volume_group *vg __attribute((unused)))
1185 uint64_t mda_adjustment, disk_size, alignment, alignment_offset;
1186 uint64_t start1, mda_size1; /* First area - start of disk */
1187 uint64_t start2, mda_size2; /* Second area - end of disk */
1188 uint64_t wipe_size = 8 << SECTOR_SHIFT;
1189 size_t pagesize = lvm_getpagesize();
1191 if (!pvmetadatacopies)
1192 return 1;
1194 alignment = pv->pe_align << SECTOR_SHIFT;
1195 alignment_offset = pv->pe_align_offset << SECTOR_SHIFT;
1196 disk_size = pv->size << SECTOR_SHIFT;
1197 pe_start <<= SECTOR_SHIFT;
1198 pe_end <<= SECTOR_SHIFT;
1200 if (pe_end > disk_size) {
1201 log_error("Physical extents end beyond end of device %s!",
1202 pv_dev_name(pv));
1203 return 0;
1206 /* Requested metadatasize */
1207 mda_size1 = pvmetadatasize << SECTOR_SHIFT;
1209 /* Place mda straight after label area at start of disk */
1210 start1 = LABEL_SCAN_SIZE;
1212 /* Unless the space available is tiny, round to PAGE_SIZE boundary */
1213 if ((!pe_start && !pe_end) ||
1214 ((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
1215 mda_adjustment = start1 % pagesize;
1216 if (mda_adjustment)
1217 start1 += (pagesize - mda_adjustment);
1220 /* Round up to pe_align boundary */
1221 mda_adjustment = (mda_size1 + start1) % alignment;
1222 if (mda_adjustment) {
1223 mda_size1 += (alignment - mda_adjustment);
1224 /* Revert if it's now too large */
1225 if (start1 + mda_size1 > disk_size)
1226 mda_size1 -= (alignment - mda_adjustment);
1229 /* Add pe_align_offset if on pe_align boundary */
1230 if (alignment_offset &&
1231 (((start1 + mda_size1) % alignment) == 0)) {
1232 mda_size1 += alignment_offset;
1233 /* Revert if it's now too large */
1234 if (start1 + mda_size1 > disk_size)
1235 mda_size1 -= alignment_offset;
1238 /* Ensure it's not going to be bigger than the disk! */
1239 if (start1 + mda_size1 > disk_size) {
1240 log_warn("WARNING: metadata area fills disk leaving no "
1241 "space for data on %s.", pv_dev_name(pv));
1242 /* Leave some free space for rounding */
1243 /* Avoid empty data area as could cause tools problems */
1244 mda_size1 = disk_size - start1 - alignment * 2;
1245 if (start1 + mda_size1 > disk_size) {
1246 log_error("Insufficient space for first mda on %s",
1247 pv_dev_name(pv));
1248 return 0;
1250 /* Round up to pe_align boundary */
1251 mda_adjustment = (mda_size1 + start1) % alignment;
1252 if (mda_adjustment)
1253 mda_size1 += (alignment - mda_adjustment);
1254 /* Only have 1 mda in this case */
1255 pvmetadatacopies = 1;
1258 /* If we already have PEs, avoid overlap */
1259 if (pe_start || pe_end) {
1260 if (pe_start <= start1)
1261 mda_size1 = 0;
1262 else if (start1 + mda_size1 > pe_start)
1263 mda_size1 = pe_start - start1;
1266 /* FIXME If creating new mdas, wipe them! */
1267 if (mda_size1) {
1268 if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
1269 mda_size1))
1270 return 0;
1272 if (!dev_set((struct device *) pv->dev, start1,
1273 (size_t) (mda_size1 >
1274 wipe_size ? : mda_size1), 0)) {
1275 log_error("Failed to wipe new metadata area");
1276 return 0;
1279 if (pvmetadatacopies == 1)
1280 return 1;
1281 } else
1282 start1 = 0;
1284 /* A second copy at end of disk */
1285 mda_size2 = pvmetadatasize << SECTOR_SHIFT;
1287 /* Ensure it's not going to be bigger than the disk! */
1288 if (mda_size2 > disk_size)
1289 mda_size2 = disk_size - start1 - mda_size1;
1291 mda_adjustment = (disk_size - mda_size2) % alignment;
1292 if (mda_adjustment)
1293 mda_size2 += mda_adjustment;
1295 start2 = disk_size - mda_size2;
1297 /* If we already have PEs, avoid overlap */
1298 if (pe_start || pe_end) {
1299 if (start2 < pe_end) {
1300 mda_size2 -= (pe_end - start2);
1301 start2 = pe_end;
1305 /* If we already have a first mda, avoid overlap */
1306 if (mda_size1) {
1307 if (start2 < start1 + mda_size1) {
1308 mda_size2 -= (start1 + mda_size1 - start2);
1309 start2 = start1 + mda_size1;
1311 /* No room for any PEs here now! */
1314 if (mda_size2) {
1315 if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
1316 mda_size2)) return 0;
1317 if (!dev_set(pv->dev, start2,
1318 (size_t) (mda_size1 >
1319 wipe_size ? : mda_size1), 0)) {
1320 log_error("Failed to wipe new metadata area");
1321 return 0;
1323 } else
1324 return 0;
1326 return 1;
1329 /* Only for orphans */
1330 /* Set label_sector to -1 if rewriting existing label into same sector */
1331 /* If mdas is supplied it overwrites existing mdas e.g. used with pvcreate */
1332 static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
1333 struct dm_list *mdas, int64_t label_sector)
1335 struct label *label;
1336 struct lvmcache_info *info;
1337 struct mda_context *mdac;
1338 struct metadata_area *mda;
1339 char buf[MDA_HEADER_SIZE] __attribute((aligned(8)));
1340 struct mda_header *mdah = (struct mda_header *) buf;
1341 uint64_t adjustment;
1342 struct data_area_list *da;
1344 /* FIXME Test mode don't update cache? */
1346 if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
1347 FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
1348 return_0;
1349 label = info->label;
1351 if (label_sector != -1)
1352 label->sector = label_sector;
1354 info->device_size = pv->size << SECTOR_SHIFT;
1355 info->fmt = fmt;
1357 /* If mdas supplied, use them regardless of existing ones, */
1358 /* otherwise retain existing ones */
1359 if (mdas) {
1360 if (info->mdas.n)
1361 del_mdas(&info->mdas);
1362 else
1363 dm_list_init(&info->mdas);
1364 dm_list_iterate_items(mda, mdas) {
1365 mdac = mda->metadata_locn;
1366 log_debug("Creating metadata area on %s at sector %"
1367 PRIu64 " size %" PRIu64 " sectors",
1368 dev_name(mdac->area.dev),
1369 mdac->area.start >> SECTOR_SHIFT,
1370 mdac->area.size >> SECTOR_SHIFT);
1371 add_mda(fmt, NULL, &info->mdas, mdac->area.dev,
1372 mdac->area.start, mdac->area.size);
1374 /* FIXME Temporary until mda creation supported by tools */
1375 } else if (!info->mdas.n) {
1376 dm_list_init(&info->mdas);
1380 * If no pe_start supplied but PV already exists,
1381 * get existing value; use-cases include:
1382 * - pvcreate on PV without prior pvremove
1383 * - vgremove on VG with PV(s) that have pe_start=0 (hacked cfg)
1385 if (info->das.n) {
1386 if (!pv->pe_start)
1387 dm_list_iterate_items(da, &info->das)
1388 pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
1389 del_das(&info->das);
1390 } else
1391 dm_list_init(&info->das);
1393 #if 0
1395 * FIXME: ideally a pre-existing pe_start seen in .pv_write
1396 * would always be preserved BUT 'pvcreate on PV without prior pvremove'
1397 * could easily cause the pe_start to overlap with the first mda!
1399 if (pv->pe_start) {
1400 log_very_verbose("%s: preserving pe_start=%lu",
1401 pv_dev_name(pv), pv->pe_start);
1402 goto preserve_pe_start;
1404 #endif
1407 * If pe_start is still unset, set it to first aligned
1408 * sector after any metadata areas that begin before pe_start.
1410 if (!pv->pe_start) {
1411 pv->pe_start = pv->pe_align;
1412 if (pv->pe_align_offset)
1413 pv->pe_start += pv->pe_align_offset;
1415 dm_list_iterate_items(mda, &info->mdas) {
1416 mdac = (struct mda_context *) mda->metadata_locn;
1417 if (pv->dev == mdac->area.dev &&
1418 ((mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) ||
1419 (mdac->area.start <= lvm_getpagesize() &&
1420 pv->pe_start < (lvm_getpagesize() >> SECTOR_SHIFT))) &&
1421 (mdac->area.start + mdac->area.size >
1422 (pv->pe_start << SECTOR_SHIFT))) {
1423 pv->pe_start = (mdac->area.start + mdac->area.size)
1424 >> SECTOR_SHIFT;
1425 /* Adjust pe_start to: (N * pe_align) + pe_align_offset */
1426 if (pv->pe_align) {
1427 adjustment =
1428 (pv->pe_start - pv->pe_align_offset) % pv->pe_align;
1429 if (adjustment)
1430 pv->pe_start += pv->pe_align - adjustment;
1432 log_very_verbose("%s: setting pe_start=%" PRIu64
1433 " (orig_pe_start=%" PRIu64 ", "
1434 "pe_align=%lu, pe_align_offset=%lu, "
1435 "adjustment=%" PRIu64 ")",
1436 pv_dev_name(pv), pv->pe_start,
1437 (adjustment ?
1438 pv->pe_start -= pv->pe_align - adjustment :
1439 pv->pe_start),
1440 pv->pe_align, pv->pe_align_offset, adjustment);
1444 if (pv->pe_start >= pv->size) {
1445 log_error("Data area is beyond end of device %s!",
1446 pv_dev_name(pv));
1447 return 0;
1450 /* FIXME: preserve_pe_start: */
1451 if (!add_da
1452 (NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
1453 return_0;
1455 if (!dev_open(pv->dev))
1456 return_0;
1458 dm_list_iterate_items(mda, &info->mdas) {
1459 mdac = mda->metadata_locn;
1460 memset(&buf, 0, sizeof(buf));
1461 mdah->size = mdac->area.size;
1462 if (!_raw_write_mda_header(fmt, mdac->area.dev,
1463 mdac->area.start, mdah)) {
1464 if (!dev_close(pv->dev))
1465 stack;
1466 return_0;
1470 if (!label_write(pv->dev, label)) {
1471 dev_close(pv->dev);
1472 return_0;
1475 if (!dev_close(pv->dev))
1476 return_0;
1478 return 1;
1481 static int _add_raw(struct dm_list *raw_list, struct device_area *dev_area)
1483 struct raw_list *rl;
1485 /* Already present? */
1486 dm_list_iterate_items(rl, raw_list) {
1487 /* FIXME Check size/overlap consistency too */
1488 if (rl->dev_area.dev == dev_area->dev &&
1489 rl->dev_area.start == dev_area->start)
1490 return 1;
1493 if (!(rl = dm_malloc(sizeof(struct raw_list)))) {
1494 log_error("_add_raw allocation failed");
1495 return 0;
1497 memcpy(&rl->dev_area, dev_area, sizeof(*dev_area));
1498 dm_list_add(raw_list, &rl->list);
1500 return 1;
1503 static int _get_pv_if_in_vg(struct lvmcache_info *info,
1504 struct physical_volume *pv)
1506 if (info->vginfo && info->vginfo->vgname &&
1507 !is_orphan_vg(info->vginfo->vgname) &&
1508 get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
1509 info->vginfo->vgid, info->dev->pvid, pv))
1510 return 1;
1512 return 0;
1515 static int _populate_pv_fields(struct lvmcache_info *info,
1516 struct physical_volume *pv,
1517 int scan_label_only)
1519 struct data_area_list *da;
1521 /* Have we already cached vgname? */
1522 if (!scan_label_only && _get_pv_if_in_vg(info, pv))
1523 return 1;
1525 /* Perform full scan (just the first time) and try again */
1526 if (!scan_label_only && !memlock() && !full_scan_done()) {
1527 lvmcache_label_scan(info->fmt->cmd, 2);
1529 if (_get_pv_if_in_vg(info, pv))
1530 return 1;
1533 /* Orphan */
1534 pv->dev = info->dev;
1535 pv->fmt = info->fmt;
1536 pv->size = info->device_size >> SECTOR_SHIFT;
1537 pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
1538 memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
1540 /* Currently only support exactly one data area */
1541 if (dm_list_size(&info->das) != 1) {
1542 log_error("Must be exactly one data area (found %d) on PV %s",
1543 dm_list_size(&info->das), dev_name(info->dev));
1544 return 0;
1547 dm_list_iterate_items(da, &info->das)
1548 pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
1550 return 1;
1553 static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
1554 struct physical_volume *pv, struct dm_list *mdas,
1555 int scan_label_only)
1557 struct label *label;
1558 struct device *dev;
1559 struct lvmcache_info *info;
1560 struct metadata_area *mda, *mda_new;
1561 struct mda_context *mdac, *mdac_new;
1563 if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
1564 return_0;
1566 if (!(label_read(dev, &label, UINT64_C(0))))
1567 return_0;
1568 info = (struct lvmcache_info *) label->info;
1570 if (!_populate_pv_fields(info, pv, scan_label_only))
1571 return 0;
1573 if (!mdas)
1574 return 1;
1576 /* Add copy of mdas to supplied list */
1577 dm_list_iterate_items(mda, &info->mdas) {
1578 mdac = (struct mda_context *) mda->metadata_locn;
1579 if (!(mda_new = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) {
1580 log_error("metadata_area allocation failed");
1581 return 0;
1583 if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac_new)))) {
1584 log_error("metadata_area allocation failed");
1585 return 0;
1587 memcpy(mda_new, mda, sizeof(*mda));
1588 memcpy(mdac_new, mdac, sizeof(*mdac));
1589 mda_new->metadata_locn = mdac_new;
1590 dm_list_add(mdas, &mda_new->list);
1593 return 1;
1596 static void _text_destroy_instance(struct format_instance *fid __attribute((unused)))
1598 return;
1601 static void _free_dirs(struct dm_list *dir_list)
1603 struct dm_list *dl, *tmp;
1605 dm_list_iterate_safe(dl, tmp, dir_list) {
1606 dm_list_del(dl);
1607 dm_free(dl);
1611 static void _free_raws(struct dm_list *raw_list)
1613 struct dm_list *rl, *tmp;
1615 dm_list_iterate_safe(rl, tmp, raw_list) {
1616 dm_list_del(rl);
1617 dm_free(rl);
1621 static void _text_destroy(const struct format_type *fmt)
1623 if (fmt->private) {
1624 _free_dirs(&((struct mda_lists *) fmt->private)->dirs);
1625 _free_raws(&((struct mda_lists *) fmt->private)->raws);
1626 dm_free(fmt->private);
1629 dm_free((void *)fmt);
1632 static struct metadata_area_ops _metadata_text_file_ops = {
1633 .vg_read = _vg_read_file,
1634 .vg_read_precommit = _vg_read_precommit_file,
1635 .vg_write = _vg_write_file,
1636 .vg_remove = _vg_remove_file,
1637 .vg_commit = _vg_commit_file
1640 static struct metadata_area_ops _metadata_text_file_backup_ops = {
1641 .vg_read = _vg_read_file,
1642 .vg_write = _vg_write_file,
1643 .vg_remove = _vg_remove_file,
1644 .vg_commit = _vg_commit_file_backup
1647 static struct metadata_area_ops _metadata_text_raw_ops = {
1648 .vg_read = _vg_read_raw,
1649 .vg_read_precommit = _vg_read_precommit_raw,
1650 .vg_write = _vg_write_raw,
1651 .vg_remove = _vg_remove_raw,
1652 .vg_precommit = _vg_precommit_raw,
1653 .vg_commit = _vg_commit_raw,
1654 .vg_revert = _vg_revert_raw,
1655 .mda_free_sectors = _mda_free_sectors_raw,
1656 .mda_total_sectors = _mda_total_sectors_raw,
1657 .mda_in_vg = _mda_in_vg_raw,
1658 .pv_analyze_mda = _pv_analyze_mda_raw,
1661 /* pvmetadatasize in sectors */
1663 * pe_start goal: FIXME -- reality of .pv_write complexity undermines this goal
1664 * - In cases where a pre-existing pe_start is provided (pvcreate --restorefile
1665 * and vgconvert): pe_start must not be changed (so pv->pe_start = pe_start).
1666 * - In cases where pe_start is 0: leave pv->pe_start as 0 and defer the
1667 * setting of pv->pe_start to .pv_write
1669 static int _text_pv_setup(const struct format_type *fmt,
1670 uint64_t pe_start, uint32_t extent_count,
1671 uint32_t extent_size, unsigned long data_alignment,
1672 unsigned long data_alignment_offset,
1673 int pvmetadatacopies,
1674 uint64_t pvmetadatasize, struct dm_list *mdas,
1675 struct physical_volume *pv, struct volume_group *vg)
1677 struct metadata_area *mda, *mda_new, *mda2;
1678 struct mda_context *mdac, *mdac_new, *mdac2;
1679 struct dm_list *pvmdas;
1680 struct lvmcache_info *info;
1681 int found;
1682 uint64_t pe_end = 0;
1683 unsigned mda_count = 0;
1684 uint64_t mda_size2 = 0;
1685 uint64_t pe_count;
1687 /* FIXME Cope with pvchange */
1688 /* FIXME Merge code with _text_create_text_instance */
1690 /* If new vg, add any further mdas on this PV to the fid's mda list */
1691 if (vg) {
1692 /* Iterate through all mdas on this PV */
1693 if ((info = info_from_pvid(pv->dev->pvid, 0))) {
1694 pvmdas = &info->mdas;
1695 dm_list_iterate_items(mda, pvmdas) {
1696 mda_count++;
1697 mdac =
1698 (struct mda_context *) mda->metadata_locn;
1700 /* FIXME Check it isn't already in use */
1702 /* Reduce usable device size */
1703 if (mda_count > 1)
1704 mda_size2 = mdac->area.size >> SECTOR_SHIFT;
1706 /* Ensure it isn't already on list */
1707 found = 0;
1708 dm_list_iterate_items(mda2, mdas) {
1709 if (mda2->ops !=
1710 &_metadata_text_raw_ops) continue;
1711 mdac2 =
1712 (struct mda_context *)
1713 mda2->metadata_locn;
1714 if (!memcmp
1715 (&mdac2->area, &mdac->area,
1716 sizeof(mdac->area))) {
1717 found = 1;
1718 break;
1721 if (found)
1722 continue;
1724 if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
1725 sizeof(*mda_new))))
1726 return_0;
1728 if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
1729 sizeof(*mdac_new))))
1730 return_0;
1731 /* FIXME multiple dev_areas inside area */
1732 memcpy(mda_new, mda, sizeof(*mda));
1733 memcpy(mdac_new, mdac, sizeof(*mdac));
1734 mda_new->metadata_locn = mdac_new;
1735 dm_list_add(mdas, &mda_new->list);
1739 /* FIXME Cope with genuine pe_count 0 */
1741 /* If missing, estimate pv->size from file-based metadata */
1742 if (!pv->size && pv->pe_count)
1743 pv->size = pv->pe_count * (uint64_t) vg->extent_size +
1744 pv->pe_start + mda_size2;
1746 /* Recalculate number of extents that will fit */
1747 if (!pv->pe_count) {
1748 pe_count = (pv->size - pv->pe_start - mda_size2) /
1749 vg->extent_size;
1750 if (pe_count > UINT32_MAX) {
1751 log_error("PV %s too large for extent size %s.",
1752 pv_dev_name(pv),
1753 display_size(vg->cmd, (uint64_t) vg->extent_size));
1754 return 0;
1756 pv->pe_count = (uint32_t) pe_count;
1759 /* Unlike LVM1, we don't store this outside a VG */
1760 /* FIXME Default from config file? vgextend cmdline flag? */
1761 pv->status |= ALLOCATABLE_PV;
1762 } else {
1763 if (pe_start)
1764 pv->pe_start = pe_start;
1766 if (!data_alignment)
1767 data_alignment = find_config_tree_int(pv->fmt->cmd,
1768 "devices/data_alignment",
1769 0) * 2;
1771 if (set_pe_align(pv, data_alignment) != data_alignment &&
1772 data_alignment)
1773 log_warn("WARNING: %s: Overriding data alignment to "
1774 "%lu sectors (requested %lu sectors)",
1775 pv_dev_name(pv), pv->pe_align, data_alignment);
1777 if (set_pe_align_offset(pv, data_alignment_offset) != data_alignment_offset &&
1778 data_alignment_offset)
1779 log_warn("WARNING: %s: Overriding data alignment offset to "
1780 "%lu sectors (requested %lu sectors)",
1781 pv_dev_name(pv), pv->pe_align_offset, data_alignment_offset);
1783 if (pv->pe_align < pv->pe_align_offset) {
1784 log_error("%s: pe_align (%lu sectors) must not be less "
1785 "than pe_align_offset (%lu sectors)",
1786 pv_dev_name(pv), pv->pe_align, pv->pe_align_offset);
1787 return 0;
1791 * This initialization has a side-effect of allowing
1792 * orphaned PVs to be created with the proper alignment.
1793 * Setting pv->pe_start here circumvents .pv_write's
1794 * "pvcreate on PV without prior pvremove" retreival of
1795 * the PV's previous pe_start.
1796 * - Without this you get actual != expected pe_start
1797 * failures in the testsuite.
1799 if (!pe_start && pv->pe_start < pv->pe_align)
1800 pv->pe_start = pv->pe_align;
1802 if (extent_count)
1803 pe_end = pe_start + extent_count * extent_size - 1;
1804 if (!_mda_setup(fmt, pe_start, pe_end, pvmetadatacopies,
1805 pvmetadatasize, mdas, pv, vg))
1806 return_0;
1809 return 1;
1812 /* NULL vgname means use only the supplied context e.g. an archive file */
1813 static struct format_instance *_text_create_text_instance(const struct format_type
1814 *fmt, const char *vgname,
1815 const char *vgid,
1816 void *context)
1818 struct format_instance *fid;
1819 struct text_fid_context *fidtc;
1820 struct metadata_area *mda, *mda_new;
1821 struct mda_context *mdac, *mdac_new;
1822 struct dir_list *dl;
1823 struct raw_list *rl;
1824 struct dm_list *dir_list, *raw_list, *mdas;
1825 char path[PATH_MAX];
1826 struct lvmcache_vginfo *vginfo;
1827 struct lvmcache_info *info;
1829 if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
1830 log_error("Couldn't allocate format instance object.");
1831 return NULL;
1834 if (!(fidtc = (struct text_fid_context *)
1835 dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
1836 log_error("Couldn't allocate text_fid_context.");
1837 return NULL;
1840 fidtc->raw_metadata_buf = NULL;
1841 fid->private = (void *) fidtc;
1843 fid->fmt = fmt;
1844 dm_list_init(&fid->metadata_areas);
1846 if (!vgname) {
1847 if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
1848 return_NULL;
1849 mda->ops = &_metadata_text_file_backup_ops;
1850 mda->metadata_locn = context;
1851 dm_list_add(&fid->metadata_areas, &mda->list);
1852 } else {
1853 dir_list = &((struct mda_lists *) fmt->private)->dirs;
1855 dm_list_iterate_items(dl, dir_list) {
1856 if (dm_snprintf(path, PATH_MAX, "%s/%s",
1857 dl->dir, vgname) < 0) {
1858 log_error("Name too long %s/%s", dl->dir,
1859 vgname);
1860 return NULL;
1863 context = create_text_context(fmt->cmd, path, NULL);
1864 if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
1865 return_NULL;
1866 mda->ops = &_metadata_text_file_ops;
1867 mda->metadata_locn = context;
1868 dm_list_add(&fid->metadata_areas, &mda->list);
1871 raw_list = &((struct mda_lists *) fmt->private)->raws;
1873 dm_list_iterate_items(rl, raw_list) {
1874 /* FIXME Cache this; rescan below if some missing */
1875 if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
1876 continue;
1878 if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
1879 return_NULL;
1881 if (!(mdac = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac))))
1882 return_NULL;
1883 mda->metadata_locn = mdac;
1884 /* FIXME Allow multiple dev_areas inside area */
1885 memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
1886 mda->ops = &_metadata_text_raw_ops;
1887 /* FIXME MISTAKE? mda->metadata_locn = context; */
1888 dm_list_add(&fid->metadata_areas, &mda->list);
1891 /* Scan PVs in VG for any further MDAs */
1892 lvmcache_label_scan(fmt->cmd, 0);
1893 if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
1894 goto_out;
1895 dm_list_iterate_items(info, &vginfo->infos) {
1896 mdas = &info->mdas;
1897 dm_list_iterate_items(mda, mdas) {
1898 mdac =
1899 (struct mda_context *) mda->metadata_locn;
1901 /* FIXME Check it holds this VG */
1902 if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
1903 sizeof(*mda_new))))
1904 return_NULL;
1906 if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
1907 sizeof(*mdac_new))))
1908 return_NULL;
1909 /* FIXME multiple dev_areas inside area */
1910 memcpy(mda_new, mda, sizeof(*mda));
1911 memcpy(mdac_new, mdac, sizeof(*mdac));
1912 mda_new->metadata_locn = mdac_new;
1913 dm_list_add(&fid->metadata_areas, &mda_new->list);
1916 /* FIXME Check raw metadata area count - rescan if required */
1919 out:
1920 return fid;
1923 void *create_text_context(struct cmd_context *cmd, const char *path,
1924 const char *desc)
1926 struct text_context *tc;
1927 char *tmp;
1929 if ((tmp = strstr(path, ".tmp")) && (tmp == path + strlen(path) - 4)) {
1930 log_error("%s: Volume group filename may not end in .tmp",
1931 path);
1932 return NULL;
1935 if (!(tc = dm_pool_alloc(cmd->mem, sizeof(*tc))))
1936 return_NULL;
1938 if (!(tc->path_live = dm_pool_strdup(cmd->mem, path)))
1939 goto_bad;
1941 if (!(tc->path_edit = dm_pool_alloc(cmd->mem, strlen(path) + 5)))
1942 goto_bad;
1944 sprintf(tc->path_edit, "%s.tmp", path);
1946 if (!desc)
1947 desc = "";
1949 if (!(tc->desc = dm_pool_strdup(cmd->mem, desc)))
1950 goto_bad;
1952 return (void *) tc;
1954 bad:
1955 dm_pool_free(cmd->mem, tc);
1957 log_error("Couldn't allocate text format context object.");
1958 return NULL;
1961 static struct format_handler _text_handler = {
1962 .scan = _text_scan,
1963 .pv_read = _text_pv_read,
1964 .pv_setup = _text_pv_setup,
1965 .pv_write = _text_pv_write,
1966 .vg_setup = _text_vg_setup,
1967 .lv_setup = _text_lv_setup,
1968 .create_instance = _text_create_text_instance,
1969 .destroy_instance = _text_destroy_instance,
1970 .destroy = _text_destroy
1973 static int _add_dir(const char *dir, struct dm_list *dir_list)
1975 struct dir_list *dl;
1977 if (dm_create_dir(dir)) {
1978 if (!(dl = dm_malloc(sizeof(struct dm_list) + strlen(dir) + 1))) {
1979 log_error("_add_dir allocation failed");
1980 return 0;
1982 log_very_verbose("Adding text format metadata dir: %s", dir);
1983 strcpy(dl->dir, dir);
1984 dm_list_add(dir_list, &dl->list);
1985 return 1;
1988 return 0;
1991 static int _get_config_disk_area(struct cmd_context *cmd,
1992 struct config_node *cn, struct dm_list *raw_list)
1994 struct device_area dev_area;
1995 char *id_str;
1996 struct id id;
1998 if (!(cn = cn->child)) {
1999 log_error("Empty metadata disk_area section of config file");
2000 return 0;
2003 if (!get_config_uint64(cn, "start_sector", &dev_area.start)) {
2004 log_error("Missing start_sector in metadata disk_area section "
2005 "of config file");
2006 return 0;
2008 dev_area.start <<= SECTOR_SHIFT;
2010 if (!get_config_uint64(cn, "size", &dev_area.size)) {
2011 log_error("Missing size in metadata disk_area section "
2012 "of config file");
2013 return 0;
2015 dev_area.size <<= SECTOR_SHIFT;
2017 if (!get_config_str(cn, "id", &id_str)) {
2018 log_error("Missing uuid in metadata disk_area section "
2019 "of config file");
2020 return 0;
2023 if (!id_read_format(&id, id_str)) {
2024 log_error("Invalid uuid in metadata disk_area section "
2025 "of config file: %s", id_str);
2026 return 0;
2029 if (!(dev_area.dev = device_from_pvid(cmd, &id))) {
2030 char buffer[64] __attribute((aligned(8)));
2032 if (!id_write_format(&id, buffer, sizeof(buffer)))
2033 log_error("Couldn't find device.");
2034 else
2035 log_error("Couldn't find device with uuid '%s'.",
2036 buffer);
2038 return 0;
2041 return _add_raw(raw_list, &dev_area);
2044 struct format_type *create_text_format(struct cmd_context *cmd)
2046 struct format_type *fmt;
2047 struct config_node *cn;
2048 struct config_value *cv;
2049 struct mda_lists *mda_lists;
2051 if (!(fmt = dm_malloc(sizeof(*fmt))))
2052 return_NULL;
2054 fmt->cmd = cmd;
2055 fmt->ops = &_text_handler;
2056 fmt->name = FMT_TEXT_NAME;
2057 fmt->alias = FMT_TEXT_ALIAS;
2058 fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
2059 fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
2060 FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
2061 FMT_UNLIMITED_STRIPESIZE;
2063 if (!(mda_lists = dm_malloc(sizeof(struct mda_lists)))) {
2064 log_error("Failed to allocate dir_list");
2065 dm_free(fmt);
2066 return NULL;
2069 dm_list_init(&mda_lists->dirs);
2070 dm_list_init(&mda_lists->raws);
2071 mda_lists->file_ops = &_metadata_text_file_ops;
2072 mda_lists->raw_ops = &_metadata_text_raw_ops;
2073 fmt->private = (void *) mda_lists;
2075 if (!(fmt->labeller = text_labeller_create(fmt))) {
2076 log_error("Couldn't create text label handler.");
2077 dm_free(fmt);
2078 return NULL;
2081 if (!(label_register_handler(FMT_TEXT_NAME, fmt->labeller))) {
2082 log_error("Couldn't register text label handler.");
2083 dm_free(fmt);
2084 return NULL;
2087 if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) {
2088 for (cv = cn->v; cv; cv = cv->next) {
2089 if (cv->type != CFG_STRING) {
2090 log_error("Invalid string in config file: "
2091 "metadata/dirs");
2092 goto err;
2095 if (!_add_dir(cv->v.str, &mda_lists->dirs)) {
2096 log_error("Failed to add %s to text format "
2097 "metadata directory list ", cv->v.str);
2098 goto err;
2103 if ((cn = find_config_tree_node(cmd, "metadata/disk_areas"))) {
2104 for (cn = cn->child; cn; cn = cn->sib) {
2105 if (!_get_config_disk_area(cmd, cn, &mda_lists->raws))
2106 goto err;
2110 log_very_verbose("Initialised format: %s", fmt->name);
2112 return fmt;
2114 err:
2115 _free_dirs(&mda_lists->dirs);
2117 dm_free(fmt);
2118 return NULL;