2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "import-export.h"
20 #include "lvm-string.h"
22 #include "text_export.h"
23 #include "lvm-version.h"
27 #include <sys/utsname.h>
30 typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
31 const char *fmt, va_list ap);
32 typedef int (*nl_fn) (struct formatter * f);
35 * Macro for formatted output.
36 * out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
37 * Then argument list is reset and out_with_comment_fn is called again.
39 #define _out_with_comment(f, buffer, fmt, ap) \
42 r = f->out_with_comment(f, buffer, fmt, ap); \
47 * The first half of this file deals with
48 * exporting the vg, ie. writing it to a file.
51 struct dm_pool *mem; /* pv names allocated from here */
52 struct dm_hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
55 FILE *fp; /* where we're writing to */
63 out_with_comment_fn out_with_comment;
66 int indent; /* current level of indentation */
68 int header; /* 1 => comments at start; 0 => end */
71 static struct utsname _utsname;
73 static void _init(void)
75 static int _initialised = 0;
80 if (uname(&_utsname)) {
81 log_error("uname failed: %s", strerror(errno));
82 memset(&_utsname, 0, sizeof(_utsname));
89 * Formatting functions.
93 static void _inc_indent(struct formatter *f)
95 if (++f->indent > MAX_INDENT)
96 f->indent = MAX_INDENT;
99 static void _dec_indent(struct formatter *f)
102 log_error(INTERNAL_ERROR "problem tracking indentation");
108 * Newline function for prettier layout.
110 static int _nl_file(struct formatter *f)
112 fprintf(f->data.fp, "\n");
117 static int _extend_buffer(struct formatter *f)
121 log_debug("Doubling metadata output buffer to %" PRIu32,
122 f->data.buf.size * 2);
123 if (!(newbuf = dm_realloc(f->data.buf.start,
124 f->data.buf.size * 2))) {
125 log_error("Buffer reallocation failed.");
128 f->data.buf.start = newbuf;
129 f->data.buf.size *= 2;
134 static int _nl_raw(struct formatter *f)
136 /* If metadata doesn't fit, extend buffer */
137 if ((f->data.buf.used + 2 > f->data.buf.size) &&
138 (!_extend_buffer(f)))
141 *(f->data.buf.start + f->data.buf.used) = '\n';
142 f->data.buf.used += 1;
144 *(f->data.buf.start + f->data.buf.used) = '\0';
149 #define COMMENT_TAB 6
150 static int _out_with_comment_file(struct formatter *f, const char *comment,
151 const char *fmt, va_list ap)
154 char white_space[MAX_INDENT + 1];
156 if (ferror(f->data.fp))
159 for (i = 0; i < f->indent; i++)
160 white_space[i] = '\t';
161 white_space[i] = '\0';
162 fputs(white_space, f->data.fp);
163 i = vfprintf(f->data.fp, fmt, ap);
167 * line comments up if possible.
174 fputc('\t', f->data.fp);
176 while (++i < COMMENT_TAB);
178 fputs(comment, f->data.fp);
180 fputc('\n', f->data.fp);
185 static int _out_with_comment_raw(struct formatter *f,
186 const char *comment __attribute__((unused)),
187 const char *fmt, va_list ap)
191 n = vsnprintf(f->data.buf.start + f->data.buf.used,
192 f->data.buf.size - f->data.buf.used, fmt, ap);
194 /* If metadata doesn't fit, extend buffer */
195 if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
196 if (!_extend_buffer(f))
198 return -1; /* Retry */
201 f->data.buf.used += n;
209 * Formats a string, converting a size specified
210 * in 512-byte sectors to a more human readable
211 * form (eg, megabytes). We may want to lift this
212 * for other code to use.
214 static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
216 static const char *_units[] = {
227 double d = (double) sectors;
229 /* to convert to K */
232 for (i = 0; (d > 1024.0) && _units[i]; i++)
235 return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
238 /* increment indention level */
239 void out_inc_indent(struct formatter *f)
244 /* decrement indention level */
245 void out_dec_indent(struct formatter *f)
250 /* insert new line */
251 int out_newline(struct formatter *f)
257 * Appends a comment giving a size in more easily
258 * readable form (eg, 4M instead of 8096).
260 int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
266 if (!_sectors_to_units(size, buffer, sizeof(buffer)))
269 _out_with_comment(f, buffer, fmt, ap);
275 * Appends a comment indicating that the line is
278 int out_hint(struct formatter *f, const char *fmt, ...)
283 _out_with_comment(f, "# Hint only", fmt, ap);
289 * The normal output function with comment
291 int out_text_with_comment(struct formatter *f, const char *comment, const char *fmt, ...)
296 _out_with_comment(f, comment, fmt, ap);
302 * The normal output function.
304 int out_text(struct formatter *f, const char *fmt, ...)
309 _out_with_comment(f, NULL, fmt, ap);
314 static int _out_line(const char *line, void *_f) {
315 struct formatter *f = (struct formatter *) _f;
316 return out_text(f, "%s", line);
319 int out_config_node(struct formatter *f, const struct config_node *cn)
321 return write_config_node(cn, _out_line, f);
324 static int _print_header(struct formatter *f,
332 outf(f, "# Generated by LVM2 version %s: %s", LVM_VERSION, ctime(&t));
333 outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
334 outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
337 if (!(buf = alloca(escaped_len(desc)))) {
338 log_error("temporary stack allocation for description"
342 outf(f, "description = \"%s\"", escape_double_quotes(buf, desc));
344 outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
345 _utsname.sysname, _utsname.nodename, _utsname.release,
346 _utsname.version, _utsname.machine);
347 outf(f, "creation_time = %lu\t# %s", t, ctime(&t));
352 static int _print_flag_config(struct formatter *f, uint64_t status, int type)
355 if (!print_flags(status, type | STATUS_FLAG, buffer, sizeof(buffer)))
357 outf(f, "status = %s", buffer);
359 if (!print_flags(status, type, buffer, sizeof(buffer)))
361 outf(f, "flags = %s", buffer);
367 static int _out_tags(struct formatter *f, struct dm_list *tags)
371 if (!dm_list_empty(tags)) {
372 if (!(tag_buffer = alloc_printed_tags(tags)))
374 if (!out_text(f, "tags = %s", tag_buffer)) {
384 static int _print_vg(struct formatter *f, struct volume_group *vg)
388 if (!id_write_format(&vg->id, buffer, sizeof(buffer)))
391 outf(f, "id = \"%s\"", buffer);
393 outf(f, "seqno = %u", vg->seqno);
395 if (!_print_flag_config(f, vg->status, VG_FLAGS))
398 if (!_out_tags(f, &vg->tags))
401 if (vg->system_id && *vg->system_id)
402 outf(f, "system_id = \"%s\"", vg->system_id);
404 outsize(f, (uint64_t) vg->extent_size, "extent_size = %u",
406 outf(f, "max_lv = %u", vg->max_lv);
407 outf(f, "max_pv = %u", vg->max_pv);
409 /* Default policy is NORMAL; INHERIT is meaningless */
410 if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
412 outf(f, "allocation_policy = \"%s\"",
413 get_alloc_string(vg->alloc));
415 outf(f, "metadata_copies = %u", vg->mda_copies);
421 * Get the pv%d name from the formatters hash
424 static const char *_get_pv_name_from_uuid(struct formatter *f, char *uuid)
426 return dm_hash_lookup(f->pv_names, uuid);
429 static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
431 char uuid[64] __attribute__((aligned(8)));
433 if (!pv || !id_write_format(&pv->id, uuid, sizeof(uuid)))
436 return _get_pv_name_from_uuid(f, uuid);
439 static int _print_pvs(struct formatter *f, struct volume_group *vg)
442 struct physical_volume *pv;
447 outf(f, "physical_volumes {");
450 dm_list_iterate_items(pvl, &vg->pvs) {
453 if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
456 if (!(name = _get_pv_name_from_uuid(f, buffer)))
460 outf(f, "%s {", name);
463 outf(f, "id = \"%s\"", buffer);
465 if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) {
466 log_error("temporary stack allocation for device name"
471 outhint(f, "device = \"%s\"",
472 escape_double_quotes(buf, pv_dev_name(pv)));
475 if (!_print_flag_config(f, pv->status, PV_FLAGS))
478 if (!_out_tags(f, &pv->tags))
481 outsize(f, pv->size, "dev_size = %" PRIu64, pv->size);
483 outf(f, "pe_start = %" PRIu64, pv->pe_start);
484 outsize(f, vg->extent_size * (uint64_t) pv->pe_count,
485 "pe_count = %u", pv->pe_count);
496 static int _print_segment(struct formatter *f, struct volume_group *vg,
497 int count, struct lv_segment *seg)
499 outf(f, "segment%u {", count);
502 outf(f, "start_extent = %u", seg->le);
503 outsize(f, (uint64_t) seg->len * vg->extent_size,
504 "extent_count = %u", seg->len);
507 outf(f, "type = \"%s\"", seg->segtype->name);
509 if (!_out_tags(f, &seg->tags))
512 if (seg->segtype->ops->text_export &&
513 !seg->segtype->ops->text_export(seg, f))
522 int out_areas(struct formatter *f, const struct lv_segment *seg,
530 outf(f, "%ss = [", type);
533 for (s = 0; s < seg->area_count; s++) {
534 switch (seg_type(seg, s)) {
536 if (!(name = _get_pv_name(f, seg_pv(seg, s))))
539 outf(f, "\"%s\", %u%s", name,
541 (s == seg->area_count - 1) ? "" : ",");
544 outf(f, "\"%s\", %u%s",
545 seg_lv(seg, s)->name,
547 (s == seg->area_count - 1) ? "" : ",");
549 case AREA_UNASSIGNED:
559 static int _print_lv(struct formatter *f, struct logical_volume *lv)
561 struct lv_segment *seg;
566 outf(f, "%s {", lv->name);
569 /* FIXME: Write full lvid */
570 if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer)))
573 outf(f, "id = \"%s\"", buffer);
575 if (!_print_flag_config(f, lv->status, LV_FLAGS))
578 if (!_out_tags(f, &lv->tags))
581 if (lv->alloc != ALLOC_INHERIT)
582 outf(f, "allocation_policy = \"%s\"",
583 get_alloc_string(lv->alloc));
585 switch (lv->read_ahead) {
586 case DM_READ_AHEAD_NONE:
587 outfc(f, "# None", "read_ahead = -1");
589 case DM_READ_AHEAD_AUTO:
590 /* No output - use default */
593 outf(f, "read_ahead = %u", lv->read_ahead);
597 outf(f, "major = %d", lv->major);
599 outf(f, "minor = %d", lv->minor);
600 outf(f, "segment_count = %u", dm_list_size(&lv->segments));
604 dm_list_iterate_items(seg, &lv->segments) {
605 if (!_print_segment(f, lv->vg, seg_count++, seg))
615 static int _print_lvs(struct formatter *f, struct volume_group *vg)
620 * Don't bother with an lv section if there are no lvs.
622 if (dm_list_empty(&vg->lvs))
625 outf(f, "logical_volumes {");
629 * Write visible LVs first
631 dm_list_iterate_items(lvl, &vg->lvs) {
632 if (!(lv_is_visible(lvl->lv)))
634 if (!_print_lv(f, lvl->lv))
638 dm_list_iterate_items(lvl, &vg->lvs) {
639 if ((lv_is_visible(lvl->lv)))
641 if (!_print_lv(f, lvl->lv))
652 * In the text format we refer to pv's as 'pv1',
653 * 'pv2' etc. This function builds a hash table
654 * to enable a quick lookup from device -> name.
656 static int _build_pv_names(struct formatter *f, struct volume_group *vg)
660 struct physical_volume *pv;
661 char buffer[32], *uuid, *name;
663 if (!(f->mem = dm_pool_create("text pv_names", 512)))
666 if (!(f->pv_names = dm_hash_create(128)))
669 dm_list_iterate_items(pvl, &vg->pvs) {
672 /* FIXME But skip if there's already an LV called pv%d ! */
673 if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
676 if (!(name = dm_pool_strdup(f->mem, buffer)))
679 if (!(uuid = dm_pool_zalloc(f->mem, 64)) ||
680 !id_write_format(&pv->id, uuid, 64))
683 if (!dm_hash_insert(f->pv_names, uuid, name))
690 static int _text_vg_export(struct formatter *f,
691 struct volume_group *vg, const char *desc)
695 if (!_build_pv_names(f, vg))
698 if (f->header && !_print_header(f, desc))
701 if (!out_text(f, "%s {", vg->name))
706 if (!_print_vg(f, vg))
710 if (!_print_pvs(f, vg))
714 if (!_print_lvs(f, vg))
718 if (!out_text(f, "}"))
721 if (!f->header && !_print_header(f, desc))
728 dm_pool_destroy(f->mem);
731 dm_hash_destroy(f->pv_names);
736 int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
743 if (!(f = dm_zalloc(sizeof(*f))))
749 f->out_with_comment = &_out_with_comment_file;
752 r = _text_vg_export(f, vg, desc);
754 r = !ferror(f->data.fp);
759 /* Returns amount of buffer used incl. terminating NUL */
760 int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
767 if (!(f = dm_zalloc(sizeof(*f))))
770 f->data.buf.size = 65536; /* Initial metadata limit */
771 if (!(f->data.buf.start = dm_malloc(f->data.buf.size))) {
772 log_error("text_export buffer allocation failed");
778 f->out_with_comment = &_out_with_comment_raw;
781 if (!_text_vg_export(f, vg, desc)) {
782 dm_free(f->data.buf.start);
786 r = f->data.buf.used + 1;
787 *buf = f->data.buf.start;
794 int export_vg_to_buffer(struct volume_group *vg, char **buf)
796 return text_vg_export_raw(vg, "", buf);