mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
Remove hard-coded 64k text metadata writing restriction.
This commit is contained in:
parent
8b80d2a57c
commit
5748cb17f8
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user