From 5748cb17f8809111f13bc83c9302b3b87e382379 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Tue, 7 Jun 2005 11:00:07 +0000 Subject: [PATCH] Remove hard-coded 64k text metadata writing restriction. --- WHATS_NEW | 1 + lib/format_text/export.c | 94 +++++++++++++++++++++------------ lib/format_text/format-text.c | 8 +-- lib/format_text/import-export.h | 3 +- lib/format_text/text_export.h | 1 + lib/metadata/lv_manip.c | 4 +- 6 files changed, 71 insertions(+), 40 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index d7a40731e..c23eda52c 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.01.11 - ============================== + Remove hard-coded 64k text metadata writing restriction. Make VG name restrictions consistent. Introduce lvconvert. So far only removes mirror images. Allow mirror images to be resized. diff --git a/lib/format_text/export.c b/lib/format_text/export.c index f84682b6d..b6179cfbb 100644 --- a/lib/format_text/export.c +++ b/lib/format_text/export.c @@ -30,7 +30,7 @@ struct formatter; typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment, const char *fmt, va_list ap); -typedef void (*nl_fn) (struct formatter * f); +typedef int (*nl_fn) (struct formatter * f); /* * The first half of this file deals with * exporting the vg, ie. writing it to a file. @@ -42,7 +42,7 @@ struct formatter { union { FILE *fp; /* where we're writing to */ struct { - char *buf; + char *start; uint32_t size; uint32_t used; } buf; @@ -95,22 +95,34 @@ static void _dec_indent(struct formatter *f) /* * Newline function for prettier layout. */ -static void _nl_file(struct formatter *f) +static int _nl_file(struct formatter *f) { fprintf(f->data.fp, "\n"); + + return 1; } -static void _nl_raw(struct formatter *f) +static int _nl_raw(struct formatter *f) { - if (f->data.buf.used >= f->data.buf.size - 1) - return; + char *newbuf; - *f->data.buf.buf = '\n'; - f->data.buf.buf += 1; + /* If metadata doesn't fit, double the buffer size */ + if (f->data.buf.used + 2 > f->data.buf.size) { + if (!(newbuf = dbg_realloc(f->data.buf.start, + f->data.buf.size * 2))) { + stack; + return 0; + } + f->data.buf.start = newbuf; + f->data.buf.size *= 2; + } + + *(f->data.buf.start + f->data.buf.used) = '\n'; f->data.buf.used += 1; - *f->data.buf.buf = '\0'; - return; + *(f->data.buf.start + f->data.buf.used) = '\0'; + + return 1; } #define COMMENT_TAB 6 @@ -153,17 +165,27 @@ static int _out_with_comment_raw(struct formatter *f, const char *comment, const char *fmt, va_list ap) { int n; + char *newbuf; - n = vsnprintf(f->data.buf.buf, f->data.buf.size - f->data.buf.used, - fmt, ap); + retry: + n = vsnprintf(f->data.buf.start + f->data.buf.used, + f->data.buf.size - f->data.buf.used, fmt, ap); - if (n < 0 || (n > f->data.buf.size - f->data.buf.used - 1)) - return 0; + /* If metadata doesn't fit, double the buffer size */ + if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) { + if (!(newbuf = dbg_realloc(f->data.buf.start, + f->data.buf.size * 2))) { + stack; + return 0; + } + f->data.buf.start = newbuf; + f->data.buf.size *= 2; + goto retry; + } - f->data.buf.buf += n; f->data.buf.used += n; - f->nl(f); + outnl(f); return 1; } @@ -257,10 +279,10 @@ static int _print_header(struct formatter *f, outf(f, "# Generated by LVM2: %s", ctime(&t)); outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\""); outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE); - f->nl(f); + outnl(f); outf(f, "description = \"%s\"", desc); - f->nl(f); + outnl(f); outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename, _utsname.sysname, _utsname.nodename, _utsname.release, _utsname.version, _utsname.machine); @@ -309,7 +331,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg) /* Default policy is NORMAL; INHERIT is meaningless */ if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) { - f->nl(f); + outnl(f); outf(f, "allocation_policy = \"%s\"", get_alloc_string(vg->alloc)); } @@ -346,7 +368,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg) return 0; } - f->nl(f); + outnl(f); outf(f, "%s {", name); _inc_indent(f); @@ -360,7 +382,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg) stack; return 0; } - f->nl(f); + outnl(f); if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) { stack; @@ -407,7 +429,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg, return 0; } - f->nl(f); + outnl(f); outf(f, "type = \"%s\"", seg->segtype->name); if (!list_empty(&seg->tags)) { @@ -436,7 +458,7 @@ int out_areas(struct formatter *f, const struct lv_segment *seg, const char *name; unsigned int s; - f->nl(f); + outnl(f); outf(f, "%ss = [", type); _inc_indent(f); @@ -472,7 +494,7 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv) char buffer[4096]; int seg_count; - f->nl(f); + outnl(f); outf(f, "%s {", lv->name); _inc_indent(f); @@ -509,7 +531,7 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv) if (lv->minor >= 0) outf(f, "minor = %d", lv->minor); outf(f, "segment_count = %u", list_size(&lv->segments)); - f->nl(f); + outnl(f); seg_count = 1; list_iterate_items(seg, &lv->segments) { @@ -641,11 +663,11 @@ static int _text_vg_export(struct formatter *f, if (!_print_vg(f, vg)) fail; - f->nl(f); + outnl(f); if (!_print_pvs(f, vg)) fail; - f->nl(f); + outnl(f); if (!_print_lvs(f, vg)) fail; @@ -696,11 +718,10 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp) } /* Returns amount of buffer used incl. terminating NUL */ -int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf, - uint32_t size) +int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf) { struct formatter *f; - int r; + int r = 0; _init(); @@ -710,8 +731,13 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf, } memset(f, 0, sizeof(*f)); - f->data.buf.buf = buf; - f->data.buf.size = size; + + f->data.buf.size = 65536; /* Initial metadata limit */ + if (!(f->data.buf.start = dbg_malloc(f->data.buf.size))) { + log_error("text_export buffer allocation failed"); + goto out; + } + f->indent = 0; f->header = 0; f->out_with_comment = &_out_with_comment_raw; @@ -719,11 +745,12 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf, if (!_text_vg_export(f, vg, desc)) { stack; - r = 0; + dbg_free(f->data.buf.start); goto out; } r = f->data.buf.used + 1; + *buf = f->data.buf.start; out: dbg_free(f); @@ -731,3 +758,4 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf, } #undef outf +#undef outnl diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 9dfb5dbf3..97708e321 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -344,9 +344,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, struct pv_list *pvl; int r = 0; uint32_t new_wrap = 0, old_wrap = 0; - - /* FIXME Essential fix! Make dynamic (realloc? pool?) */ - char buf[65536]; + char *buf = NULL; int found = 0; /* Ignore any mda on a PV outside the VG. vgsplit relies on this */ @@ -373,7 +371,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0); mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah); - if (!(mdac->rlocn.size = text_vg_export_raw(vg, "", buf, sizeof(buf)))) { + if (!(mdac->rlocn.size = text_vg_export_raw(vg, "", &buf))) { log_error("VG %s metadata writing failed", vg->name); goto out; } @@ -433,6 +431,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, if (!r && !dev_close(mdac->area.dev)) stack; + if (buf) + dbg_free(buf); return r; } diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index f36ba4adc..71eb03e8b 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -59,8 +59,7 @@ int print_tags(struct list *tags, char *buffer, size_t size); int read_tags(struct pool *mem, struct list *tags, struct config_value *cv); int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp); -int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf, - uint32_t size); +int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf); struct volume_group *text_vg_import_file(struct format_instance *fid, const char *file, time_t *when, char **desc); diff --git a/lib/format_text/text_export.h b/lib/format_text/text_export.h index fdc42c1c0..a8ea6689e 100644 --- a/lib/format_text/text_export.h +++ b/lib/format_text/text_export.h @@ -17,6 +17,7 @@ #define _LVM_TEXT_EXPORT_H #define outf(args...) do {if (!out_text(args)) {stack; return 0;}} while (0) +#define outnl(f) do {if (!f->nl(f)) {stack; return 0;}} while (0) struct formatter; struct lv_segment; diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 4b33cb1bf..b23e23281 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -537,6 +537,7 @@ static int _check_contiguous(struct lv_segment *prev_lvseg, /* * Choose sets of parallel areas to use, respecting any constraints. */ +/* FIXME Also accept existing areas new space must be parallel to */ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc, struct list *pvms, struct pv_area **areas, uint32_t areas_size, unsigned can_split, @@ -634,6 +635,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc, _comp_area); /* First time around, use smallest area as log_area */ + /* FIXME decide which PV to use at top of function instead */ if (!_alloc_parallel_area(ah, needed, areas, allocated, (ah->log_count && !ah->log_area.len) ? @@ -994,7 +996,7 @@ int lv_extend(struct logical_volume *lv, return 0; } - if (!mirrors) { + if (mirrors < 2) { if (!lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size, mirrored_pv, mirrored_pe, status, 0, NULL)) { stack; -- 2.43.5