master - cleanup: use struct pvcreate_restorable_params throughout
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6d8de3638c3e71...
Commit: 6d8de3638c3e715a1c0273e3fed9daf71a871685
Parent: 6692b177777501532ba0d422dcb2a22016405519
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Feb 18 12:47:31 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 11:25:11 2013 +0100
cleanup: use struct pvcreate_restorable_params throughout
---
lib/format1/format1.c | 21 +++++++++++++--------
lib/format_pool/format_pool.c | 4 +---
lib/format_text/format-text.c | 18 ++++++++----------
lib/metadata/metadata-exported.h | 9 ++++-----
lib/metadata/metadata.c | 31 +++++++++++++------------------
lib/metadata/metadata.h | 5 +----
tools/toollib.c | 4 ++--
tools/vgconvert.c | 15 +++++++++------
8 files changed, 51 insertions(+), 56 deletions(-)
diff --git a/lib/format1/format1.c b/lib/format1/format1.c
index bf5333e..335a7e2 100644
--- a/lib/format1/format1.c
+++ b/lib/format1/format1.c
@@ -339,11 +339,9 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
static int _format1_pv_initialise(const struct format_type * fmt,
int64_t label_sector __attribute__((unused)),
- uint64_t pe_start,
- uint32_t extent_count,
- uint32_t extent_size,
unsigned long data_alignment __attribute__((unused)),
unsigned long data_alignment_offset __attribute__((unused)),
+ struct pvcreate_restorable_params *rp,
struct physical_volume * pv)
{
if (pv->size > MAX_PV_SIZE)
@@ -355,18 +353,18 @@ static int _format1_pv_initialise(const struct format_type * fmt,
}
/* Nothing more to do if extent size isn't provided */
- if (!extent_size)
+ if (!rp->extent_size)
return 1;
/*
* This works out pe_start and pe_count.
*/
- if (!calculate_extent_count(pv, extent_size, extent_count, pe_start))
+ if (!calculate_extent_count(pv, rp->extent_size, rp->extent_count, rp->pe_start))
return_0;
/* Retain existing extent locations exactly */
- if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
- (extent_count && (extent_count != pv->pe_count))) {
+ if (((rp->pe_start || rp->extent_count) && (rp->pe_start != pv->pe_start)) ||
+ (rp->extent_count && (rp->extent_count != pv->pe_count))) {
log_error("Metadata would overwrite physical extents");
return 0;
}
@@ -378,7 +376,14 @@ static int _format1_pv_setup(const struct format_type *fmt,
struct physical_volume *pv,
struct volume_group *vg)
{
- return _format1_pv_initialise(fmt, -1, 0, 0, vg->extent_size, 0, 0, pv);
+ struct pvcreate_restorable_params rp = {.restorefile = NULL,
+ .id = {{0}},
+ .idp = NULL,
+ .pe_start = 0,
+ .extent_count = 0,
+ .extent_size = vg->extent_size};
+
+ return _format1_pv_initialise(fmt, -1, 0, 0, &rp, pv);
}
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c
index 04bc4cf..c051968 100644
--- a/lib/format_pool/format_pool.c
+++ b/lib/format_pool/format_pool.c
@@ -165,11 +165,9 @@ bad:
static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unused)),
int64_t label_sector __attribute__((unused)),
- uint64_t pe_start __attribute__((unused)),
- uint32_t extent_count __attribute__((unused)),
- uint32_t extent_size __attribute__((unused)),
unsigned long data_alignment __attribute__((unused)),
unsigned long data_alignment_offset __attribute__((unused)),
+ struct pvcreate_restorable_params *rp __attribute__((unused)),
struct physical_volume *pv __attribute__((unused)))
{
return 1;
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index cf15313..a769daf 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1466,19 +1466,17 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
static int _text_pv_initialise(const struct format_type *fmt,
const int64_t label_sector,
- uint64_t pe_start,
- uint32_t extent_count,
- uint32_t extent_size,
unsigned long data_alignment,
unsigned long data_alignment_offset,
+ struct pvcreate_restorable_params *rp,
struct physical_volume *pv)
{
/*
* Try to keep the value of PE start set to a firm value if requested.
* This is usefull when restoring existing PE start value (backups etc.).
*/
- if (pe_start != PV_PE_START_CALC)
- pv->pe_start = pe_start;
+ if (rp->pe_start != PV_PE_START_CALC)
+ pv->pe_start = rp->pe_start;
if (!data_alignment)
data_alignment = find_config_tree_int(pv->fmt->cmd,
@@ -1514,14 +1512,14 @@ static int _text_pv_initialise(const struct format_type *fmt,
return 0;
}
- if (pe_start == PV_PE_START_CALC)
+ if (rp->pe_start == PV_PE_START_CALC)
pv->pe_start = pv->pe_align + pv->pe_align_offset;
- if (extent_size)
- pv->pe_size = extent_size;
+ if (rp->extent_size)
+ pv->pe_size = rp->extent_size;
- if (extent_count)
- pv->pe_count = extent_count;
+ if (rp->extent_count)
+ pv->pe_count = rp->extent_count;
if ((pv->pe_start + pv->pe_count * pv->pe_size - 1) > (pv->size << SECTOR_SHIFT)) {
log_error("Physical extents end beyond end of device %s.",
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 1f77ce9..5c8a6df 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -391,6 +391,8 @@ struct lv_list {
struct logical_volume *lv;
};
+#define PV_PE_START_CALC ((uint64_t) -1) /* Calculate pe_start value */
+
struct pvcreate_restorable_params {
const char *restorefile; /* 0 if no --restorefile option */
struct id id; /* FIXME: redundant */
@@ -477,17 +479,14 @@ uint32_t vg_read_error(struct volume_group *vg_handle);
* areas can avoid overlap */
struct physical_volume *pv_create(const struct cmd_context *cmd,
struct device *dev,
- struct id *id,
uint64_t size,
unsigned long data_alignment,
unsigned long data_alignment_offset,
- uint64_t pe_start,
- uint32_t existing_extent_count,
- uint32_t existing_extent_size,
uint64_t label_sector,
unsigned pvmetadatacopies,
uint64_t pvmetadatasize,
- unsigned metadataignore);
+ unsigned metadataignore,
+ struct pvcreate_restorable_params *rp);
int pv_resize(struct physical_volume *pv, struct volume_group *vg,
uint64_t size);
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 025329f..2c071b0 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1430,7 +1430,7 @@ void pvcreate_params_set_defaults(struct pvcreate_params *pp)
pp->metadataignore = DEFAULT_PVMETADATAIGNORE;
pp->rp.restorefile = 0;
pp->rp.idp = 0;
- pp->rp.pe_start = 0;
+ pp->rp.pe_start = PV_PE_START_CALC;
pp->rp.extent_count = 0;
pp->rp.extent_size = 0;
}
@@ -1530,12 +1530,10 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
dm_list_init(&mdas);
- if (!(pv = pv_create(cmd, dev, pp->rp.idp, pp->size,
- pp->data_alignment, pp->data_alignment_offset,
- pp->rp.pe_start ? pp->rp.pe_start : PV_PE_START_CALC,
- pp->rp.extent_count, pp->rp.extent_size,
- pp->labelsector, pp->pvmetadatacopies,
- pp->pvmetadatasize, pp->metadataignore))) {
+ if (!(pv = pv_create(cmd, dev, pp->size, pp->data_alignment,
+ pp->data_alignment_offset, pp->labelsector,
+ pp->pvmetadatacopies, pp->pvmetadatasize,
+ pp->metadataignore, &pp->rp))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
goto bad;
}
@@ -1602,16 +1600,14 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem, struct device *dev
*/
struct physical_volume *pv_create(const struct cmd_context *cmd,
struct device *dev,
- struct id *id, uint64_t size,
+ uint64_t size,
unsigned long data_alignment,
unsigned long data_alignment_offset,
- uint64_t pe_start,
- uint32_t existing_extent_count,
- uint32_t existing_extent_size,
uint64_t label_sector,
unsigned pvmetadatacopies,
uint64_t pvmetadatasize,
- unsigned metadataignore)
+ unsigned metadataignore,
+ struct pvcreate_restorable_params *rp)
{
const struct format_type *fmt = cmd->fmt;
struct dm_pool *mem = fmt->orphan_vg->vgmem;
@@ -1622,8 +1618,8 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
if (!pv)
return_NULL;
- if (id)
- memcpy(&pv->id, id, sizeof(*id));
+ if (rp->idp)
+ memcpy(&pv->id, rp->idp, sizeof(*rp->idp));
else if (!id_create(&pv->id)) {
log_error("Failed to create random uuid for %s.",
dev_name(dev));
@@ -1669,9 +1665,8 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
pv->fmt = fmt;
pv->vg_name = fmt->orphan_vg_name;
- if (!fmt->ops->pv_initialise(fmt, label_sector, pe_start,
- existing_extent_count, existing_extent_size,
- data_alignment, data_alignment_offset, pv)) {
+ if (!fmt->ops->pv_initialise(fmt, label_sector, data_alignment,
+ data_alignment_offset, rp, pv)) {
log_error("Format-specific initialisation of physical "
"volume %s failed.", pv_dev_name(pv));
goto bad;
@@ -1680,7 +1675,7 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
for (mda_index = 0; mda_index < pvmetadatacopies; mda_index++) {
if (pv->fmt->ops->pv_add_metadata_area &&
!pv->fmt->ops->pv_add_metadata_area(pv->fmt, pv,
- pe_start != PV_PE_START_CALC,
+ rp->pe_start != PV_PE_START_CALC,
mda_index, pvmetadatasize,
metadataignore)) {
log_error("Failed to add metadata area for "
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 830c0e1..f7b3409 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -35,7 +35,6 @@
//#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */
#define MIRROR_LOG_OFFSET 2 /* sectors */
#define VG_MEMPOOL_CHUNK 10240 /* in bytes, hint only */
-#define PV_PE_START_CALC ((uint64_t) -1) /* Calculate pe_start value */
/*
* Ceiling(n / sz)
@@ -251,11 +250,9 @@ struct format_handler {
*/
int (*pv_initialise) (const struct format_type * fmt,
int64_t label_sector,
- uint64_t pe_start,
- uint32_t extent_count,
- uint32_t extent_size,
unsigned long data_alignment,
unsigned long data_alignment_offset,
+ struct pvcreate_restorable_params *rp,
struct physical_volume * pv);
/*
diff --git a/tools/toollib.c b/tools/toollib.c
index c3c4dbe..3717bde 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1451,7 +1451,7 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
- if (pp->data_alignment && pp->rp.pe_start) {
+ if (pp->data_alignment && pp->rp.pe_start != PV_PE_START_CALC) {
if (pp->rp.pe_start % pp->data_alignment)
log_warn("WARNING: Ignoring data alignment %" PRIu64
" incompatible with --restorefile value (%"
@@ -1470,7 +1470,7 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
- if (pp->data_alignment_offset && pp->rp.pe_start) {
+ if (pp->data_alignment_offset && pp->rp.pe_start != PV_PE_START_CALC) {
log_warn("WARNING: Ignoring data alignment offset %" PRIu64
" incompatible with --restorefile value (%"
PRIu64").", pp->data_alignment_offset, pp->rp.pe_start);
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 2ba4095..85f68f2 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -20,11 +20,11 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
void *handle __attribute__((unused)))
{
struct physical_volume *pv, *existing_pv;
+ struct pvcreate_restorable_params rp;
struct logical_volume *lv;
struct lv_list *lvl;
int pvmetadatacopies = 0;
uint64_t pvmetadatasize = 0;
- uint64_t pe_start = 0;
struct pv_list *pvl;
int change_made = 0;
struct lvinfo info;
@@ -116,16 +116,19 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
dm_list_iterate_items(pvl, &vg->pvs) {
existing_pv = pvl->pv;
- pe_start = pv_pe_start(existing_pv);
+ rp.id = existing_pv->id;
+ rp.idp = &rp.id;
+ rp.pe_start = pv_pe_start(existing_pv);
+ rp.extent_count = pv_pe_count(existing_pv);
+ rp.extent_size = pv_pe_size(existing_pv);
+
/* pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv) + pe_start - 1; */
if (!(pv = pv_create(cmd, pv_dev(existing_pv),
- &existing_pv->id, 0, 0, 0,
- pe_start, pv_pe_count(existing_pv),
- pv_pe_size(existing_pv),
+ 0, 0, 0,
arg_int64_value(cmd, labelsector_ARG,
DEFAULT_LABELSECTOR),
- pvmetadatacopies, pvmetadatasize, 0))) {
+ pvmetadatacopies, pvmetadatasize, 0, &rp))) {
log_error("Failed to setup physical volume \"%s\"",
pv_dev_name(existing_pv));
if (change_made)
11 years, 2 months
master - cleanup: add struct pvcreate_restorable_params and move relevant items from pvcreate_params
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6692b177777501...
Commit: 6692b177777501532ba0d422dcb2a22016405519
Parent: 71f49345004d385acc71a8e534c4313069cc59b6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Feb 18 10:51:32 2013 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Feb 26 11:24:38 2013 +0100
cleanup: add struct pvcreate_restorable_params and move relevant items from pvcreate_params
Extract restorable PV creation parameters from struct pvcreate_params into
a separate struct pvcreate_restorable_params for clarity and also for better
maintainability when adding any new items later.
---
lib/metadata/metadata-exported.h | 16 ++++++++++------
lib/metadata/metadata.c | 22 +++++++++++-----------
tools/pvcreate.c | 20 ++++++++++----------
tools/toollib.c | 10 +++++-----
4 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b37d64c..1f77ce9 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -391,6 +391,15 @@ struct lv_list {
struct logical_volume *lv;
};
+struct pvcreate_restorable_params {
+ const char *restorefile; /* 0 if no --restorefile option */
+ struct id id; /* FIXME: redundant */
+ struct id *idp; /* 0 if no --uuid option */
+ uint64_t pe_start;
+ uint32_t extent_count;
+ uint32_t extent_size;
+};
+
struct pvcreate_params {
int zero;
uint64_t size;
@@ -399,15 +408,10 @@ struct pvcreate_params {
int pvmetadatacopies;
uint64_t pvmetadatasize;
int64_t labelsector;
- struct id id; /* FIXME: redundant */
- struct id *idp; /* 0 if no --uuid option */
- uint64_t pe_start;
- uint32_t extent_count;
- uint32_t extent_size;
- const char *restorefile; /* 0 if no --restorefile option */
force_t force;
unsigned yes;
unsigned metadataignore;
+ struct pvcreate_restorable_params rp;
};
struct physical_volume *pvcreate_single(struct cmd_context *cmd,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index d03b49c..025329f 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1425,14 +1425,14 @@ void pvcreate_params_set_defaults(struct pvcreate_params *pp)
pp->pvmetadatacopies = DEFAULT_PVMETADATACOPIES;
pp->pvmetadatasize = DEFAULT_PVMETADATASIZE;
pp->labelsector = DEFAULT_LABELSECTOR;
- pp->idp = 0;
- pp->pe_start = 0;
- pp->extent_count = 0;
- pp->extent_size = 0;
- pp->restorefile = 0;
pp->force = PROMPT;
pp->yes = 0;
pp->metadataignore = DEFAULT_PVMETADATAIGNORE;
+ pp->rp.restorefile = 0;
+ pp->rp.idp = 0;
+ pp->rp.pe_start = 0;
+ pp->rp.extent_count = 0;
+ pp->rp.extent_size = 0;
}
@@ -1504,10 +1504,10 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
if (!pp)
pp = &default_pp;
- if (pp->idp) {
- if ((dev = lvmcache_device_from_pvid(cmd, pp->idp, NULL, NULL)) &&
+ if (pp->rp.idp) {
+ if ((dev = lvmcache_device_from_pvid(cmd, pp->rp.idp, NULL, NULL)) &&
(dev != dev_cache_get(pv_name, cmd->filter))) {
- if (!id_write_format((const struct id*)&pp->idp->uuid,
+ if (!id_write_format((const struct id*)&pp->rp.idp->uuid,
buffer, sizeof(buffer)))
goto_bad;
log_error("uuid %s already in use on \"%s\"", buffer,
@@ -1530,10 +1530,10 @@ struct physical_volume * pvcreate_single(struct cmd_context *cmd,
dm_list_init(&mdas);
- if (!(pv = pv_create(cmd, dev, pp->idp, pp->size,
+ if (!(pv = pv_create(cmd, dev, pp->rp.idp, pp->size,
pp->data_alignment, pp->data_alignment_offset,
- pp->pe_start ? pp->pe_start : PV_PE_START_CALC,
- pp->extent_count, pp->extent_size,
+ pp->rp.pe_start ? pp->rp.pe_start : PV_PE_START_CALC,
+ pp->rp.extent_count, pp->rp.extent_size,
pp->labelsector, pp->pvmetadatacopies,
pp->pvmetadatasize, pp->metadataignore))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
diff --git a/tools/pvcreate.c b/tools/pvcreate.c
index c75f561..d7e7e52 100644
--- a/tools/pvcreate.c
+++ b/tools/pvcreate.c
@@ -53,29 +53,29 @@ static int pvcreate_restore_params_validate(struct cmd_context *cmd,
if (arg_count(cmd, uuidstr_ARG)) {
uuid = arg_str_value(cmd, uuidstr_ARG, "");
- if (!id_read_format(&pp->id, uuid))
+ if (!id_read_format(&pp->rp.id, uuid))
return 0;
- pp->idp = &pp->id;
+ pp->rp.idp = &pp->rp.id;
lvmcache_seed_infos_from_lvmetad(cmd); /* need to check for UUID dups */
}
if (arg_count(cmd, restorefile_ARG)) {
- pp->restorefile = arg_str_value(cmd, restorefile_ARG, "");
+ pp->rp.restorefile = arg_str_value(cmd, restorefile_ARG, "");
/* The uuid won't already exist */
- if (!(vg = backup_read_vg(cmd, NULL, pp->restorefile))) {
+ if (!(vg = backup_read_vg(cmd, NULL, pp->rp.restorefile))) {
log_error("Unable to read volume group from %s",
- pp->restorefile);
+ pp->rp.restorefile);
return 0;
}
- if (!(existing_pvl = find_pv_in_vg_by_uuid(vg, pp->idp))) {
+ if (!(existing_pvl = find_pv_in_vg_by_uuid(vg, pp->rp.idp))) {
release_vg(vg);
log_error("Can't find uuid %s in backup file %s",
- uuid, pp->restorefile);
+ uuid, pp->rp.restorefile);
return 0;
}
- pp->pe_start = pv_pe_start(existing_pvl->pv);
- pp->extent_size = pv_pe_size(existing_pvl->pv);
- pp->extent_count = pv_pe_count(existing_pvl->pv);
+ pp->rp.pe_start = pv_pe_start(existing_pvl->pv);
+ pp->rp.extent_size = pv_pe_size(existing_pvl->pv);
+ pp->rp.extent_count = pv_pe_count(existing_pvl->pv);
release_vg(vg);
}
diff --git a/tools/toollib.c b/tools/toollib.c
index 1abe837..c3c4dbe 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1451,11 +1451,11 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
- if (pp->data_alignment && pp->pe_start) {
- if (pp->pe_start % pp->data_alignment)
+ if (pp->data_alignment && pp->rp.pe_start) {
+ if (pp->rp.pe_start % pp->data_alignment)
log_warn("WARNING: Ignoring data alignment %" PRIu64
" incompatible with --restorefile value (%"
- PRIu64").", pp->data_alignment, pp->pe_start);
+ PRIu64").", pp->data_alignment, pp->rp.pe_start);
pp->data_alignment = 0;
}
@@ -1470,10 +1470,10 @@ int pvcreate_params_validate(struct cmd_context *cmd,
return 0;
}
- if (pp->data_alignment_offset && pp->pe_start) {
+ if (pp->data_alignment_offset && pp->rp.pe_start) {
log_warn("WARNING: Ignoring data alignment offset %" PRIu64
" incompatible with --restorefile value (%"
- PRIu64").", pp->data_alignment_offset, pp->pe_start);
+ PRIu64").", pp->data_alignment_offset, pp->rp.pe_start);
pp->data_alignment_offset = 0;
}
11 years, 2 months
master - activation: fix pvmove partial tree creation
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=71f49345004d38...
Commit: 71f49345004d385acc71a8e534c4313069cc59b6
Parent: b73de7315116da41a993d20567f9a1520610f545
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sat Feb 23 12:09:12 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 12:09:12 2013 +0100
activation: fix pvmove partial tree creation
Do not try to add LV again into the partial tree, if it's been
already added. Otherwise we may end in endless loop.
---
lib/activate/dev_manager.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index e326929..bffa8a5 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1605,7 +1605,8 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Add any LVs referencing a PVMOVE LV unless told not to. */
if (dm->track_pvmove_deps && lv->status & PVMOVE)
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
- if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
+ if (!_cached_info(dm->mem, dtree, sl->seg->lv, 0) &&
+ !_add_lv_to_dtree(dm, dtree, sl->seg->lv, origin_only))
return_0;
/* Adding LV head of replicator adds all other related devs */
11 years, 2 months
master - thin: lvconvert support for external origin
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b73de7315116da...
Commit: b73de7315116da41a993d20567f9a1520610f545
Parent: 2cba0ea9f96ed658d11df4428ec20502da1867c0
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Feb 5 11:26:27 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:38:20 2013 +0100
thin: lvconvert support for external origin
Add basic support for converting LV into an external origin volume.
Syntax:
lvconvert --thinpool vg/pool --originname renamed_origin -T origin
It will convert volume 'origin' into a thin volume, which will
use 'renamed_origin' as an external read-only origin.
All read/write into origin will go via 'pool'.
renamed_origin volume is read-only volume, that could be activated
only in read-only mode, and cannot be modified.
---
WHATS_NEW | 1 +
lib/activate/activate.c | 6 ++-
man/lvconvert.8.in | 32 +++++++++
tools/args.h | 3 +-
tools/commands.h | 7 ++-
tools/lvconvert.c | 174 +++++++++++++++++++++++++++++++++++++++++++++--
6 files changed, 212 insertions(+), 11 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 4e1f758..dc4fc8f 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Initial support for lvconvert of thin external origin.
Add _lv_remove_segs_using_this_lv() for removal of dependent lvs.
Improve activation code for better support of stacked devices.
Add _add_layer_target_to_dtree() for adding linear layer into dtree.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 6187828..f19dff7 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -1580,6 +1580,10 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
(lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
lockfs = 1;
+ /* Converting non-thin LV to thin external origin ? */
+ if (!lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
+ lockfs = 1; /* Sync before conversion */
+
if (laopts->origin_only && lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1;
diff --git a/man/lvconvert.8.in b/man/lvconvert.8.in
index 578047b..c5929c2 100644
--- a/man/lvconvert.8.in
+++ b/man/lvconvert.8.in
@@ -99,6 +99,10 @@ lvconvert \- convert a logical volume from linear to mirror or snapshot
.RB [ \-h | \-? | \-\-help ]
.RB [ \-v | \-\-verbose ]
.RB [ \-\-version ]
+.RB [ \-T | \-\-thin
+.IR ExternalOriginLogicalVolume { Name | Path }
+.RB [ \-\-originname
+.IR NewExternalOriginVolumeName ]]
.RI [ PhysicalVolume [ Path ][ :PE [ -PE ]]...]
.sp
@@ -230,6 +234,13 @@ merge finishes, the merged snapshot is removed. Multiple snapshots may
be specified on the commandline or a @tag may be used to specify
multiple snapshots be merged to their respective origin.
.TP
+.B \-\-originname \fINewExternalOriginVolumeName\fP
+The name for converted external origin volume.
+.br
+Without this option a default names of "lvol#" will be generated where
+# is the LVM internal number of the logical volume.
+Converted volume will be read-only.
+.TP
.BR \-\-poolmetadata " " \fIThinPoolMetadataLogicalVolume { \fIName | \fIPath }
Specifies thin pool metadata logical volume.
The size should be in between 2MiB and 16GiB.
@@ -288,6 +299,13 @@ StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
For metadata in LVM2 format, the stripe size may be a larger
power of 2 but must not exceed the physical extent size.
.TP
+.IR \fB\-T ", " \fB\-\-thin " " ExternalOriginLogicalVolume { Name | Path }
+Changes the logical volume into a thin volume for the thin pool
+specified with the option \fB\-\-thinpool\fP. \fIExternalOriginLogicalVolume\fP
+is converted into a new read-only logical volume which will be used as an
+external origin volume for unprovisioned areas.
+The non-default name for this new volume can be specified with \fB\-\-originname\fP.
+.TP
.IR \fB\-\-thinpool " " ThinPoolLogicalVolume { Name | Path }
Changes logical volume into a thin pool volume. The volume
will store the pool's data.
@@ -379,6 +397,20 @@ available in the volume group.
.sp
.B lvconvert \-\-replace /dev/sdb1 vg00/my_raid1 /dev/sdf1
+Convert the logical volume "vg00/lvpool" into a thin pool with chunk size 128KiB
+and convert "vg00/lv1" into a thin volume using this pool. Original "vg00/lv1"
+is used as an external read-only origin, where all writes to such volume
+are stored in the "vg00/lvpool".
+.sp
+.B lvconvert \-\-thinpool vg00/lvpool -c 128 -T lv1
+
+Convert the logical volume "vg00/origin" into a thin volume from the thin pool
+"vg00/lvpool". This thin volume will use "vg00/origin" as an external origin
+volume for unprovisioned areas in this volume.
+For the read-only external origin use the new name "vg00/external".
+.sp
+.B lvconvert \-\-thinpool vg00/lvpool \-\-originname external -T vg00/origin
+
.SH SEE ALSO
.BR lvm (8),
.BR vgcreate (8),
diff --git a/tools/args.h b/tools/args.h
index d4d6c40..b140cdb 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -69,6 +69,7 @@ arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0)
arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0)
arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0)
+arg(originname_ARG, '\0', "originname", string_arg, 0)
arg(poll_ARG, '\0', "poll", yes_no_arg, 0)
arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0)
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0)
diff --git a/tools/commands.h b/tools/commands.h
index 986539e..32d3c96 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -151,6 +151,8 @@ xx(lvconvert,
"\t [--poolmetadatasize size]\n"
"\t [-r|--readahead ReadAheadSectors|auto|none]\n"
"\t [--stripes Stripes [-I|--stripesize StripeSize]]]\n"
+ "\t[-T|--thin ExternalLogicalVolume[Path]\n"
+ "\t [--originname NewExternalOriginVolumeName]]\n"
"\t[-Z|--zero {y|n}]\n"
"\t[-d|--debug] [-h|-?|--help] [-v|--verbose]\n",
@@ -158,7 +160,8 @@ xx(lvconvert,
merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG, noudevsync_ARG,
readahead_ARG, regionsize_ARG, repair_ARG, replace_ARG, snapshot_ARG, splitmirrors_ARG,
trackchanges_ARG, type_ARG, stripes_long_ARG, stripesize_ARG, test_ARG,
- chunksize_ARG, discards_ARG, poolmetadata_ARG, poolmetadatasize_ARG, thinpool_ARG,
+ chunksize_ARG, discards_ARG, poolmetadata_ARG, poolmetadatasize_ARG,
+ originname_ARG, thin_ARG, thinpool_ARG,
use_policies_ARG, yes_ARG, force_ARG, zero_ARG)
xx(lvcreate,
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 962a35a..234eb41 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -57,6 +57,7 @@ struct lvconvert_params {
struct logical_volume *lv_to_poll;
uint64_t poolmetadata_size;
+ const char *origin_lv_name;
const char *pool_data_lv_name;
const char *pool_metadata_lv_name;
thin_discards_t discards;
@@ -68,6 +69,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
{
char *ptr;
const char *vg_name = NULL;
+ const char *tmp_str;
if (lp->merge)
return 1;
@@ -94,16 +96,35 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
if (lp->pool_data_lv_name) {
if (*pargc) {
- log_error("More then one logical volume name name specified.");
- return 0;
+ if (!arg_count(cmd, thin_ARG)) {
+ log_error("More then one logical volume name specified.");
+ return 0;
+ }
+ } else {
+ if (arg_count(cmd, thin_ARG)) {
+ log_error("External thin volume name is missing.");
+ return 0;
+ }
+
+ if (!lp->vg_name || !validate_name(lp->vg_name)) {
+ log_error("Please provide a valid volume group name.");
+ return 0;
+ }
+
+ lp->lv_name = lp->pool_data_lv_name;
+ return 1;
}
+ }
- if (!lp->vg_name || !validate_name(lp->vg_name)) {
- log_error("Please provide a valid volume group name.");
- return 0;
+ if (lp->origin_lv_name) {
+ /* FIXME: Using generic routine */
+ if (strchr(lp->origin_lv_name, '/')) {
+ if (!(lp->vg_name = extract_vgname(cmd, lp->origin_lv_name)))
+ return_0;
+ /* Strip VG from origin_lv_name */
+ if ((tmp_str = strrchr(lp->origin_lv_name, '/')))
+ lp->origin_lv_name = tmp_str + 1;
}
- lp->lv_name = lp->pool_data_lv_name;
- return 1; /* Create metadata LV on it's own */
}
if (!*pargc) {
@@ -219,6 +240,9 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
return 0;
}
lp->discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_PASSDOWN);
+ } else if (arg_count(cmd, thin_ARG)) {
+ log_error("--thin is only valid with --thinpool.");
+ return 0;
} else if (arg_count(cmd, discards_ARG)) {
log_error("--discards is only valid with --thinpool.");
return 0;
@@ -376,6 +400,13 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
lp->pool_data_lv_name = tmp_str + 1;
}
+ if (arg_count(cmd, originname_ARG)) {
+ if (!(lp->origin_lv_name = arg_str_value(cmd, originname_ARG, NULL))) {
+ log_error("--originname is invalid.");
+ return 0;
+ }
+ }
+
lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, "thin-pool"));
if (!lp->segtype)
return_0;
@@ -1825,6 +1856,116 @@ out:
return r;
}
+/* Swap lvid and LV names */
+static int _swap_lv(struct cmd_context *cmd,
+ struct logical_volume *a, struct logical_volume *b)
+{
+ union lvid lvid;
+ const char *name;
+
+ lvid = a->lvid;
+ a->lvid = b->lvid;
+ b->lvid = lvid;
+
+ name = a->name;
+ a->name = b->name;
+ if (!lv_rename_update(cmd, b, name, 0))
+ return_0;
+
+ return 1;
+}
+
+static int _lvconvert_thinpool_external(struct cmd_context *cmd,
+ struct logical_volume *pool_lv,
+ struct logical_volume *external_lv,
+ struct lvconvert_params *lp)
+{
+ struct logical_volume *torigin_lv;
+ struct volume_group *vg = pool_lv->vg;
+ struct lvcreate_params lvc = { 0 };
+
+ dm_list_init(&lvc.tags);
+
+ if (!(lvc.segtype = get_segtype_from_string(cmd, "thin")))
+ return_0;
+
+ lvc.activate = CHANGE_AE;
+ lvc.alloc = ALLOC_INHERIT;
+ lvc.lv_name = lp->origin_lv_name;
+ lvc.major = -1;
+ lvc.minor = -1;
+ lvc.permission = LVM_READ;
+ lvc.pool = pool_lv->name;
+ lvc.pvh = &vg->pvs;
+ lvc.read_ahead = DM_READ_AHEAD_AUTO;
+ lvc.stripes = 1;
+ lvc.vg_name = vg->name;
+ lvc.voriginextents = external_lv->le_count;
+ lvc.voriginsize = external_lv->size;
+
+ /* New thin LV needs to be created (all messages sent to pool) */
+ if (!(torigin_lv = lv_create_single(vg, &lvc)))
+ return_0;
+
+ /* Activate again via -torigin, so this active LV is not needed */
+ if (!deactivate_lv(cmd, torigin_lv)) {
+ log_error("Aborting. Unable to deactivate new LV. "
+ "Manual intervention required.");
+ return 0;
+ }
+
+ /*
+ * Crashing till this point will leave plain thin volume
+ * which could be easily removed by the user after i.e. power-off
+ */
+
+ if (!_swap_lv(cmd, torigin_lv, external_lv)) {
+ stack;
+ goto revert_new_lv;
+ }
+
+ /* Preserve read-write status of original LV here */
+ torigin_lv->status |= (external_lv->status & LVM_WRITE);
+
+ if (!attach_thin_external_origin(first_seg(torigin_lv), external_lv)) {
+ stack;
+ goto revert_new_lv;
+ }
+
+ if (!_reload_lv(cmd, vg, torigin_lv)) {
+ stack;
+ goto deactivate_and_revert_new_lv;
+ }
+
+ log_print_unless_silent("Converted %s/%s to thin external origin.",
+ vg->name, external_lv->name);
+
+ return 1;
+
+deactivate_and_revert_new_lv:
+ if (!_swap_lv(cmd, torigin_lv, external_lv))
+ stack;
+
+ if (!deactivate_lv(cmd, torigin_lv)) {
+ log_error("Unable to deactivate failed new LV. "
+ "Manual intervention required.");
+ return 0;
+ }
+
+ if (!detach_thin_external_origin(first_seg(torigin_lv)))
+ return_0;
+
+revert_new_lv:
+ /* FIXME Better to revert to backup of metadata? */
+ if (!lv_remove(torigin_lv) || !vg_write(vg) || !vg_commit(vg))
+ log_error("Manual intervention may be required to remove "
+ "abandoned LV(s) before retrying.");
+ else
+ backup(vg);
+
+ return 0;
+}
+
/*
* Thin lvconvert version which
* rename metadata
@@ -1843,6 +1984,7 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
struct logical_volume *data_lv;
struct logical_volume *metadata_lv;
struct logical_volume *pool_metadata_lv;
+ struct logical_volume *external_lv = NULL;
if (!lv_is_visible(pool_lv)) {
log_error("Can't convert internal LV %s/%s.",
@@ -1850,6 +1992,19 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
return 0;
}
+ if (arg_count(cmd, thin_ARG)) {
+ external_lv = pool_lv;
+ if (!(pool_lv = find_lv(external_lv->vg, lp->pool_data_lv_name))) {
+ log_error("Can't find pool LV %s/%s.",
+ external_lv->vg->name, lp->pool_data_lv_name);
+ return 0;
+ }
+ if (lv_is_thin_pool(pool_lv)) {
+ r = 1; /* Already existing thin pool */
+ goto out;
+ }
+ }
+
if (lv_is_thin_type(pool_lv) && !lp->pool_metadata_lv_name) {
log_error("Can't use thin logical volume %s/%s for thin pool data.",
pool_lv->vg->name, pool_lv->name);
@@ -2064,7 +2219,12 @@ mda_write:
r = 1;
out:
+ if (r && external_lv &&
+ !(r = _lvconvert_thinpool_external(cmd, pool_lv, external_lv, lp)))
+ stack;
+
backup(pool_lv->vg);
+
return r;
}
11 years, 2 months
master - thin: removal of external_origin
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2cba0ea9f96ed6...
Commit: 2cba0ea9f96ed658d11df4428ec20502da1867c0
Parent: 30c13eff3766eb49f925acabf836470b63d05903
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Feb 20 16:14:24 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:37:01 2013 +0100
thin: removal of external_origin
---
lib/metadata/lv_manip.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 72516ea..ef9f643 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3352,6 +3352,12 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
+ if (lv_is_external_origin(lv)) {
+ log_error("Can't remove external origin logical volume \"%s\".",
+ lv->name);
+ return 0;
+ }
+
if (lv->status & MIRROR_IMAGE) {
log_error("Can't remove logical volume %s used by a mirror",
lv->name);
@@ -3578,6 +3584,10 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
return_0;
}
+ if (lv_is_external_origin(lv) &&
+ !_lv_remove_segs_using_this_lv(cmd, lv, force, level, "external origin"))
+ return_0;
+
if (lv_is_used_thin_pool(lv) &&
!_lv_remove_segs_using_this_lv(cmd, lv, force, level, "pool"))
return_0;
11 years, 2 months
master - thin: report external origin
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=30c13eff3766eb...
Commit: 30c13eff3766eb49f925acabf836470b63d05903
Parent: 386f3d5a5e6a8b147793c8e59d72c4496144ec2c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jan 15 15:16:16 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:37:01 2013 +0100
thin: report external origin
Use the field 'origin' for reporting external origin lv name.
For thin volumes with external origin, report the size of
external origin size via:
lvs -o+origin_size
---
lib/display/display.c | 3 +++
lib/metadata/lv.c | 7 ++++++-
lib/report/report.c | 3 +++
3 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/lib/display/display.c b/lib/display/display.c
index b15ff71..c0d0cd9 100644
--- a/lib/display/display.c
+++ b/lib/display/display.c
@@ -594,6 +594,9 @@ int lvdisplay_full(struct cmd_context *cmd,
if (seg->origin)
log_print("LV Thin origin name %s",
seg->origin->name);
+ if (seg->external_lv)
+ log_print("LV External origin name %s",
+ seg->origin->name);
if (inkernel)
thin_active = lv_thin_percent(lv, 0, &thin_percent);
} else if (lv_is_thin_pool(lv)) {
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 9f6b327..f1c79be 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -169,6 +169,9 @@ char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return lv_name_dup(mem, first_seg(lv)->origin);
+ if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
+ return lv_name_dup(mem, first_seg(lv)->external_lv);
+
return NULL;
}
@@ -282,6 +285,8 @@ uint64_t lv_origin_size(const struct logical_volume *lv)
{
if (lv_is_cow(lv))
return (uint64_t) find_cow(lv)->len * lv->vg->extent_size;
+ if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
+ return first_seg(lv)->external_lv->size;
if (lv_is_origin(lv))
return lv->size;
return 0;
diff --git a/lib/report/report.c b/lib/report/report.c
index 5a4e4df..633dfe4 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -343,6 +343,9 @@ static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return _lvname_disp(rh, mem, field, first_seg(lv)->origin, private);
+ if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv)
+ return _lvname_disp(rh, mem, field, first_seg(lv)->external_lv, private);
+
dm_report_field_set_value(field, "", NULL);
return 1;
}
11 years, 2 months
master - thin: external origin cannot be changed
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=386f3d5a5e6a8b...
Commit: 386f3d5a5e6a8b147793c8e59d72c4496144ec2c
Parent: 87331dc41979b649d0b0603c26ff421516fe944e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Feb 5 14:03:43 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:37:01 2013 +0100
thin: external origin cannot be changed
Do not allow conversion of external origin into writeable LV,
and prohibit changing the external origin size.
If the snapshot origin is also external origin, merge is prohibited.
---
tools/lvchange.c | 6 ++++++
tools/lvconvert.c | 6 ++++++
tools/lvresize.c | 9 +++++++++
3 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 07015e7..67db083 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -36,6 +36,12 @@ static int lvchange_permission(struct cmd_context *cmd,
return 0;
}
+ if (lv_is_external_origin(lv)) {
+ log_error("Cannot change permissions of external origin "
+ "\"%s\".", lv->name);
+ return 0;
+ }
+
if ((lv->status & MIRRORED) && (vg_is_clustered(lv->vg)) &&
lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
log_error("Cannot change permissions of mirror \"%s\" "
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 9b41722..962a35a 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2109,6 +2109,12 @@ static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
lv->name);
return ECMD_FAILED;
}
+ if (lv_is_external_origin(origin_from_cow(lv))) {
+ log_error("Cannot merge snapshot \"%s\" into "
+ "the read-only external origin \"%s\".",
+ lv->name, origin_from_cow(lv)->name);
+ return ECMD_FAILED;
+ }
if (lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)
&& info.exists && info.live_table &&
(!lv_snapshot_percent(lv, &snap_percent) ||
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 4c9580d..d49da8a 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -390,6 +390,15 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
return ECMD_FAILED;
}
+ if (lv_is_external_origin(lvl->lv)) {
+ /*
+ * Since external-origin can be activated read-only,
+ * there is no way to use extended areas.
+ */
+ log_error("Cannot resize external origin \"%s\".", lvl->lv->name);
+ return EINVALID_CMD_LINE;
+ }
+
if (lvl->lv->status & (RAID_IMAGE | RAID_META)) {
log_error("Cannot resize a RAID %s directly",
(lvl->lv->status & RAID_IMAGE) ? "image" :
11 years, 2 months
master - thin: add support for external origin
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=87331dc41979b6...
Commit: 87331dc41979b649d0b0603c26ff421516fe944e
Parent: d023b2d12f31700956bca3b274e88c42f2d65d7a
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Feb 21 10:25:44 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:36:58 2013 +0100
thin: add support for external origin
Add internal support for thin volume's external origin.
---
lib/activate/dev_manager.c | 60 ++++++++++++++++++++++++++++++++++++--
lib/format_text/flags.c | 2 +-
lib/metadata/lv.c | 2 +-
lib/metadata/lv.h | 1 +
lib/metadata/lv_manip.c | 5 ++-
lib/metadata/merge.c | 7 ++++-
lib/metadata/metadata-exported.h | 4 ++-
lib/metadata/metadata.h | 5 ++-
lib/metadata/thin_manip.c | 48 ++++++++++++++++++++++++++++++
lib/thin/thin.c | 31 +++++++++++++++++--
10 files changed, 153 insertions(+), 12 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 5ce099e..e326929 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1565,6 +1565,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
/* FIXME Can we avoid doing this every time? */
+ /* Reused also for lv_is_external_origin(lv) */
if (!_add_dev_to_dtree(dm, dtree, lv, "real"))
return_0;
@@ -1596,7 +1597,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
}
/* Add any snapshots of this LV */
- if (lv_is_origin(lv) && !origin_only)
+ if (lv_is_origin(lv) && (lv_is_external_origin(lv) || !origin_only))
dm_list_iterate(snh, &lv->snapshot_segs)
if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
return_0;
@@ -1614,6 +1615,9 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Add any LVs used by segments in this LV */
dm_list_iterate_items(seg, &lv->segments) {
+ if (seg->external_lv &&
+ !_add_lv_to_dtree(dm, dtree, seg->external_lv, 1)) /* stack */
+ return_0;
if (seg->log_lv &&
!_add_lv_to_dtree(dm, dtree, seg->log_lv, origin_only))
return_0;
@@ -2001,6 +2005,45 @@ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
return 1;
}
+static int _add_active_externals_to_dtree(struct dev_manager *dm,
+ struct dm_tree *dtree,
+ struct lv_segment *seg,
+ struct lv_activate_opts *laopts)
+{
+ struct seg_list *sl;
+
+ /* Add any ACTIVE LVs using this external origin LV */
+ log_debug_activation("Adding active users of external lv %s",
+ seg->external_lv->name);
+ dm_list_iterate_items(sl, &seg->external_lv->segs_using_this_lv) {
+ if (sl->seg->external_lv != seg->external_lv ||
+ sl->seg == seg)
+ continue;
+
+ /*
+ * Find if the LV is active
+ * These LVs are not scanned the generic partial dtree
+ * since in most cases we do not want to work with them.
+ * However when new EO user is added all users must be known.
+ *
+ * As EO could have been chained and passed to a new
+ * volume, whole device needs to be tested, so the
+ * removal of layered EO (-real) happens.
+ */
+ if (!_add_lv_to_dtree(dm, dtree, sl->seg->lv, 0))
+ return_0;
+
+ /* Only layer check is needed here (also avoids loop) */
+ if (_cached_info(dm->mem, dtree, sl->seg->lv,
+ lv_layer(sl->seg->lv)) &&
+ !_add_new_lv_to_dtree(dm, dtree, sl->seg->lv,
+ laopts, lv_layer(sl->seg->lv)))
+ return_0;
+ }
+
+ return 1;
+}
+
static int _add_segment_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
struct dm_tree_node *dnode,
@@ -2009,7 +2052,6 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
const char *layer)
{
uint32_t s;
- struct seg_list *sl;
struct lv_segment *seg_present;
const char *target_name;
@@ -2031,6 +2073,17 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
return 0;
}
+ /* Add external origin layer */
+ if (seg->external_lv) {
+ if (!_add_new_lv_to_dtree(dm, dtree, seg->external_lv, laopts,
+ lv_layer(seg->external_lv)))
+ return_0;
+
+ if (!layer &&
+ !_add_active_externals_to_dtree(dm, dtree, seg, laopts))
+ return_0;
+ }
+
/* Add mirror log */
if (seg->log_lv &&
!_add_new_lv_to_dtree(dm, dtree, seg->log_lv, laopts, NULL))
@@ -2200,6 +2253,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* If this is a snapshot origin, add real LV */
/* If this is a snapshot origin + merging snapshot, add cow + real LV */
+ /* Snapshot origin could be also external origin */
if (lv_is_origin(lv) && !layer) {
if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, "real"))
return_0;
@@ -2228,7 +2282,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
if (!_add_snapshot_target_to_dtree(dm, dnode, lv, laopts))
return_0;
- } else if (lv_is_thin_pool(lv) && !layer) {
+ } else if ((lv_is_external_origin(lv) || lv_is_thin_pool(lv)) && !layer) {
/* External origin or Thin pool is using layer */
if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, lv_layer(lv)))
return_0;
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index a3a3d0e..2a6b7a5 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index c27ef08..9f6b327 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -229,7 +229,7 @@ const char *lv_layer(const struct logical_volume *lv)
{
if (lv_is_thin_pool(lv))
return "tpool";
- else if (lv_is_origin(lv))
+ else if (lv_is_origin(lv) || lv_is_external_origin(lv))
return "real";
return NULL;
diff --git a/lib/metadata/lv.h b/lib/metadata/lv.h
index b1078bb..03255fb 100644
--- a/lib/metadata/lv.h
+++ b/lib/metadata/lv.h
@@ -37,6 +37,7 @@ struct logical_volume {
uint32_t le_count;
uint32_t origin_count;
+ uint32_t external_count;
struct dm_list snapshot_segs;
struct lv_segment *snapshot;
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 58c1e26..72516ea 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -321,6 +321,9 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
seg->transaction_id = first_seg(first_seg(thin_pool_lv)->pool_lv)->transaction_id;
if (!attach_pool_lv(seg, first_seg(thin_pool_lv)->pool_lv, thin_pool_lv))
return_NULL;
+ /* Use the same external origin */
+ if (!attach_thin_external_origin(seg, first_seg(thin_pool_lv)->external_lv))
+ return_NULL;
} else {
seg->transaction_id = first_seg(thin_pool_lv)->transaction_id;
if (!attach_pool_lv(seg, thin_pool_lv, NULL))
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index a4563f8..477d7bb 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -243,6 +243,11 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
lv->name, seg_count, seg->device_id);
inc_error_count;
}
+ if (seg->external_lv && (seg->external_lv->status & LVM_WRITE)) {
+ log_error("LV %s: external origin %s is writable.",
+ lv->name, seg->external_lv->name);
+ inc_error_count;
+ }
} else {
if (seg->pool_lv) {
log_error("LV %s: segment %u must not have thin pool LV set",
@@ -372,7 +377,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
seg_found++;
if (seg->metadata_lv == lv || seg->pool_lv == lv)
seg_found++;
- if (seg_is_thin_volume(seg) && seg->origin == lv)
+ if (seg_is_thin_volume(seg) && (seg->origin == lv || seg->external_lv == lv))
seg_found++;
if (!seg_found) {
log_error("LV %s is used by LV %s:%" PRIu32 "-%" PRIu32
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 890aa18..b37d64c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -136,6 +136,7 @@
#define VGMETADATACOPIES_ALL UINT32_MAX
#define VGMETADATACOPIES_UNMANAGED 0
+#define lv_is_external_origin(lv) (((lv)->external_count > 0) ? 1 : 0)
#define lv_is_thin_volume(lv) ((lv)->status & THIN_VOLUME ? 1 : 0)
#define lv_is_thin_pool(lv) ((lv)->status & THIN_POOL ? 1 : 0)
#define lv_is_used_thin_pool(lv) (lv_is_thin_pool(lv) && !dm_list_empty(&(lv)->segs_using_this_lv))
@@ -355,6 +356,7 @@ struct lv_segment {
unsigned zero_new_blocks; /* For thin_pool */
thin_discards_t discards; /* For thin_pool */
struct dm_list thin_messages; /* For thin_pool */
+ struct logical_volume *external_lv; /* For thin */
struct logical_volume *pool_lv; /* For thin */
uint32_t device_id; /* For thin, 24bit */
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index 19bf742..830c0e1 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -475,6 +475,9 @@ int pool_has_message(const struct lv_segment *seg,
int pool_below_threshold(const struct lv_segment *pool_seg);
int extend_pool(struct logical_volume *lv, const struct segment_type *segtype,
struct alloc_handle *ah, uint32_t stripes, uint32_t stripe_size);
+int attach_thin_external_origin(struct lv_segment *seg,
+ struct logical_volume *external_lv);
+int detach_thin_external_origin(struct lv_segment *seg);
/*
* Begin skeleton for external LVM library
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 05fc052..59748de 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -108,6 +108,9 @@ int detach_pool_lv(struct lv_segment *seg)
}
}
+ if (!detach_thin_external_origin(seg))
+ return_0;
+
if (!attach_pool_message(first_seg(seg->pool_lv),
DM_THIN_MESSAGE_DELETE,
NULL, seg->device_id, no_update))
@@ -198,6 +201,51 @@ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
return 1;
}
+int attach_thin_external_origin(struct lv_segment *seg,
+ struct logical_volume *external_lv)
+{
+ if (seg->external_lv) {
+ log_error(INTERNAL_ERROR "LV \"%s\" already has external origin.",
+ seg->lv->name);
+ return 0;
+ }
+
+ seg->external_lv = external_lv;
+
+ if (external_lv) {
+ if (!add_seg_to_segs_using_this_lv(external_lv, seg))
+ return_0;
+
+ external_lv->external_count++;
+
+ if (external_lv->status & LVM_WRITE) {
+ log_verbose("Setting logical volume \"%s\" read-only.",
+ external_lv->name);
+ external_lv->status &= ~LVM_WRITE;
+ }
+ }
+
+ return 1;
+}
+
+int detach_thin_external_origin(struct lv_segment *seg)
+{
+ if (seg->external_lv) {
+ if (!lv_is_external_origin(seg->external_lv)) {
+ log_error(INTERNAL_ERROR "Inconsitent external origin.");
+ return 0;
+ }
+
+ if (!remove_seg_from_segs_using_this_lv(seg->external_lv, seg))
+ return_0;
+
+ seg->external_lv->external_count--;
+ seg->external_lv = NULL;
+ }
+
+ return 1;
+}
+
/*
* Check whether pool has some message queued for LV or for device_id
* When LV is NULL and device_id is 0 it just checks for any message.
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index 4b9bb8b..3e1da91 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -424,7 +424,7 @@ static int _thin_text_import(struct lv_segment *seg,
struct dm_hash_table *pv_hash __attribute__((unused)))
{
const char *lv_name;
- struct logical_volume *pool_lv, *origin = NULL;
+ struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL;
if (!dm_config_get_str(sn, "thin_pool", &lv_name))
return SEG_LOG_ERROR("Thin pool must be a string in");
@@ -450,9 +450,20 @@ static int _thin_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Unsupported value %u for device_id",
seg->device_id);
+ if (dm_config_has_node(sn, "external_origin")) {
+ if (!dm_config_get_str(sn, "external_origin", &lv_name))
+ return SEG_LOG_ERROR("External origin must be a string in");
+
+ if (!(external_lv = find_lv(seg->lv->vg, lv_name)))
+ return SEG_LOG_ERROR("Unknown external origin %s in", lv_name);
+ }
+
if (!attach_pool_lv(seg, pool_lv, origin))
return_0;
+ if (!attach_thin_external_origin(seg, external_lv))
+ return_0;
+
return 1;
}
@@ -462,6 +473,8 @@ static int _thin_text_export(const struct lv_segment *seg, struct formatter *f)
outf(f, "transaction_id = %" PRIu64, seg->transaction_id);
outf(f, "device_id = %d", seg->device_id);
+ if (seg->external_lv)
+ outf(f, "external_origin = \"%s\"", seg->external_lv->name);
if (seg->origin)
outf(f, "origin = \"%s\"", seg->origin->name);
@@ -478,7 +491,7 @@ static int _thin_add_target_line(struct dev_manager *dm,
struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
- char *pool_dlid;
+ char *pool_dlid, *external_dlid;
uint32_t device_id = seg->device_id;
if (!(pool_dlid = build_dm_uuid(mem, seg->pool_lv->lvid.s, lv_layer(seg->pool_lv)))) {
@@ -490,6 +503,18 @@ static int _thin_add_target_line(struct dev_manager *dm,
if (!dm_tree_node_add_thin_target(node, len, pool_dlid, device_id))
return_0;
+ /* Add external origin LV */
+ if (seg->external_lv) {
+ if (!(external_dlid = build_dm_uuid(mem, seg->external_lv->lvid.s,
+ lv_layer(seg->external_lv)))) {
+ log_error("Failed to build uuid for external origin LV %s.",
+ seg->external_lv->name);
+ return 0;
+ }
+ if (!dm_tree_node_set_thin_external_origin(node, external_dlid))
+ return_0;
+ }
+
return 1;
}
11 years, 2 months
master - lvremove: easier removal of dependent lvs
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d023b2d12f3170...
Commit: d023b2d12f31700956bca3b274e88c42f2d65d7a
Parent: 3679bb1cd9f48a0dc4a557ad1c3c3b3713e840bf
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Feb 20 16:13:17 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:31:05 2013 +0100
lvremove: easier removal of dependent lvs
Add function to remove lvs which are depending on removed lv
prior the lv is removed.
User is asked for confirmation.
---
WHATS_NEW | 1 +
lib/metadata/lv_manip.c | 49 ++++++++++++++++++++++++++++++----------------
2 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 273f152..4e1f758 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Add _lv_remove_segs_using_this_lv() for removal of dependent lvs.
Improve activation code for better support of stacked devices.
Add _add_layer_target_to_dtree() for adding linear layer into dtree.
Extend _cached_info() to accept layer string.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 818e740..58c1e26 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3488,6 +3488,35 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
return 1;
}
+static int _lv_remove_segs_using_this_lv(struct cmd_context *cmd, struct logical_volume *lv,
+ const force_t force, unsigned level,
+ const char *lv_type)
+{
+ struct seg_list *sl;
+
+ if ((force == PROMPT) &&
+ yes_no_prompt("Removing %s \"%s\" will remove %u dependent volume(s). "
+ "Proceed? [y/n]: ", lv_type, lv->name,
+ dm_list_size(&lv->segs_using_this_lv)) == 'n') {
+ log_error("Logical volume \"%s\" not removed.", lv->name);
+ return 0;
+ }
+ /*
+ * Not using _safe iterator here - since we may delete whole subtree
+ * (similar as process_each_lv_in_vg())
+ * the code is roughly equivalent to this:
+ *
+ * while (!dm_list_empty(&lv->segs_using_this_lv))
+ * dm_list_iterate_items(sl, &lv->segs_using_this_lv)
+ * break;
+ */
+ dm_list_iterate_items(sl, &lv->segs_using_this_lv)
+ if (!lv_remove_with_dependencies(cmd, sl->seg->lv,
+ force, level + 1))
+ return_0;
+
+ return 1;
+}
/*
* remove LVs with its dependencies - LV leaf nodes should be removed first
*/
@@ -3496,7 +3525,6 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
{
percent_t snap_percent;
struct dm_list *snh, *snht;
- struct seg_list *sl, *tsl;
struct lvinfo info;
if (lv_is_cow(lv)) {
@@ -3547,22 +3575,9 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
return_0;
}
- if (lv_is_used_thin_pool(lv)) {
- /* Remove thin LVs first */
- if ((force == PROMPT) &&
- yes_no_prompt("Removing pool %s will also remove %u "
- "thin volume(s). OK? [y/n]: ", lv->name,
- /* Note: Snaphosts not included */
- dm_list_size(&lv->segs_using_this_lv)) == 'n') {
- log_error("Logical volume %s not removed.", lv->name);
- return 0;
- }
-
- dm_list_iterate_items_safe(sl, tsl, &lv->segs_using_this_lv)
- if (!lv_remove_with_dependencies(cmd, sl->seg->lv,
- force, level + 1))
- return_0;
- }
+ if (lv_is_used_thin_pool(lv) &&
+ !_lv_remove_segs_using_this_lv(cmd, lv, force, level, "pool"))
+ return_0;
return lv_remove_single(cmd, lv, force);
}
11 years, 2 months
master - activation: simplify activation code
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3679bb1cd9f48a...
Commit: 3679bb1cd9f48a0dc4a557ad1c3c3b3713e840bf
Parent: 0631d233d84cc451380155b8062bd37c6f22c2f7
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Feb 21 10:39:47 2013 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Sat Feb 23 10:30:03 2013 +0100
activation: simplify activation code
Reorder activation code to look similar for preload tree and
activation tree.
Its also give much better suppport for device stacking,
since now we also support activation of snapshot which might
be then used for other devices.
---
WHATS_NEW | 1 +
lib/activate/activate.h | 1 -
lib/activate/dev_manager.c | 249 +++++++++++++++++++++-----------------------
lib/thin/thin.c | 15 ---
4 files changed, 121 insertions(+), 145 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 68baaf1..273f152 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Improve activation code for better support of stacked devices.
Add _add_layer_target_to_dtree() for adding linear layer into dtree.
Extend _cached_info() to accept layer string.
Allow identical table reload for RAID to restore transiently failed PVs.
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index df4120c..bf1f7a0 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -34,7 +34,6 @@ struct lv_activate_opts {
int exclusive;
int origin_only;
int no_merging;
- int real_pool;
int send_messages;
int skip_in_use;
unsigned revert;
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 5f0457b..5ce099e 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1556,6 +1556,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
{
uint32_t s;
struct seg_list *sl;
+ struct dm_list *snh;
struct lv_segment *seg = first_seg(lv);
struct dm_tree_node *thin_node;
const char *uuid;
@@ -1570,14 +1571,34 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!origin_only && !_add_dev_to_dtree(dm, dtree, lv, "cow"))
return_0;
- if ((lv->status & MIRRORED) && seg->log_lv &&
- !_add_dev_to_dtree(dm, dtree, seg->log_lv, NULL))
- return_0;
+ if (origin_only && lv_is_thin_volume(lv)) {
+ if (!_add_dev_to_dtree(dm, dtree, lv, NULL))
+ return_0;
+#if 0
+ /* ? Use origin_only to avoid 'deep' thin pool suspend ? */
+ /* FIXME Implement dm_tree_node_skip_children optimisation */
+ if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, lv_lauer(lv))))
+ return_0;
+ if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)))
+ dm_tree_node_skip_children(thin_node, 1);
+#endif
+ }
+
+ if (lv_is_thin_pool(lv)) {
+ if (!_add_dev_to_dtree(dm, dtree, lv, lv_layer(lv)))
+ return_0;
+ /* Setup callback for deactivation based on partial tree */
+ if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
+ return_0;
+ if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
+ !_thin_pool_register_callback(dm, thin_node, lv))
+ return_0;
+ }
- if (lv->status & RAID)
- for (s = 0; s < seg->area_count; s++)
- if (!_add_dev_to_dtree(dm, dtree,
- seg_metalv(seg, s), NULL))
+ /* Add any snapshots of this LV */
+ if (lv_is_origin(lv) && !origin_only)
+ dm_list_iterate(snh, &lv->snapshot_segs)
+ if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
return_0;
/* Add any LVs referencing a PVMOVE LV unless told not to. */
@@ -1591,39 +1612,29 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
!_add_partial_replicator_to_dtree(dm, dtree, lv))
return_0;
- if (lv_is_thin_volume(lv)) {
- if (origin_only) {
- /* origin_only has special meaning for thin volumes */
- if (!_add_dev_to_dtree(dm, dtree, lv, NULL))
- return_0;
-#if 0
- /* FIXME Implement dm_tree_node_skip_children optimisation */
- if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, NULL)))
- return_0;
- if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)))
- dm_tree_node_skip_children(thin_node, 1);
-#endif
- } else {
- /* Add thin pool LV layer */
- lv = seg->pool_lv;
- seg = first_seg(lv);
- }
- }
-
- if (!origin_only && lv_is_thin_pool(lv)) {
- if (!_add_lv_to_dtree(dm, dtree, seg->metadata_lv, 0))
- return_0;
- /* FIXME code from _create_partial_dtree() should be moved here */
- if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, 0), 0))
- return_0;
- if (!_add_dev_to_dtree(dm, dtree, lv, lv_layer(lv)))
+ /* Add any LVs used by segments in this LV */
+ dm_list_iterate_items(seg, &lv->segments) {
+ if (seg->log_lv &&
+ !_add_lv_to_dtree(dm, dtree, seg->log_lv, origin_only))
return_0;
- /* If the partial tree is used for deactivation, setup callback */
- if (!(uuid = build_dm_uuid(dm->mem, lv->lvid.s, lv_layer(lv))))
+ if (seg->metadata_lv &&
+ !_add_lv_to_dtree(dm, dtree, seg->metadata_lv, origin_only))
return_0;
- if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
- !_thin_pool_register_callback(dm, thin_node, lv))
+ if (seg->pool_lv &&
+ !_add_lv_to_dtree(dm, dtree, seg->pool_lv, 1)) /* stack */
return_0;
+
+ for (s = 0; s < seg->area_count; s++) {
+ /* FIXME: raid requires to use '0' instead of preserving
+ * origin_only value for stacking */
+ if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
+ !_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
+ return_0;
+ /* FIXME: raid tests fails with origin_only */
+ if (seg_is_raid(seg) &&
+ !_add_lv_to_dtree(dm, dtree, seg_metalv(seg, s), 0))
+ return_0;
+ }
}
return 1;
@@ -1632,9 +1643,6 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv, int origin_only)
{
struct dm_tree *dtree;
- struct dm_list *snh;
- struct lv_segment *seg;
- uint32_t s;
if (!(dtree = dm_tree_create())) {
log_debug_activation("Partial dtree creation failed for %s.", lv->name);
@@ -1644,20 +1652,6 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
if (!_add_lv_to_dtree(dm, dtree, lv, (lv_is_origin(lv) || lv_is_thin_volume(lv)) ? origin_only : 0))
goto_bad;
- /* Add any snapshots of this LV */
- if (!origin_only && lv_is_origin(lv))
- dm_list_iterate(snh, &lv->snapshot_segs)
- if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
- goto_bad;
-
- /* Add any LVs used by segments in this LV */
- dm_list_iterate_items(seg, &lv->segments)
- for (s = 0; s < seg->area_count; s++)
- if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
- if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
- goto_bad;
- }
-
return dtree;
bad:
@@ -2015,10 +2009,9 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
const char *layer)
{
uint32_t s;
- struct dm_list *snh;
+ struct seg_list *sl;
struct lv_segment *seg_present;
const char *target_name;
- struct lv_activate_opts lva;
/* Ensure required device-mapper targets are loaded */
seg_present = find_cow(seg->lv) ? : seg;
@@ -2042,75 +2035,36 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
if (seg->log_lv &&
!_add_new_lv_to_dtree(dm, dtree, seg->log_lv, laopts, NULL))
return_0;
+ /* Add thin pool metadata */
+ if (seg->metadata_lv &&
+ !_add_new_lv_to_dtree(dm, dtree, seg->metadata_lv, laopts, NULL))
+ return_0;
+ /* Add thin pool layer */
+ if (seg->pool_lv &&
+ !_add_new_lv_to_dtree(dm, dtree, seg->pool_lv, laopts,
+ lv_layer(seg->pool_lv)))
+ return_0;
if (seg_is_replicator_dev(seg)) {
if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg, laopts))
return_0;
- /* If this is a snapshot origin, add real LV */
- /* If this is a snapshot origin + merging snapshot, add cow + real LV */
- } else if (lv_is_origin(seg->lv) && !layer) {
- if (!laopts->no_merging && lv_is_merging_origin(seg->lv)) {
- if (!_add_new_lv_to_dtree(dm, dtree,
- find_merging_cow(seg->lv)->cow, laopts, "cow"))
- return_0;
- /*
- * Must also add "real" LV for use when
- * snapshot-merge target is added
- */
- }
- if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "real"))
- return_0;
- } else if (lv_is_cow(seg->lv) && !layer) {
- if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "cow"))
- return_0;
- } else if ((layer != lv_layer(seg->lv)) && seg_is_thin(seg)) {
- lva = *laopts;
- lva.real_pool = 1;
- if (!_add_new_lv_to_dtree(dm, dtree, seg_is_thin_pool(seg) ?
- seg->lv : seg->pool_lv, &lva,
- seg_is_thin_pool(seg) ?
- lv_layer(seg->lv) : lv_layer(seg->pool_lv)))
+ }
+
+ /* Add any LVs used by this segment */
+ for (s = 0; s < seg->area_count; ++s) {
+ if ((seg_type(seg, s) == AREA_LV) &&
+ (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
+ laopts, NULL)))
return_0;
- } else {
- if (seg_is_thin_pool(seg) &&
- !_add_new_lv_to_dtree(dm, dtree, seg->metadata_lv, laopts, NULL))
+ if (seg_is_raid(seg) &&
+ !_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
+ laopts, NULL))
return_0;
-
- /* Add any LVs used by this segment */
- for (s = 0; s < seg->area_count; s++) {
- if ((seg_type(seg, s) == AREA_LV) &&
- (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
- laopts, NULL)))
- return_0;
- if (seg_is_raid(seg) &&
- !_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
- laopts, NULL))
- return_0;
- }
}
- /* Now we've added its dependencies, we can add the target itself */
- if (lv_is_origin(seg->lv) && !layer) {
- if (laopts->no_merging || !lv_is_merging_origin(seg->lv)) {
- if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
- return_0;
- } else {
- if (!_add_snapshot_merge_target_to_dtree(dm, dnode, seg->lv))
- return_0;
- }
- } else if (lv_is_cow(seg->lv) && !layer) {
- if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv, laopts))
- return_0;
- } else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
+ if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0;
- if (lv_is_origin(seg->lv) && !layer)
- /* Add any snapshots of this LV */
- dm_list_iterate(snh, &seg->lv->snapshot_segs)
- if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
- laopts, NULL))
- return_0;
-
return 1;
}
@@ -2172,6 +2126,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_segment *seg;
struct lv_layer *lvlayer;
struct seg_list *sl;
+ struct dm_list *snh;
struct dm_tree_node *dnode;
const struct dm_info *dinfo;
char *name, *dlid;
@@ -2242,21 +2197,62 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Create table */
dm->pvmove_mirror_count = 0u;
- dm_list_iterate_items(seg, &lv->segments) {
- if (!_add_segment_to_dtree(dm, dtree, dnode, seg, laopts, layer))
+
+ /* If this is a snapshot origin, add real LV */
+ /* If this is a snapshot origin + merging snapshot, add cow + real LV */
+ if (lv_is_origin(lv) && !layer) {
+ if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, "real"))
return_0;
- /* These aren't real segments in the LVM2 metadata */
- if (lv_is_origin(lv) && !layer)
- break;
- if (!laopts->no_merging && lv_is_cow(lv) && !layer)
- break;
- if (max_stripe_size < seg->stripe_size * seg->area_count)
- max_stripe_size = seg->stripe_size * seg->area_count;
+ if (!laopts->no_merging && lv_is_merging_origin(lv)) {
+ if (!_add_new_lv_to_dtree(dm, dtree,
+ find_merging_cow(lv)->cow, laopts, "cow"))
+ return_0;
+ /*
+ * Must also add "real" LV for use when
+ * snapshot-merge target is added
+ */
+ if (!_add_snapshot_merge_target_to_dtree(dm, dnode, lv))
+ return_0;
+ } else if (!_add_origin_target_to_dtree(dm, dnode, lv))
+ return_0;
+
+ /* Add any snapshots of this LV */
+ dm_list_iterate(snh, &lv->snapshot_segs)
+ if (!_add_new_lv_to_dtree(dm, dtree,
+ dm_list_struct_base(snh, struct lv_segment,
+ origin_list)->cow,
+ laopts, NULL))
+ return_0;
+ } else if (lv_is_cow(lv) && !layer) {
+ if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, "cow"))
+ return_0;
+ if (!_add_snapshot_target_to_dtree(dm, dnode, lv, laopts))
+ return_0;
+ } else if (lv_is_thin_pool(lv) && !layer) {
+ /* External origin or Thin pool is using layer */
+ if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, lv_layer(lv)))
+ return_0;
+ if (!_add_layer_target_to_dtree(dm, dnode, lv))
+ return_0;
+ } else {
+ /* Add 'real' segments for LVs */
+ dm_list_iterate_items(seg, &lv->segments) {
+ if (!_add_segment_to_dtree(dm, dtree, dnode, seg, laopts, layer))
+ return_0;
+ if (max_stripe_size < seg->stripe_size * seg->area_count)
+ max_stripe_size = seg->stripe_size * seg->area_count;
+ }
}
+ /* Setup thin pool callback */
+ if (lv_is_thin_pool(lv) && layer &&
+ !_thin_pool_register_callback(dm, dnode, lv))
+ return_0;
+
if (read_ahead == DM_READ_AHEAD_AUTO) {
/* we need RA at least twice a whole stripe - see the comment in md/raid0.c */
read_ahead = max_stripe_size * 2;
+ /* FIXME: layered device read-ahead */
if (!read_ahead)
lv_calculate_readahead(lv, &read_ahead);
read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
@@ -2264,11 +2260,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
- /* Setup thin pool callback */
- if (layer && lv_is_thin_pool(lv) &&
- !_thin_pool_register_callback(dm, dnode, lv))
- return_0;
-
/* Add any LVs referencing a PVMOVE LV unless told not to */
if (dm->track_pvmove_deps && (lv->status & PVMOVE))
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
diff --git a/lib/thin/thin.c b/lib/thin/thin.c
index 06ab67b..4b9bb8b 100644
--- a/lib/thin/thin.c
+++ b/lib/thin/thin.c
@@ -251,21 +251,6 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
return 0;
}
- if (!laopts->real_pool) {
- if (!(pool_dlid = build_dm_uuid(mem, seg->lv->lvid.s, "tpool"))) {
- log_error("Failed to build uuid for thin pool LV %s.", seg->pool_lv->name);
- return 0;
- }
-
- if (!add_linear_area_to_dtree(node, len, seg->lv->vg->extent_size,
- cmd->use_linear_target,
- seg->lv->vg->name, seg->lv->name) ||
- !dm_tree_node_add_target_area(node, NULL, pool_dlid, 0))
- return_0;
-
- return 1;
- }
-
if (!(metadata_dlid = build_dm_uuid(mem, seg->metadata_lv->lvid.s, NULL))) {
log_error("Failed to build uuid for metadata LV %s.",
seg->metadata_lv->name);
11 years, 2 months