1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

format_text: Move metadata size checking into separate fn.

Move checks into _metadata_fits_into_buffer() and add macro for alignment.
This commit is contained in:
Alasdair G Kergon 2017-12-11 17:08:29 +00:00
parent 46393bfca0
commit 2db67a8ea0

View File

@ -37,6 +37,12 @@
#include <dirent.h>
#include <ctype.h>
/*
* Round up offset within buffer to next location that is an exact multiple of alignment.
* (We shouldn't assume the start of the metadata area was aligned the same way when it was created.)
*/
#define ALIGN_ABSOLUTE(offset, buffer_start, alignment) ((offset) + (alignment) - UINT64_C(1) - ((buffer_start) + (offset) + (alignment) - UINT64_C(1)) % (alignment))
static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
const struct format_instance_ctx *fic);
@ -615,6 +621,34 @@ static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
return vg;
}
static int _metadata_fits_into_buffer(struct mda_context *mdac, struct mda_header *mdah,
struct raw_locn *rlocn, uint64_t new_wrap)
{
uint64_t old_wrap = 0; /* Amount of wrap around in existing metadata */
uint64_t new_end; /* The end location of the new metadata */
/* Do we have existing metadata that ends beyond the end of the buffer? */
if (rlocn && (rlocn->offset + rlocn->size > mdah->size))
old_wrap = (rlocn->offset + rlocn->size) - mdah->size;
new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE :
mdac->rlocn.offset + mdac->rlocn.size;
/* If both wrap around, there's necessarily overlap */
if (new_wrap && old_wrap)
return_0;
/* If either wraps around, does the new end fall beyond the old start? */
if (rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset))
return_0;
/* Does the total amount of metadata, old and new, fit inside the buffer? */
if (MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size)
return_0;
return 1;
}
static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
{
@ -624,7 +658,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_header *mdah;
struct pv_list *pvl;
int r = 0;
uint64_t new_wrap = 0, old_wrap = 0, new_end;
uint64_t new_wrap; /* Number of bytes of new metadata that wrap around to start of buffer */
int found = 0;
int noprecommit = 0;
const char *old_vg_name = NULL;
@ -657,21 +691,16 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
rlocn = _find_vg_rlocn(&mdac->area, mdah, mda_is_primary(mda), old_vg_name ? : vg->name, &noprecommit);
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah, mdac->area.start, MDA_ORIGINAL_ALIGNMENT);
mdac->rlocn.size = fidtc->raw_metadata_buf_size;
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah, mdac->area.start, MDA_ORIGINAL_ALIGNMENT);
if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size)
new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size;
else
new_wrap = 0;
if (rlocn && (rlocn->offset + rlocn->size > mdah->size))
old_wrap = (rlocn->offset + rlocn->size) - mdah->size;
new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE :
mdac->rlocn.offset + mdac->rlocn.size;
if ((new_wrap && old_wrap) ||
(rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset)) ||
(MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size)) {
if (!_metadata_fits_into_buffer(mdac, mdah, rlocn, new_wrap)) {
log_error("VG %s metadata on %s (" FMTu64 " bytes) too large for circular buffer (" FMTu64 " bytes with " FMTu64 " used)",
vg->name, dev_name(mdac->area.dev), mdac->rlocn.size, mdah->size - MDA_HEADER_SIZE, rlocn ? rlocn->size : 0);
goto out;
@ -1263,8 +1292,8 @@ int vgname_from_mda(const struct format_type *fmt,
(char *)&vgsummary->vgid);
if (mda_free_sectors) {
current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
(rlocn->size + SECTOR_SIZE - UINT64_C(1)) % SECTOR_SIZE;
current_usage = ALIGN_ABSOLUTE(rlocn->size, 0, MDA_ORIGINAL_ALIGNMENT);
buffer_size = mdah->size - MDA_HEADER_SIZE;
if (current_usage * 2 >= buffer_size)