mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Fix automatic text metadata buffer expansion (using macro). [stdarg usage bug]
Cache formatted text metadata buffer between metadata area writes. [improves write performance when lots of metadata area clones]
This commit is contained in:
parent
31b5c6e65c
commit
78aa12e1dc
@ -1,5 +1,7 @@
|
||||
Version 2.02.00 -
|
||||
===================================
|
||||
Fix automatic text metadata buffer expansion (using macro).
|
||||
Cache formatted text metadata buffer between metadata area writes.
|
||||
Add pe_start field to pvs.
|
||||
Add 'LVM-' prefix to uuids.
|
||||
Split lv_segment_area from lv_segment to permit extension.
|
||||
|
@ -29,6 +29,19 @@ struct formatter;
|
||||
typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
|
||||
const char *fmt, va_list ap);
|
||||
typedef int (*nl_fn) (struct formatter * f);
|
||||
|
||||
/*
|
||||
* Macro for formatted output.
|
||||
* out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
|
||||
* Then argument list is reset and out_with_comment_fn is called again.
|
||||
*/
|
||||
#define _out_with_comment(f, buffer, fmt, ap) \
|
||||
do { \
|
||||
va_start(ap, fmt); \
|
||||
r = f->out_with_comment(f, buffer, fmt, ap); \
|
||||
va_end(ap); \
|
||||
} while (r == -1)
|
||||
|
||||
/*
|
||||
* The first half of this file deals with
|
||||
* exporting the vg, ie. writing it to a file.
|
||||
@ -100,19 +113,30 @@ static int _nl_file(struct formatter *f)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _nl_raw(struct formatter *f)
|
||||
static int _extend_buffer(struct formatter *f)
|
||||
{
|
||||
char *newbuf;
|
||||
|
||||
/* If metadata doesn't fit, double the buffer size */
|
||||
if (f->data.buf.used + 2 > f->data.buf.size) {
|
||||
if (!(newbuf = dm_realloc(f->data.buf.start,
|
||||
f->data.buf.size * 2))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
f->data.buf.start = newbuf;
|
||||
f->data.buf.size *= 2;
|
||||
log_debug("Doubling metadata output buffer to %" PRIu32,
|
||||
f->data.buf.size * 2);
|
||||
if (!(newbuf = dm_realloc(f->data.buf.start,
|
||||
f->data.buf.size * 2))) {
|
||||
log_error("Buffer reallocation failed.");
|
||||
return 0;
|
||||
}
|
||||
f->data.buf.start = newbuf;
|
||||
f->data.buf.size *= 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _nl_raw(struct formatter *f)
|
||||
{
|
||||
/* If metadata doesn't fit, extend buffer */
|
||||
if ((f->data.buf.used + 2 > f->data.buf.size) &&
|
||||
(!_extend_buffer(f))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(f->data.buf.start + f->data.buf.used) = '\n';
|
||||
@ -163,22 +187,17 @@ static int _out_with_comment_raw(struct formatter *f, const char *comment,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
int n;
|
||||
char *newbuf;
|
||||
|
||||
retry:
|
||||
n = vsnprintf(f->data.buf.start + f->data.buf.used,
|
||||
f->data.buf.size - f->data.buf.used, fmt, ap);
|
||||
|
||||
/* If metadata doesn't fit, double the buffer size */
|
||||
/* If metadata doesn't fit, extend buffer */
|
||||
if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
|
||||
if (!(newbuf = dm_realloc(f->data.buf.start,
|
||||
f->data.buf.size * 2))) {
|
||||
if (!_extend_buffer(f)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
f->data.buf.start = newbuf;
|
||||
f->data.buf.size *= 2;
|
||||
goto retry;
|
||||
return -1; /* Retry */
|
||||
}
|
||||
|
||||
f->data.buf.used += n;
|
||||
@ -229,9 +248,7 @@ int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
||||
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = f->out_with_comment(f, buffer, fmt, ap);
|
||||
va_end(ap);
|
||||
_out_with_comment(f, buffer, fmt, ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -245,9 +262,7 @@ int out_hint(struct formatter *f, const char *fmt, ...)
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = f->out_with_comment(f, "# Hint only", fmt, ap);
|
||||
va_end(ap);
|
||||
_out_with_comment(f, "# Hint only", fmt, ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -260,9 +275,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = f->out_with_comment(f, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
_out_with_comment(f, NULL, fmt, ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -43,6 +43,11 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
void *context);
|
||||
|
||||
struct text_fid_context {
|
||||
char *raw_metadata_buf;
|
||||
uint32_t raw_metadata_buf_size;
|
||||
};
|
||||
|
||||
struct dir_list {
|
||||
struct list list;
|
||||
char dir[0];
|
||||
@ -337,12 +342,12 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
|
||||
struct raw_locn *rlocn;
|
||||
struct mda_header *mdah;
|
||||
struct pv_list *pvl;
|
||||
int r = 0;
|
||||
uint32_t new_wrap = 0, old_wrap = 0;
|
||||
char *buf = NULL;
|
||||
int found = 0;
|
||||
|
||||
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
|
||||
@ -369,11 +374,15 @@ 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))) {
|
||||
if (!fidtc->raw_metadata_buf &&
|
||||
!(fidtc->raw_metadata_buf_size =
|
||||
text_vg_export_raw(vg, "", &fidtc->raw_metadata_buf))) {
|
||||
log_error("VG %s metadata writing failed", vg->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
mdac->rlocn.size = fidtc->raw_metadata_buf_size;
|
||||
|
||||
if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size)
|
||||
new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size;
|
||||
|
||||
@ -396,7 +405,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
|
||||
/* Write text out, circularly */
|
||||
if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
|
||||
(size_t) (mdac->rlocn.size - new_wrap), buf)) {
|
||||
(size_t) (mdac->rlocn.size - new_wrap),
|
||||
fidtc->raw_metadata_buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@ -409,18 +419,20 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!dev_write(mdac->area.dev,
|
||||
mdac->area.start + MDA_HEADER_SIZE,
|
||||
(size_t) new_wrap,
|
||||
buf + mdac->rlocn.size - new_wrap)) {
|
||||
fidtc->raw_metadata_buf +
|
||||
mdac->rlocn.size - new_wrap)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mdac->rlocn.checksum = calc_crc(INITIAL_CRC, buf,
|
||||
mdac->rlocn.checksum = calc_crc(INITIAL_CRC, fidtc->raw_metadata_buf,
|
||||
(uint32_t) (mdac->rlocn.size -
|
||||
new_wrap));
|
||||
if (new_wrap)
|
||||
mdac->rlocn.checksum = calc_crc(mdac->rlocn.checksum,
|
||||
buf + mdac->rlocn.size -
|
||||
fidtc->raw_metadata_buf +
|
||||
mdac->rlocn.size -
|
||||
new_wrap, new_wrap);
|
||||
|
||||
r = 1;
|
||||
@ -429,8 +441,6 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!r && !dev_close(mdac->area.dev))
|
||||
stack;
|
||||
|
||||
if (buf)
|
||||
dm_free(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -440,6 +450,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
int precommit)
|
||||
{
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
|
||||
struct mda_header *mdah;
|
||||
struct raw_locn *rlocn;
|
||||
struct pv_list *pvl;
|
||||
@ -488,8 +499,14 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
if (!precommit && !dev_close(mdac->area.dev))
|
||||
stack;
|
||||
if (!precommit) {
|
||||
if (!dev_close(mdac->area.dev))
|
||||
stack;
|
||||
if (fidtc->raw_metadata_buf) {
|
||||
dm_free(fidtc->raw_metadata_buf);
|
||||
fidtc->raw_metadata_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -512,6 +529,7 @@ static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
|
||||
struct pv_list *pvl;
|
||||
int found = 0;
|
||||
|
||||
@ -529,6 +547,11 @@ static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!dev_close(mdac->area.dev))
|
||||
stack;
|
||||
|
||||
if (fidtc->raw_metadata_buf) {
|
||||
dm_free(fidtc->raw_metadata_buf);
|
||||
fidtc->raw_metadata_buf = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1401,6 +1424,7 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
void *context)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
struct text_fid_context *fidtc;
|
||||
struct metadata_area *mda, *mda_new;
|
||||
struct mda_context *mdac, *mdac_new;
|
||||
struct dir_list *dl;
|
||||
@ -1415,8 +1439,16 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fid->fmt = fmt;
|
||||
if (!(fidtc = (struct text_fid_context *)
|
||||
dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
|
||||
log_error("Couldn't allocate text_fid_context.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fidtc->raw_metadata_buf = NULL;
|
||||
fid->private = (void *) fidtc;
|
||||
|
||||
fid->fmt = fmt;
|
||||
list_init(&fid->metadata_areas);
|
||||
|
||||
if (!vgname) {
|
||||
|
@ -181,6 +181,7 @@ struct metadata_area {
|
||||
struct format_instance {
|
||||
const struct format_type *fmt;
|
||||
struct list metadata_areas; /* e.g. metadata locations */
|
||||
void *private;
|
||||
};
|
||||
|
||||
struct volume_group {
|
||||
|
Loading…
Reference in New Issue
Block a user