1
0
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:
Alasdair Kergon 2005-10-23 00:14:48 +00:00
parent 31b5c6e65c
commit 78aa12e1dc
4 changed files with 86 additions and 38 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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) {

View File

@ -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 {