4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 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
19 #include "import-export.h"
22 #include "lvm-string.h"
24 #include "text_export.h"
25 #include "lvm-version.h"
29 #include <sys/utsname.h>
32 typedef int (*out_with_comment_fn
) (struct formatter
* f
, const char *comment
,
33 const char *fmt
, va_list ap
);
34 typedef int (*nl_fn
) (struct formatter
* f
);
37 * Macro for formatted output.
38 * out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
39 * Then argument list is reset and out_with_comment_fn is called again.
41 #define _out_with_comment(f, buffer, fmt, ap) \
44 r = f->out_with_comment(f, buffer, fmt, ap); \
49 * The first half of this file deals with
50 * exporting the vg, ie. writing it to a file.
53 struct dm_pool
*mem
; /* pv names allocated from here */
54 struct dm_hash_table
*pv_names
; /* dev_name -> pv_name (eg, pv1) */
57 FILE *fp
; /* where we're writing to */
65 out_with_comment_fn out_with_comment
;
68 int indent
; /* current level of indentation */
70 int header
; /* 1 => comments at start; 0 => end */
73 static struct utsname _utsname
;
75 static void _init(void)
77 static int _initialised
= 0;
82 if (uname(&_utsname
)) {
83 log_error("uname failed: %s", strerror(errno
));
84 memset(&_utsname
, 0, sizeof(_utsname
));
91 * Formatting functions.
95 static void _inc_indent(struct formatter
*f
)
97 if (++f
->indent
> MAX_INDENT
)
98 f
->indent
= MAX_INDENT
;
101 static void _dec_indent(struct formatter
*f
)
104 log_error("Internal error tracking indentation");
110 * Newline function for prettier layout.
112 static int _nl_file(struct formatter
*f
)
114 fprintf(f
->data
.fp
, "\n");
119 static int _extend_buffer(struct formatter
*f
)
123 log_debug("Doubling metadata output buffer to %" PRIu32
,
124 f
->data
.buf
.size
* 2);
125 if (!(newbuf
= dm_realloc(f
->data
.buf
.start
,
126 f
->data
.buf
.size
* 2))) {
127 log_error("Buffer reallocation failed.");
130 f
->data
.buf
.start
= newbuf
;
131 f
->data
.buf
.size
*= 2;
136 static int _nl_raw(struct formatter
*f
)
138 /* If metadata doesn't fit, extend buffer */
139 if ((f
->data
.buf
.used
+ 2 > f
->data
.buf
.size
) &&
140 (!_extend_buffer(f
)))
143 *(f
->data
.buf
.start
+ f
->data
.buf
.used
) = '\n';
144 f
->data
.buf
.used
+= 1;
146 *(f
->data
.buf
.start
+ f
->data
.buf
.used
) = '\0';
151 #define COMMENT_TAB 6
152 static int _out_with_comment_file(struct formatter
*f
, const char *comment
,
153 const char *fmt
, va_list ap
)
156 char white_space
[MAX_INDENT
+ 1];
158 if (ferror(f
->data
.fp
))
161 for (i
= 0; i
< f
->indent
; i
++)
162 white_space
[i
] = '\t';
163 white_space
[i
] = '\0';
164 fputs(white_space
, f
->data
.fp
);
165 i
= vfprintf(f
->data
.fp
, fmt
, ap
);
169 * line comments up if possible.
176 fputc('\t', f
->data
.fp
);
178 while (++i
< COMMENT_TAB
);
180 fputs(comment
, f
->data
.fp
);
182 fputc('\n', f
->data
.fp
);
187 static int _out_with_comment_raw(struct formatter
*f
,
188 const char *comment
__attribute((unused
)),
189 const char *fmt
, va_list ap
)
193 n
= vsnprintf(f
->data
.buf
.start
+ f
->data
.buf
.used
,
194 f
->data
.buf
.size
- f
->data
.buf
.used
, fmt
, ap
);
196 /* If metadata doesn't fit, extend buffer */
197 if (n
< 0 || (n
+ f
->data
.buf
.used
+ 2 > f
->data
.buf
.size
)) {
198 if (!_extend_buffer(f
))
200 return -1; /* Retry */
203 f
->data
.buf
.used
+= n
;
211 * Formats a string, converting a size specified
212 * in 512-byte sectors to a more human readable
213 * form (eg, megabytes). We may want to lift this
214 * for other code to use.
216 static int _sectors_to_units(uint64_t sectors
, char *buffer
, size_t s
)
218 static const char *_units
[] = {
229 double d
= (double) sectors
;
231 /* to convert to K */
234 for (i
= 0; (d
> 1024.0) && _units
[i
]; i
++)
237 return dm_snprintf(buffer
, s
, "# %g %s", d
, _units
[i
]) > 0;
240 /* increment indention level */
241 void out_inc_indent(struct formatter
*f
)
246 /* decrement indention level */
247 void out_dec_indent(struct formatter
*f
)
252 /* insert new line */
253 int out_newline(struct formatter
*f
)
259 * Appends a comment giving a size in more easily
260 * readable form (eg, 4M instead of 8096).
262 int out_size(struct formatter
*f
, uint64_t size
, const char *fmt
, ...)
268 if (!_sectors_to_units(size
, buffer
, sizeof(buffer
)))
271 _out_with_comment(f
, buffer
, fmt
, ap
);
277 * Appends a comment indicating that the line is
280 int out_hint(struct formatter
*f
, const char *fmt
, ...)
285 _out_with_comment(f
, "# Hint only", fmt
, ap
);
293 static int _out_comment(struct formatter
*f
, const char *comment
, const char *fmt
, ...)
298 _out_with_comment(f
, comment
, fmt
, ap
);
304 * The normal output function.
306 int out_text(struct formatter
*f
, const char *fmt
, ...)
311 _out_with_comment(f
, NULL
, fmt
, ap
);
316 static int _out_line(const char *line
, void *_f
) {
317 struct formatter
*f
= (struct formatter
*) _f
;
318 return out_text(f
, "%s", line
);
321 int out_config_node(struct formatter
*f
, const struct config_node
*cn
)
323 return write_config_node(cn
, _out_line
, f
);
326 static int _print_header(struct formatter
*f
,
334 outf(f
, "# Generated by LVM2 version %s: %s", LVM_VERSION
, ctime(&t
));
335 outf(f
, CONTENTS_FIELD
" = \"" CONTENTS_VALUE
"\"");
336 outf(f
, FORMAT_VERSION_FIELD
" = %d", FORMAT_VERSION_VALUE
);
339 if (!(buf
= alloca(escaped_len(desc
)))) {
340 log_error("temporary stack allocation for description"
344 outf(f
, "description = \"%s\"", escape_double_quotes(buf
, desc
));
346 outf(f
, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname
.nodename
,
347 _utsname
.sysname
, _utsname
.nodename
, _utsname
.release
,
348 _utsname
.version
, _utsname
.machine
);
349 outf(f
, "creation_time = %lu\t# %s", t
, ctime(&t
));
354 static int _print_flag_config(struct formatter
*f
, int status
, int type
)
357 if (!print_flags(status
, type
| STATUS_FLAG
, buffer
, sizeof(buffer
)))
359 outf(f
, "status = %s", buffer
);
361 if (!print_flags(status
, type
, buffer
, sizeof(buffer
)))
363 outf(f
, "flags = %s", buffer
);
368 static int _print_vg(struct formatter
*f
, struct volume_group
*vg
)
372 if (!id_write_format(&vg
->id
, buffer
, sizeof(buffer
)))
375 outf(f
, "id = \"%s\"", buffer
);
377 outf(f
, "seqno = %u", vg
->seqno
);
379 if (!_print_flag_config(f
, vg
->status
, VG_FLAGS
))
382 if (!dm_list_empty(&vg
->tags
)) {
383 if (!print_tags(&vg
->tags
, buffer
, sizeof(buffer
)))
385 outf(f
, "tags = %s", buffer
);
388 if (vg
->system_id
&& *vg
->system_id
)
389 outf(f
, "system_id = \"%s\"", vg
->system_id
);
391 if (!out_size(f
, (uint64_t) vg
->extent_size
, "extent_size = %u",
394 outf(f
, "max_lv = %u", vg
->max_lv
);
395 outf(f
, "max_pv = %u", vg
->max_pv
);
397 /* Default policy is NORMAL; INHERIT is meaningless */
398 if (vg
->alloc
!= ALLOC_NORMAL
&& vg
->alloc
!= ALLOC_INHERIT
) {
400 outf(f
, "allocation_policy = \"%s\"",
401 get_alloc_string(vg
->alloc
));
408 * Get the pv%d name from the formatters hash
411 static const char *_get_pv_name_from_uuid(struct formatter
*f
, char *uuid
)
413 return dm_hash_lookup(f
->pv_names
, uuid
);
416 static const char *_get_pv_name(struct formatter
*f
, struct physical_volume
*pv
)
418 char uuid
[64] __attribute((aligned(8)));
420 if (!pv
|| !id_write_format(&pv
->id
, uuid
, sizeof(uuid
)))
423 return _get_pv_name_from_uuid(f
, uuid
);
426 static int _print_pvs(struct formatter
*f
, struct volume_group
*vg
)
429 struct physical_volume
*pv
;
434 outf(f
, "physical_volumes {");
437 dm_list_iterate_items(pvl
, &vg
->pvs
) {
440 if (!id_write_format(&pv
->id
, buffer
, sizeof(buffer
)))
443 if (!(name
= _get_pv_name_from_uuid(f
, buffer
)))
447 outf(f
, "%s {", name
);
450 outf(f
, "id = \"%s\"", buffer
);
452 if (!(buf
= alloca(escaped_len(pv_dev_name(pv
))))) {
453 log_error("temporary stack allocation for device name"
458 if (!out_hint(f
, "device = \"%s\"",
459 escape_double_quotes(buf
, pv_dev_name(pv
))))
463 if (!_print_flag_config(f
, pv
->status
, PV_FLAGS
))
466 if (!dm_list_empty(&pv
->tags
)) {
467 if (!print_tags(&pv
->tags
, buffer
, sizeof(buffer
)))
469 outf(f
, "tags = %s", buffer
);
472 if (!out_size(f
, pv
->size
, "dev_size = %" PRIu64
, pv
->size
))
475 outf(f
, "pe_start = %" PRIu64
, pv
->pe_start
);
476 if (!out_size(f
, vg
->extent_size
* (uint64_t) pv
->pe_count
,
477 "pe_count = %u", pv
->pe_count
))
489 static int _print_segment(struct formatter
*f
, struct volume_group
*vg
,
490 int count
, struct lv_segment
*seg
)
494 outf(f
, "segment%u {", count
);
497 outf(f
, "start_extent = %u", seg
->le
);
498 if (!out_size(f
, (uint64_t) seg
->len
* vg
->extent_size
,
499 "extent_count = %u", seg
->len
))
503 outf(f
, "type = \"%s\"", seg
->segtype
->name
);
505 if (!dm_list_empty(&seg
->tags
)) {
506 if (!print_tags(&seg
->tags
, buffer
, sizeof(buffer
)))
508 outf(f
, "tags = %s", buffer
);
511 if (seg
->segtype
->ops
->text_export
&&
512 !seg
->segtype
->ops
->text_export(seg
, f
))
521 int out_areas(struct formatter
*f
, const struct lv_segment
*seg
,
529 outf(f
, "%ss = [", type
);
532 for (s
= 0; s
< seg
->area_count
; s
++) {
533 switch (seg_type(seg
, s
)) {
535 if (!(name
= _get_pv_name(f
, seg_pv(seg
, s
))))
538 outf(f
, "\"%s\", %u%s", name
,
540 (s
== seg
->area_count
- 1) ? "" : ",");
543 outf(f
, "\"%s\", %u%s",
544 seg_lv(seg
, s
)->name
,
546 (s
== seg
->area_count
- 1) ? "" : ",");
548 case AREA_UNASSIGNED
:
558 static int _print_lv(struct formatter
*f
, struct logical_volume
*lv
)
560 struct lv_segment
*seg
;
565 outf(f
, "%s {", lv
->name
);
568 /* FIXME: Write full lvid */
569 if (!id_write_format(&lv
->lvid
.id
[1], buffer
, sizeof(buffer
)))
572 outf(f
, "id = \"%s\"", buffer
);
574 if (!_print_flag_config(f
, lv
->status
, LV_FLAGS
))
577 if (!dm_list_empty(&lv
->tags
)) {
578 if (!print_tags(&lv
->tags
, buffer
, sizeof(buffer
)))
580 outf(f
, "tags = %s", buffer
);
583 if (lv
->alloc
!= ALLOC_INHERIT
)
584 outf(f
, "allocation_policy = \"%s\"",
585 get_alloc_string(lv
->alloc
));
587 switch (lv
->read_ahead
) {
588 case DM_READ_AHEAD_NONE
:
589 _out_comment(f
, "# None", "read_ahead = -1");
591 case DM_READ_AHEAD_AUTO
:
592 /* No output - use default */
595 outf(f
, "read_ahead = %u", lv
->read_ahead
);
599 outf(f
, "major = %d", lv
->major
);
601 outf(f
, "minor = %d", lv
->minor
);
602 outf(f
, "segment_count = %u", dm_list_size(&lv
->segments
));
606 dm_list_iterate_items(seg
, &lv
->segments
) {
607 if (!_print_segment(f
, lv
->vg
, seg_count
++, seg
))
617 static int _print_lvs(struct formatter
*f
, struct volume_group
*vg
)
622 * Don't bother with an lv section if there are no lvs.
624 if (dm_list_empty(&vg
->lvs
))
627 outf(f
, "logical_volumes {");
631 * Write visible LVs first
633 dm_list_iterate_items(lvl
, &vg
->lvs
) {
634 if (!(lv_is_visible(lvl
->lv
)))
636 if (!_print_lv(f
, lvl
->lv
))
640 dm_list_iterate_items(lvl
, &vg
->lvs
) {
641 if ((lv_is_visible(lvl
->lv
)))
643 if (!_print_lv(f
, lvl
->lv
))
654 * In the text format we refer to pv's as 'pv1',
655 * 'pv2' etc. This function builds a hash table
656 * to enable a quick lookup from device -> name.
658 static int _build_pv_names(struct formatter
*f
, struct volume_group
*vg
)
662 struct physical_volume
*pv
;
663 char buffer
[32], *uuid
, *name
;
665 if (!(f
->mem
= dm_pool_create("text pv_names", 512)))
668 if (!(f
->pv_names
= dm_hash_create(128)))
671 dm_list_iterate_items(pvl
, &vg
->pvs
) {
674 /* FIXME But skip if there's already an LV called pv%d ! */
675 if (dm_snprintf(buffer
, sizeof(buffer
), "pv%d", count
++) < 0)
678 if (!(name
= dm_pool_strdup(f
->mem
, buffer
)))
681 if (!(uuid
= dm_pool_zalloc(f
->mem
, 64)) ||
682 !id_write_format(&pv
->id
, uuid
, 64))
685 if (!dm_hash_insert(f
->pv_names
, uuid
, name
))
692 static int _text_vg_export(struct formatter
*f
,
693 struct volume_group
*vg
, const char *desc
)
697 if (!_build_pv_names(f
, vg
))
700 if (f
->header
&& !_print_header(f
, desc
))
703 if (!out_text(f
, "%s {", vg
->name
))
708 if (!_print_vg(f
, vg
))
712 if (!_print_pvs(f
, vg
))
716 if (!_print_lvs(f
, vg
))
720 if (!out_text(f
, "}"))
723 if (!f
->header
&& !_print_header(f
, desc
))
730 dm_pool_destroy(f
->mem
);
733 dm_hash_destroy(f
->pv_names
);
738 int text_vg_export_file(struct volume_group
*vg
, const char *desc
, FILE *fp
)
745 if (!(f
= dm_malloc(sizeof(*f
))))
748 memset(f
, 0, sizeof(*f
));
752 f
->out_with_comment
= &_out_with_comment_file
;
755 r
= _text_vg_export(f
, vg
, desc
);
757 r
= !ferror(f
->data
.fp
);
762 /* Returns amount of buffer used incl. terminating NUL */
763 int text_vg_export_raw(struct volume_group
*vg
, const char *desc
, char **buf
)
770 if (!(f
= dm_malloc(sizeof(*f
))))
773 memset(f
, 0, sizeof(*f
));
775 f
->data
.buf
.size
= 65536; /* Initial metadata limit */
776 if (!(f
->data
.buf
.start
= dm_malloc(f
->data
.buf
.size
))) {
777 log_error("text_export buffer allocation failed");
783 f
->out_with_comment
= &_out_with_comment_raw
;
786 if (!_text_vg_export(f
, vg
, desc
)) {
787 dm_free(f
->data
.buf
.start
);
791 r
= f
->data
.buf
.used
+ 1;
792 *buf
= f
->data
.buf
.start
;
799 int export_vg_to_buffer(struct volume_group
*vg
, char **buf
)
801 return text_vg_export_raw(vg
, "", buf
);