1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

format_text: Refactor and document metadata offset calculation.

This commit is contained in:
Alasdair G Kergon 2017-12-12 18:36:54 +00:00
parent e932c5da50
commit 4002f5e206

View File

@ -476,7 +476,9 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
} }
/* /*
* Determine offset for uncommitted metadata * Find first aligned offset after end of existing metadata.
* Based on the alignment provided, this is the exact offset to use for the new metadata.
* The caller is responsible for validating the result.
*/ */
static uint64_t _next_rlocn_offset(struct raw_locn *rlocn, struct mda_header *mdah, uint64_t mdac_area_start, uint64_t alignment) static uint64_t _next_rlocn_offset(struct raw_locn *rlocn, struct mda_header *mdah, uint64_t mdac_area_start, uint64_t alignment)
{ {
@ -484,7 +486,7 @@ static uint64_t _next_rlocn_offset(struct raw_locn *rlocn, struct mda_header *md
if (!rlocn) if (!rlocn)
/* Find an empty slot */ /* Find an empty slot */
/* FIXME Assume only one VG per mdah for now */ /* FIXME Assumes only one VG per mdah for now */
return alignment; return alignment;
/* Calculate new start position relative to start of buffer rounded up to absolute alignment */ /* Calculate new start position relative to start of buffer rounded up to absolute alignment */
@ -626,23 +628,28 @@ static int _metadata_fits_into_buffer(struct mda_context *mdac, struct mda_heade
uint64_t old_wrap = 0; /* Amount of wrap around in existing metadata */ uint64_t old_wrap = 0; /* Amount of wrap around in existing metadata */
uint64_t new_end; /* The end location of the new 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? */ /* Does the total amount of metadata, old and new, fit inside the buffer? */
if (rlocn && (rlocn->offset + rlocn->size > mdah->size)) if (MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size)
old_wrap = (rlocn->offset + rlocn->size) - mdah->size; return_0;
new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE : /* Does the existing metadata wrap around the end of the buffer? */
mdac->rlocn.offset + mdac->rlocn.size; if (rlocn) {
if (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 both wrap around, there's necessarily overlap */
if (new_wrap && old_wrap) if (new_wrap && old_wrap)
return_0; return_0;
/* If either wraps around, does the new end fall beyond the old start? */ /* If there's no existing metadata, we're OK */
if (rlocn && (new_wrap || old_wrap) && (new_end > rlocn->offset)) if (!rlocn)
return_0; return 1;
/* Does the total amount of metadata, old and new, fit inside the buffer? */ /* If either wraps around, there's overlap if the new end falls beyond the old start */
if (MDA_HEADER_SIZE + (rlocn ? rlocn->size : 0) + mdac->rlocn.size >= mdah->size) if ((new_wrap || old_wrap) && (new_end > rlocn->offset))
return_0; return_0;
return 1; return 1;
@ -658,6 +665,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct pv_list *pvl; struct pv_list *pvl;
int r = 0; int r = 0;
uint64_t new_wrap; /* Number of bytes of new metadata that wrap around to start of buffer */ uint64_t new_wrap; /* Number of bytes of new metadata that wrap around to start of buffer */
uint64_t alignment = MDA_ORIGINAL_ALIGNMENT;
int found = 0; int found = 0;
int noprecommit = 0; int noprecommit = 0;
const char *old_vg_name = NULL; const char *old_vg_name = NULL;
@ -675,6 +683,12 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if (!found) if (!found)
return 1; return 1;
/*
* This is paired with the following closes:
* - at the end of this fn if returning 0
* - in _vg_commit_raw_rlocn regardless of return code
* which handles commit (but not pre-commit) and revert.
*/
if (!dev_open(mdac->area.dev)) if (!dev_open(mdac->area.dev))
return_0; return_0;
@ -692,8 +706,10 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
mdac->rlocn.size = fidtc->raw_metadata_buf_size; mdac->rlocn.size = fidtc->raw_metadata_buf_size;
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah, mdac->area.start, MDA_ORIGINAL_ALIGNMENT); /* Find where the new metadata would be written with our preferred alignment */
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah, mdac->area.start, alignment);
/* Does the new metadata wrap around? */
if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size) if (mdac->rlocn.offset + mdac->rlocn.size > mdah->size)
new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size; new_wrap = (mdac->rlocn.offset + mdac->rlocn.size) - mdah->size;
else else
@ -705,9 +721,9 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
goto out; goto out;
} }
log_debug_metadata("Writing %s metadata to %s at " FMTu64 " len " FMTu64 " of " FMTu64, log_debug_metadata("Writing %s metadata to %s at " FMTu64 " len " FMTu64 " of " FMTu64 " aligned to " FMTu64,
vg->name, dev_name(mdac->area.dev), mdac->area.start + vg->name, dev_name(mdac->area.dev), mdac->area.start +
mdac->rlocn.offset, mdac->rlocn.size - new_wrap, mdac->rlocn.size); mdac->rlocn.offset, mdac->rlocn.size - new_wrap, mdac->rlocn.size, alignment);
/* Write text out, circularly */ /* Write text out, circularly */
if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset, if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
@ -837,6 +853,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
out: out:
if (!precommit) { if (!precommit) {
/* This is an paired with the open at the start of _vg_write_raw */
if (!dev_close(mdac->area.dev)) if (!dev_close(mdac->area.dev))
stack; stack;