From d96dea9abf241696a9870eaa214dc99bd65dcfb9 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 11 Dec 2001 12:16:58 +0000 Subject: [PATCH] o Split import-export.c into two files. --- lib/format_text/export.c | 454 ++++++++++++++++++++++++++++++++ lib/format_text/import-export.c | 168 ------------ lib/format_text/import-export.h | 14 +- 3 files changed, 467 insertions(+), 169 deletions(-) create mode 100644 lib/format_text/export.c delete mode 100644 lib/format_text/import-export.c diff --git a/lib/format_text/export.c b/lib/format_text/export.c new file mode 100644 index 000000000..88c90ba9f --- /dev/null +++ b/lib/format_text/export.c @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the LGPL. + */ + +#include "text-rep.h" +#include "metadata.h" +#include "log.h" +#include "hash.h" +#include "pool.h" + +#include + + +/* + * The first half of this file deals with + * exporting the vg, ie. writing it to a file. + */ +struct formatter { + struct pool *mem; /* pv names allocated from here */ + struct hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */ + + FILE *fp; /* where we're writing to */ + int indent; /* current level of indentation */ +}; + +#define MAX_INDENT 5 +static void _inc_indent(struct formatter *f) +{ + if (++f->indent > MAX_INDENT) + f->indent = MAX_INDENT; +} + +static void _dec_indent(struct formatter *f) +{ + if (--f->indent) { + log_debug("Indenting seems to have messed up\n"); + f->indent = 0; + } +} + +/* + * Newline function for prettier layout. + */ +static void _nl(struct formatter *f) +{ + fprintf(f->fp, "\n"); +} + +#define COMMENT_TAB 6 +static void _out_with_comment(struct formatter *f, const char *comment, + const char *fmt, va_list ap) +{ + int i; + char white_space[MAX_INDENT + 1]; + + for (i = 0; i < f->indent; i++) + white_space[i] = '\t'; + white_space[i] = '\0'; + fprintf(f->fp, white_space); + + i = vfprintf(f->fp, fmt, ap); + + if (comment) { + /* + * line comments up if possible. + */ + i += 8 * f->indent; + i /= 8; + i++; + + do + fputc('\t', f->fp); + + while (++i < COMMENT_TAB); + + fprintf(f->fp, comment); + } + fputc('\n', f->fp); +} + +/* + * Formats a string, converting a size specified + * in 512-byte sectors to a more human readable + * form (eg, megabytes). We may want to lift this + * for other code to use. + */ +static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s) +{ + static char *_units = [ + "Kilobytes", + "Megabytes", + "Gigabytes", + "Terrabytes", + NULL + ]; + + int i; + double d = (double) sectors; + + /* to convert to K */ + d /= 2.0; + + for (i = 0; (d > 1024.0) && _units[i]; i++) + d /= 1024.0; + + /* FIXME: arrange so this doesn't print a + * decimal point unless we have a + * fractional part. */ + return snprintf(buffer, s, "# %g %s", d, _units[i]) > 0; +} + +/* + * Appends a comment giving a size in more easily + * readable form (eg, 4M instead of 8096). + */ +static void _out_size(struct formatter *f, uint64_t size, + const char *fmt, ...) +{ + char buffer[64]; + va_list ap; + + _sectors_to_units(size, buffer, sizeof(buffer)); + + va_start(ap, fmt); + _out_with_comment(f, buffer, fmt, ap); + va_end(ap); +} + +/* + * Appends a comment indicating that the line is + * only a hint. + */ +static void _out_hint(struct formatter *f, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _out_with_comment(f, "# Hint only", fmt, ap); + va_end(ap); +} + +/* + * The normal output function. + */ +static void _out(struct formatter *f, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _out_with_comment(f, NULL, fmt, ap); + va_end(ap); +} + +static int _print_header(struct formatter *f, struct volume_group *vg) +{ + _out(f, + "# This file was originally generated by the LVM2 library\n" + "# It is inadvisable for people to edit this by hand unless\n" + "# they *really* know what they're doing.\n" + "# Generated: %s\n", ctime(time(NULL))); + return 1; +} + +static int _print_vg(struct formatter *f, struct volume_group *vg) +{ + char buffer[256]; + + if (!id_write_format(&vg.uuid, buffer, sizeof(buffer))) { + stack; + return 0; + } + + _out(f, "id = \"%s\"", buffer); + _nl(f); + + if (!_print_flags(vg->status, _vg_flags, buffer, size)) { + stack; + return 0; + } + + _out(f, "status = %s"); + _nl(f); + + _out_size(f, vg->extent_size, "extent_size = %u", vg->extent_size); + _nl(f); + + _out(f, "max_lv = %u", vg->max_lv); + _out(f, "max_pv = %u", vg->max_pv); + _nl(f); + + return 1; +} + +/* + * Get the pv%d name from the formatters hash + * table. + */ +static inline const char * +_get_pv_name(struct formatter *f, struct physical_volume *pv) +{ + return (const char *) hash_lookup(f->pv_names, dev_name(pv)); +} + +static int _print_pvs(struct formatter *f, struct volume_group *vg) +{ + struct list pvh; + struct physical_volume *pv; + char buffer[256]; + const char *name; + + _out(f, "physical_volumes {"); + _nl(f); + _inc_indent(f); + + list_iterate (pvh, &vg->pvs) { + + if (!(name = _get_pv_name(f, pv))) { + stack; + return 0; + } + + _out(f, "%s {", name); + _inc_indent(f); + + pv = &list_item(pvh, struct pv_list)->pv; + + if (!id_write_format(&pv->uuid, buffer, sizeof(buffer))) { + stack; + return 0; + } + + _out(f, "tid = \"%s\"", buffer); + _out_hint(f, "device = %s", dev_name(pv->dev)); + _nl(f); + + if (!print_flags(pv->status, _pv_flags, + buffer, sizeof(buffer))) { + stack; + return 0; + } + + _out(f, "status = %s", buffer); + _out(f, "pe_start = %u", pv->pe_start); + _out_size(f, vg->extent_size * (uint64_t) pv->pe_count, + "pe_count = %u", pv->pe_count); + + _dec_indent(f); + _out(f, "}"); + _nl(f); + } + + _dec_indent(f); + _out(f, "}"); + return 1; +} + +static int _print_segment(struct formatter *f, struct volume_group *vg, + int count, struct stripe_segment *seg, int last) +{ + int s; + const char *name; + + _out(f, "segment%u {", count); + _inc_indent(f); + + _out(f, "start_entent = %u", seg->le); + _out_size(f, seg->len * vg->extent_size, "extent_count = %u", seg->len); + _out(f, "stripes = %u", seg->stripes); + + if (seg->stripes > 1) + _out_size(f, "stripe_size = %u", seg->stripe_size); + + _nl(f); + _out(f, "areas = ["); + _inc_indent(f); + + for (s = 0; s < seg->stripes; s++) { + if (!(name = _get_pv_name(f, seg->areas[s].pv))) { + stack; + return 0; + } + + _out(f, "\"%s\", %u%s", name, seg->area[s].pe, + last ? "" : ","); + } + + _dec_indent(f); + _out(f, "]"); + + _dec_indent(f); + _out(f, "}"); + + return 1; +} + +static int _print_lvs(struct formatter *f, struct volume_group *vg) +{ + struct list *lvh, *segh; + struct logical_volume *lv; + struct stripe_segment *seg; + char buffer[256]; + int seg_count = 1; + + _out(f, "logical_volumes {"); + _nl(f); + _inc_indent(f); + + list_iterate (lvh, &vg->lvs) { + lv = &list_item(lvh, struct lv_list)->lv; + + _out(f, "%s {", lv->name); + _inc_indent(f); + + if (!_print_flags(lv->status, _lv_flags, + buffer, sizeof(buffer))) { + stack; + return 0; + } + + _out(f, "read_ahead = %u", lv->read_ahead); + _nl(f); + + _out(f, "segment_count = %u", _count_segments(lv)); + _nl(f); + + list_iterate (segh, &lv->segments) { + seg = list_item(segh, struct stripe_segment); + + if (!_print_segment(f, seg_count++, seg)) { + stack; + return 0; + } + } + + _out(f, "}"); + _dec_indent(f); + } + + _out(f, "}"); + _nl(f); + _dec_indent(f); + + return 1; +} + +/* + * In the text format we refer to pv's as 'pv1', + * 'pv2' etc. This function builds a hash table + * to enable a quick lookup from device -> name. + */ +static int _build_pv_names(struct formatter *f, + struct volume_group *vg) +{ + int count = 0; + struct list *pvh; + struct physical_volume *pv; + char buffer[32], *name; + + if (!(f->mem = pool_create(512))) { + stack; + goto bad; + } + + if (!(f->pv_names = hash_create(128))) { + stack; + goto bad; + } + + list_iterate (pvh, &vg->pvs) { + pv = &list_item(pvh, struct pv_list)->pv; + + if (snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) { + stack; + goto bad; + } + + if (!(name = pool_strdup(f->mem, buffer))) { + stack; + goto bad; + } + + if (!hash_insert(f->pv_names, dev_name(pv->dev), buffer)) { + stack; + goto bad; + } + } + + return 1; + + bad: + if (f->mem) + pool_destroy(f->mem); + + if (f->pv_names) + hash_destroy(f->pv_names); + + return 0; +} + +int text_vg_export(FILE *fp, struct volume_group *vg) +{ + int r = 0; + struct formatter *f; + + if (!f = dbg_malloc(sizeof(*f))) { + stack; + return 0; + } + + memset(f, 0, sizeof(*f)); + f->fp = fp; + f->indent = 0; + + if (!_build_pv_names(f, vg)) { + stack; + goto out; + } + +#define fail do {stack; goto out;} while(0) + + if (!_print_header(f, vg)) + fail; + + _out(f, "%s {", vg->name); + _inc_indent(f): + + if (!_print_vg(f, vg)) + fail; + + if (!_print_pvs(f, vg)) + fail; + + if (!_print_lvs(f, vg)) + fail; + +#undef fail + + _dec_indent(f); + _out(f, "}"); + + r = 1; + + out: + if (f->mem) + pool_destroy(f->mem); + + if (f->pv_names) + hash_destroy(f->pv_names); + + dbg_free(f): + return r; +} diff --git a/lib/format_text/import-export.c b/lib/format_text/import-export.c deleted file mode 100644 index a6082579e..000000000 --- a/lib/format_text/import-export.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software (UK) Limited. - * - * This file is released under the LGPL. - */ - -#include "text-rep.h" -#include "metadata.h" -#include "log.h" - -#include - -struct flag { - int mask; - char *description; -}; - -static struct flag _vg_flags[] = { - {ACTIVE, "ACTIVE"}, - {EXPORTED_VG, "EXPORTED"}, - {EXTENDABLE_VG, "EXTENDABLE"}, - {CLUSTERED, "CLUSTERED"}, - {SHARED, "SHARED"}, - {0, NULL} -}; - -static struct flag _pv_flags[] = { - {ACTIVE, "ACTIVE"}, - {ALLOCATED_PV, "ALLOCATED"}, - {0, NULL} -}; - -static struct flag _lv_flags[] = { - {ACTIVE, "ACTIVE"}, - {READ, "READ"}, - {WRITE, "WRITE"}, - {ALLOC_SIMPLE, "ALLOC_SIMPLE"}, - {ALLOC_STRICT, "ALLOC_STRICT"}, - {ALLOC_CONTIGUOUS, "ALLOC_CONTIGUOUS"}, - {SNAPSHOT, "SNASHOT"}, - {SNAPSHOT_ORG, "SNAPSHOT_ORIGIN"}, - {0, NULL} -}; - -static void _print_flags(uint32_t status, struct flag *flags, FILE *fp) -{ - int f, first = 1; - - fprintf(fp, "["); - for (f = 0; flags[f].mask; f++) { - if (status & flags[f].mask) { - if (!first) - fprintf(fp, ", "); - else - first = 0; - - fprintf(fp, "\"%s\"", flags[f].name); - status &= ~flags[f].mask; - } - } - fprintf(fp, "]"); - - if (status) - /* FIXME: agk is this the correct log level ? */ - log_print("Not all flags were successfully exported, " - "possible bug."); -} - -static int _print_header(FILE *fp, struct volume_group *vg) -{ - fprintf(fp, "# This file was generated by the LVM2 library\n" - "# %s\n\n", ctime(time(NULL))); - return 1; -} - -static int _print_vg(FILE *fp, struct volume_group *vg) -{ - fprintf(fp, "volume_group {\n"); - - fprintf(fp, "\tid = "); - _print_uuid(&vg.uuid); - fprintf(fp, "\n\tname = \"%s\"\n", vg->name); - - fprintf(fp, "\tstatus = "); - _print_flags(fp, vg->status, _vg_flags); - - fprintf(fp, "\n\textent_size = %u", vg->extent_size); - _print_size_comment(fp, vg->extent_size); - - fprintf(fp, "\tmax_lv = %u\n", vg->max_lv); - fprintf(fp, "\tmax_pv = %u\n", vg->max_pv); - fprintf(fp, "}\n"); - return 1; -} - -static int _print_pvs(FILE *fp, struct volume_group *vg) -{ - struct list pvh; - struct physical_volume *pv; - int count; - - fprintf(fp, "physical_volumes {\n\n"); - - list_iterate (pvh, &vg->pvs) { - fprintf(fp, "\tpv%d {\n", count++); - pv = &list_item(pvh, struct pv_list)->pv; - fprintf(fp, "\t\tid = "); - _print_uuid(fp, &pv->uuid); - fprintf(fp, "\n\t\tdevice = %s\t# Hint only\n\n", - dev_name(pv->dev)); - - fprintf(fp, "\t\tstatus = "); - _print_flags(fp, pv->status, _pv_flags); - - fprintf(fp, "\n\n\t\tpe_start = %u\n"); - fprintf(fp, "\t\tpe_count = %u", pv->pe_count); - _print_size_comment(fp, pe_count * vg->extent_size); - _fprintf(fp, "\n\t}\n") - } - - fprintf(fp, "}\n\n"); - return 1; -} - -static int _print_lvs(FILE *fp, struct volume_group *vg) -{ - struct list *lvh; - struct logical_volume *lv; - - fprintf(fp, "logical_volumes {\n"); - - list_iterate (lvh, &vg->lvs) { - lv = &list_item(lvh, struct lv_list)->lv; - - - } - - fprintf(fp, "}\n"); - return 1; -} - -struct volume_group *text_vg_import(struct pool *mem, struct config_file *cf) -{ - log_err("text_vg_import not implemented yet."); - return NULL; -} - -int text_vg_export(FILE *fp, struct volume_group *vg) -{ -#define fail do {stack; return 0;} while(0) - - if (!_print_header(fp, vg)) - fail; - - if (!_print_vg(fp, vg)) - fail; - - if (!_print_pvs(fp, vg)) - fail; - - if (!_print_lvs(fp, vg)) - fail; - -#undef fail - - return 1; -} - diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index 766ebabbd..8de853ecf 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -7,7 +7,19 @@ #ifndef _LVM_TEXT_IMPORT_EXPORT_H #define _LVM_TEXT_IMPORT_EXPORT_H +#include "config.h" + +enum { + VG_FLAGS, + PV_FLAGS, + LV_FLAGS +}; + +int print_flags(uint32_t status, int type, char *buffer, size_t size); +int read_flags(uint32_t *status, int type, struct config_value *cv); + + +int text_vg_export(FILE *fp, struct volume_group *vg); struct volume_group *text_vg_import(struct pool *mem, struct config_file *cf); -struct config_file *text_vg_export(struct pool *mem, struct volume_group *vg); #endif