mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-06 11:33:14 +03:00
Allow non-orphan PVs with two metadata areas to be resized.
We allow writing non-orphan PVs only for resize now. The "orphan PV" assert in pv_write fn uses the "allow_non_orphan" parameter to control this assert. However, we should find a more elaborate solution so we can remove this restriction altogether (pv_write together with vg_write is not atomic, we need to find a safe mechanism so there's an easy revert possible in case of an error).
This commit is contained in:
@@ -5,8 +5,8 @@ Version 2.02.85 -
|
|||||||
Improve normal allocation algorithm to include clinging to existing areas.
|
Improve normal allocation algorithm to include clinging to existing areas.
|
||||||
Add allocation/maximise_cling & mirror_logs_require_separate_pvs to lvm.conf.
|
Add allocation/maximise_cling & mirror_logs_require_separate_pvs to lvm.conf.
|
||||||
Fix metadata balance code to work with recent changes in metadata handling.
|
Fix metadata balance code to work with recent changes in metadata handling.
|
||||||
Add old_uuid field to physical_volume and fix pvchange -u for recent changes.
|
Add old_id field to physical_volume and fix pvchange -u for recent changes.
|
||||||
Allow pvresize on a PV with two metadata areas (for PVs not in a VG).
|
Allow pvresize on a PV with two metadata areas.
|
||||||
Change pvcreate to use new metadata handling interface.
|
Change pvcreate to use new metadata handling interface.
|
||||||
Restructure existing pv_setup and pv_write fn, add pv_initialise fn.
|
Restructure existing pv_setup and pv_write fn, add pv_initialise fn.
|
||||||
Add internal interface to support adding and removing metadata areas.
|
Add internal interface to support adding and removing metadata areas.
|
||||||
|
@@ -1273,7 +1273,8 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
|||||||
|
|
||||||
/* Add a new cache entry with PV info or update existing one. */
|
/* Add a new cache entry with PV info or update existing one. */
|
||||||
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
|
if (!(info = lvmcache_add(fmt->labeller, (const char *) &pv->id,
|
||||||
pv->dev, FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
|
pv->dev, pv->vg ? pv->vg->name : FMT_TEXT_ORPHAN_VG_NAME,
|
||||||
|
NULL, 0)))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
label = info->label;
|
label = info->label;
|
||||||
@@ -2161,17 +2162,6 @@ static int _text_pv_resize(const struct format_type *fmt,
|
|||||||
/* If there's an mda at the end, move it to a new position. */
|
/* If there's an mda at the end, move it to a new position. */
|
||||||
if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
|
if ((mda = fid_get_mda_indexed(fid, pvid, ID_LEN, 1)) &&
|
||||||
(mdac = mda->metadata_locn)) {
|
(mdac = mda->metadata_locn)) {
|
||||||
/*
|
|
||||||
* FIXME: Remove this restriction - we need to
|
|
||||||
* allow writing PV labels on non-orphan VGs
|
|
||||||
* for this to work correctly.
|
|
||||||
*/
|
|
||||||
if (vg) {
|
|
||||||
log_error("Resizing a PV with two metadata areas "
|
|
||||||
"that is part of a VG is not supported.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Maybe MDA0 size would be better? */
|
/* FIXME: Maybe MDA0 size would be better? */
|
||||||
mda_size = mdac->area.size >> SECTOR_SHIFT;
|
mda_size = mdac->area.size >> SECTOR_SHIFT;
|
||||||
mda_ignored = mda_is_ignored(mda);
|
mda_ignored = mda_is_ignored(mda);
|
||||||
|
@@ -384,7 +384,7 @@ struct dm_list *get_vgnames(struct cmd_context *cmd, int include_internal);
|
|||||||
struct dm_list *get_vgids(struct cmd_context *cmd, int include_internal);
|
struct dm_list *get_vgids(struct cmd_context *cmd, int include_internal);
|
||||||
int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings);
|
int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings);
|
||||||
|
|
||||||
int pv_write(struct cmd_context *cmd, struct physical_volume *pv);
|
int pv_write(struct cmd_context *cmd, struct physical_volume *pv, int allow_non_orphan);
|
||||||
int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
|
int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
|
||||||
const char *pv_name);
|
const char *pv_name);
|
||||||
int move_pvs_used_by_lv(struct volume_group *vg_from,
|
int move_pvs_used_by_lv(struct volume_group *vg_from,
|
||||||
|
@@ -586,7 +586,7 @@ int vg_remove(struct volume_group *vg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Write to same sector label was read from */
|
/* FIXME Write to same sector label was read from */
|
||||||
if (!pv_write(vg->cmd, pv)) {
|
if (!pv_write(vg->cmd, pv, 0)) {
|
||||||
log_error("Failed to remove physical volume \"%s\""
|
log_error("Failed to remove physical volume \"%s\""
|
||||||
" from volume group \"%s\"",
|
" from volume group \"%s\"",
|
||||||
pv_dev_name(pv), vg->name);
|
pv_dev_name(pv), vg->name);
|
||||||
@@ -1511,7 +1511,7 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
|
|||||||
log_very_verbose("Writing physical volume data to disk \"%s\"",
|
log_very_verbose("Writing physical volume data to disk \"%s\"",
|
||||||
pv_name);
|
pv_name);
|
||||||
|
|
||||||
if (!(pv_write(cmd, pv))) {
|
if (!(pv_write(cmd, pv, 0))) {
|
||||||
log_error("Failed to write physical volume \"%s\"", pv_name);
|
log_error("Failed to write physical volume \"%s\"", pv_name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -3536,7 +3536,7 @@ int scan_vgs_for_pvs(struct cmd_context *cmd, int warnings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pv_write(struct cmd_context *cmd __attribute__((unused)),
|
int pv_write(struct cmd_context *cmd __attribute__((unused)),
|
||||||
struct physical_volume *pv)
|
struct physical_volume *pv, int allow_non_orphan)
|
||||||
{
|
{
|
||||||
if (!pv->fmt->ops->pv_write) {
|
if (!pv->fmt->ops->pv_write) {
|
||||||
log_error("Format does not support writing physical volumes");
|
log_error("Format does not support writing physical volumes");
|
||||||
@@ -3549,7 +3549,8 @@ int pv_write(struct cmd_context *cmd __attribute__((unused)),
|
|||||||
* to provide some revert mechanism since PV label together
|
* to provide some revert mechanism since PV label together
|
||||||
* with VG metadata write is not atomic.
|
* with VG metadata write is not atomic.
|
||||||
*/
|
*/
|
||||||
if (!is_orphan_vg(pv->vg_name) || pv->pe_alloc_count) {
|
if (!allow_non_orphan &&
|
||||||
|
(!is_orphan_vg(pv->vg_name) || pv->pe_alloc_count)) {
|
||||||
log_error("Assertion failed: can't _pv_write non-orphan PV "
|
log_error("Assertion failed: can't _pv_write non-orphan PV "
|
||||||
"(in VG %s)", pv->vg_name);
|
"(in VG %s)", pv->vg_name);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3574,7 +3575,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pv_write(cmd, pv)) {
|
if (!pv_write(cmd, pv, 0)) {
|
||||||
log_error("Failed to clear metadata from physical "
|
log_error("Failed to clear metadata from physical "
|
||||||
"volume \"%s\" after removal from \"%s\"",
|
"volume \"%s\" after removal from \"%s\"",
|
||||||
pv_dev_name(pv), old_vg_name);
|
pv_dev_name(pv), old_vg_name);
|
||||||
|
@@ -192,6 +192,7 @@ unsigned mda_is_ignored(struct metadata_area *mda);
|
|||||||
void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
|
void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
|
||||||
unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
|
unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
|
||||||
void vg_set_fid(struct volume_group *vg, struct format_instance *fid);
|
void vg_set_fid(struct volume_group *vg, struct format_instance *fid);
|
||||||
|
/* FIXME: Add generic interface for mda counts based on given key. */
|
||||||
int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
|
int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
|
||||||
const char *key, size_t key_len, const unsigned sub_key);
|
const char *key, size_t key_len, const unsigned sub_key);
|
||||||
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
|
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
|
||||||
|
@@ -140,7 +140,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
|
|
||||||
pv->vg_name = pv->fmt->orphan_vg_name;
|
pv->vg_name = pv->fmt->orphan_vg_name;
|
||||||
pv->pe_alloc_count = 0;
|
pv->pe_alloc_count = 0;
|
||||||
if (!(pv_write(cmd, pv))) {
|
if (!(pv_write(cmd, pv, 0))) {
|
||||||
log_error("pv_write with new uuid failed "
|
log_error("pv_write with new uuid failed "
|
||||||
"for %s.", pv_name);
|
"for %s.", pv_name);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -162,7 +162,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
backup(vg);
|
backup(vg);
|
||||||
} else if (!(pv_write(cmd, pv))) {
|
} else if (!(pv_write(cmd, pv, 0))) {
|
||||||
log_error("Failed to store physical volume \"%s\"",
|
log_error("Failed to store physical volume \"%s\"",
|
||||||
pv_name);
|
pv_name);
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
struct pvresize_params {
|
struct pvresize_params {
|
||||||
uint64_t new_size;
|
uint64_t new_size;
|
||||||
@@ -96,6 +97,16 @@ static int _pv_resize_single(struct cmd_context *cmd,
|
|||||||
goto_out;
|
goto_out;
|
||||||
|
|
||||||
log_verbose("Updating physical volume \"%s\"", pv_name);
|
log_verbose("Updating physical volume \"%s\"", pv_name);
|
||||||
|
|
||||||
|
/* Write PV label only if this an orphan PV or it has 2nd mda. */
|
||||||
|
if ((is_orphan_vg(vg_name) ||
|
||||||
|
fid_get_mda_indexed(vg->fid, (const char *) &pv->id, ID_LEN, 1)) &&
|
||||||
|
!pv_write(cmd, pv, 1)) {
|
||||||
|
log_error("Failed to store physical volume \"%s\"",
|
||||||
|
pv_name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_orphan_vg(vg_name)) {
|
if (!is_orphan_vg(vg_name)) {
|
||||||
if (!vg_write(vg) || !vg_commit(vg)) {
|
if (!vg_write(vg) || !vg_commit(vg)) {
|
||||||
log_error("Failed to store physical volume \"%s\" in "
|
log_error("Failed to store physical volume \"%s\" in "
|
||||||
@@ -103,10 +114,6 @@ static int _pv_resize_single(struct cmd_context *cmd,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
backup(vg);
|
backup(vg);
|
||||||
} else if (!(pv_write(cmd, pv))) {
|
|
||||||
log_error("Failed to store physical volume \"%s\"",
|
|
||||||
pv_name);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_print("Physical volume \"%s\" changed", pv_name);
|
log_print("Physical volume \"%s\" changed", pv_name);
|
||||||
|
@@ -151,7 +151,7 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
|
|||||||
|
|
||||||
log_very_verbose("Writing physical volume data to disk \"%s\"",
|
log_very_verbose("Writing physical volume data to disk \"%s\"",
|
||||||
pv_dev_name(pv));
|
pv_dev_name(pv));
|
||||||
if (!(pv_write(cmd, pv))) {
|
if (!(pv_write(cmd, pv, 0))) {
|
||||||
log_error("Failed to write physical volume \"%s\"",
|
log_error("Failed to write physical volume \"%s\"",
|
||||||
pv_dev_name(pv));
|
pv_dev_name(pv));
|
||||||
log_error("Use pvcreate and vgcfgrestore to repair "
|
log_error("Use pvcreate and vgcfgrestore to repair "
|
||||||
|
@@ -438,7 +438,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pv_write(cmd, pv)) {
|
if (!pv_write(cmd, pv, 0)) {
|
||||||
log_error("Failed to clear metadata from physical "
|
log_error("Failed to clear metadata from physical "
|
||||||
"volume \"%s\" "
|
"volume \"%s\" "
|
||||||
"after removal from \"%s\"", name, vg->name);
|
"after removal from \"%s\"", name, vg->name);
|
||||||
|
Reference in New Issue
Block a user