[Some activation-related features will stop working for a while now.
Some types of activation are getting split into two steps, with the
first step using the precommitted metadata.]
Version 2.02.00 -
===================================
+ Clear up precommitted metadata better.
A pvresize implementation.
Fix contiguous allocation when there are no preceding segments.
Add mirror_seg pointer to lv_segment struct.
{
struct logical_volume *lv;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
return _lv_info(cmd, lv, 0, info, with_open_count);
if (!activation())
return 1;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ /* Use precommitted metadata if present */
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
return 0;
if (test_mode()) {
if (!activation())
return 1;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (test_mode()) {
if (!activation())
return 1;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (test_mode()) {
if (!activation())
goto activate;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (!_passes_activation_filter(cmd, lv)) {
if (!activation())
return 1;
- if (!(lv = lv_from_lvid(cmd, lvid_s)))
+ if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
return 0;
if (filter && !_passes_activation_filter(cmd, lv)) {
static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
struct mda_header *mdah,
const char *vgname,
- int precommit)
+ int *precommitted)
{
size_t len;
char vgnamebuf[NAME_LEN + 2];
- struct raw_locn *rlocn;
+ struct raw_locn *rlocn, *rlocn_precommitted;
struct lvmcache_info *info;
rlocn = mdah->raw_locns; /* Slot 0 */
+ rlocn_precommitted = rlocn + 1; /* Slot 1 */
- if (precommit)
- rlocn++; /* Slot 1 */
+ /* Should we use precommitted metadata? */
+ if (*precommitted && rlocn_precommitted->size &&
+ (rlocn_precommitted->offset != rlocn->offset)) {
+ rlocn = rlocn_precommitted;
+ } else
+ *precommitted = 0;
/* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
/* FIXME Ignore if checksum incorrect!!! */
struct device_area *dev_area, const char *vgname)
{
int r = 0;
+ int noprecommit = 0;
struct mda_header *mdah;
if (!dev_open(dev_area->dev)) {
return 0;
}
- if (_find_vg_rlocn(dev_area, mdah, vgname, 0))
+ if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit))
r = 1;
if (!dev_close(dev_area->dev))
static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
const char *vgname,
struct device_area *area,
- int precommit)
+ int precommitted)
{
struct volume_group *vg = NULL;
struct raw_locn *rlocn;
goto out;
}
- if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, precommit))) {
+ if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
goto out;
}
goto out;
}
log_debug("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
- PRIu64, vg->name, precommit ? "pre-commit " : "",
+ PRIu64, vg->name, precommitted ? "pre-commit " : "",
vg->seqno, dev_name(area->dev),
area->start + rlocn->offset, rlocn->size);
+ if (precommitted)
+ vg->status |= PRECOMMITTED;
+
out:
if (!dev_close(area->dev))
stack;
int r = 0;
uint32_t new_wrap = 0, old_wrap = 0;
int found = 0;
+ int noprecommit = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate_items(pvl, &vg->pvs) {
goto out;
}
- rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0);
+ rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit);
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
if (!fidtc->raw_metadata_buf &&
struct pv_list *pvl;
int r = 0;
int found = 0;
+ int noprecommit = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate_items(pvl, &vg->pvs) {
goto out;
}
- if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0))) {
+ if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
mdah->raw_locns[0].offset = 0;
+ mdah->raw_locns[0].size = 0;
+ mdah->raw_locns[0].checksum = 0;
mdah->raw_locns[1].offset = 0;
+ mdah->raw_locns[1].size = 0;
+ mdah->raw_locns[1].checksum = 0;
mdah->raw_locns[2].offset = 0;
+ mdah->raw_locns[2].size = 0;
+ mdah->raw_locns[2].checksum = 0;
rlocn = &mdah->raw_locns[0];
}
if (precommit)
rlocn++;
+ else {
+ /* If not precommitting, wipe the precommitted rlocn */
+ mdah->raw_locns[1].offset = 0;
+ mdah->raw_locns[1].size = 0;
+ mdah->raw_locns[1].checksum = 0;
+ }
+
+ /* Is there new metadata to commit? */
+ if (mdac->rlocn.size) {
+ rlocn->offset = mdac->rlocn.offset;
+ rlocn->size = mdac->rlocn.size;
+ rlocn->checksum = mdac->rlocn.checksum;
+ log_debug("%sCommitting %s metadata (%u) to %s header at %"
+ PRIu64, precommit ? "Pre-" : "", vg->name, vg->seqno,
+ dev_name(mdac->area.dev), mdac->area.start);
+ } else
+ log_debug("Wiping pre-committed %s metadata from %s "
+ "header at %" PRIu64, vg->name,
+ dev_name(mdac->area.dev), mdac->area.start);
- rlocn->offset = mdac->rlocn.offset;
- rlocn->size = mdac->rlocn.size;
- rlocn->checksum = mdac->rlocn.checksum;
-
- log_debug("%sCommitting %s metadata (%u) to %s header at %" PRIu64,
- precommit ? "Pre-" : "", vg->name, vg->seqno,
- dev_name(mdac->area.dev), mdac->area.start);
if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
mdah)) {
log_error("Failed to write metadata area header");
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;
if (!found)
return 1;
- 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;
+ /* Wipe pre-committed metadata */
+ mdac->rlocn.size = 0;
+ return _vg_commit_raw_rlocn(fid, vg, mda, 0);
}
static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_header *mdah;
struct raw_locn *rlocn;
int r = 0;
+ int noprecommit = 0;
if (!dev_open(mdac->area.dev)) {
stack;
goto out;
}
- if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0))) {
+ if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
rlocn = &mdah->raw_locns[0];
mdah->raw_locns[1].offset = 0;
}
struct metadata_area *mda)
{
struct text_context *tc = (struct text_context *) mda->metadata_locn;
+ struct volume_group *vg;
+
+ if ((vg = _vg_read_file_name(fid, vgname, tc->path_edit)))
+ vg->status |= PRECOMMITTED;
+ else
+ vg = _vg_read_file_name(fid, vgname, tc->path_live);
- return _vg_read_file_name(fid, vgname, tc->path_edit);
+ return vg;
}
static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
* If consistent is 0, caller must check whether consistent == 1 on return
* and take appropriate action if it isn't (e.g. abort; get write lock
* and call vg_read again).
+ *
+ * If precommitted is set, use precommitted metadata if present.
*/
static struct volume_group *_vg_read(struct cmd_context *cmd,
const char *vgname,
struct volume_group *vg, *correct_vg = NULL;
struct metadata_area *mda;
int inconsistent = 0;
+ int use_precommitted = precommitted;
if (!*vgname) {
- if (precommitted) {
+ if (use_precommitted) {
log_error("Internal error: vg_read requires vgname "
"with pre-commit.");
return NULL;
}
}
- if (precommitted && !(fmt->features & FMT_PRECOMMIT)) {
- log_error("Internal error: %s doesn't support "
- "pre-commit", fmt->name);
- return NULL;
- }
+ if (use_precommitted && !(fmt->features & FMT_PRECOMMIT))
+ use_precommitted = 0;
/* create format instance with appropriate metadata area */
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
/* Ensure contents of all metadata areas match - else do recovery */
list_iterate_items(mda, &fid->metadata_areas) {
- if ((precommitted &&
+ if ((use_precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
- (!precommitted &&
+ (!use_precommitted &&
!(vg = mda->ops->vg_read(fid, vgname, mda)))) {
inconsistent = 1;
continue;
return NULL;
}
- if (precommitted && !(fmt->features & FMT_PRECOMMIT)) {
- log_error("Internal error: %s doesn't support "
- "pre-commit", fmt->name);
- return NULL;
- }
+ if (precommitted && !(fmt->features & FMT_PRECOMMIT))
+ use_precommitted = 0;
/* create format instance with appropriate metadata area */
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
/* Ensure contents of all metadata areas match - else recover */
list_iterate_items(mda, &fid->metadata_areas) {
- if ((precommitted &&
+ if ((use_precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname,
mda))) ||
- (!precommitted &&
+ (!use_precommitted &&
!(vg = mda->ops->vg_read(fid, vgname, mda)))) {
inconsistent = 1;
continue;
lvmcache_update_vg(correct_vg);
if (inconsistent) {
- if (precommitted) {
+ /* FIXME Test should be if we're *using* precommitted metadata not if we were searching for it */
+ if (use_precommitted) {
log_error("Inconsistent pre-commit metadata copies "
"for volume group %s", vgname);
return NULL;
return vg;
}
-struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
- const char *vgname,
- int *consistent)
-{
- return _vg_read(cmd, vgname, consistent, 1);
-}
-
/* This is only called by lv_from_lvid, which is only called from
* activate.c so we know the appropriate VG lock is already held and
* the vg_read is therefore safe.
*/
-struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
+static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
+ const char *vgid,
+ int precommitted)
{
const char *vgname;
struct list *vgnames;
/* Is corresponding vgname already cached? */
if ((vginfo = vginfo_from_vgid(vgid)) &&
vginfo->vgname && *vginfo->vgname) {
- if ((vg = vg_read(cmd, vginfo->vgname, &consistent)) &&
+ if ((vg = _vg_read(cmd, vginfo->vgname,
+ &consistent, precommitted)) &&
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
if (!consistent) {
log_error("Volume group %s metadata is "
if (!vgname || !*vgname)
continue; // FIXME Unnecessary?
consistent = 0;
- if ((vg = vg_read(cmd, vgname, &consistent)) &&
+ if ((vg = _vg_read(cmd, vgname, &consistent,
+ precommitted)) &&
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
if (!consistent) {
log_error("Volume group %s metadata is "
}
/* Only called by activate.c */
-struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s)
+struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s,
+ int precommitted)
{
struct lv_list *lvl;
struct volume_group *vg;
lvid = (const union lvid *) lvid_s;
log_very_verbose("Finding volume group for uuid %s", lvid_s);
- if (!(vg = vg_read_by_vgid(cmd, lvid->id[0].uuid))) {
+ if (!(vg = _vg_read_by_vgid(cmd, lvid->id[0].uuid, precommitted))) {
log_error("Volume group for uuid not found: %s", lvid_s);
return NULL;
}
int vg_revert(struct volume_group *vg);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
int *consistent);
-// struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
-// const char *vg_name,
-// int *consistent);
-// struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
struct list *mdas, uint64_t *label_sector,
int warnings);
/* Find LV with given lvid (used during activation) */
struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
- const char *lvid_s);
+ const char *lvid_s,
+ int precommitted);
/* FIXME Merge these functions with ones above */
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);