master - snapshot: Rename snapshot segment returning methods from find_*_cow to find_*_snapshot
by Mike Snitzer
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f9e0adcce56055...
Commit: f9e0adcce56055f625ab8c77c7d66e4db61fe23a
Parent: 79106f73940762ccde7fa536f37f922ba4773b70
Author: Mike Snitzer <snitzer(a)redhat.com>
AuthorDate: Tue Jul 2 16:26:03 2013 -0400
Committer: Mike Snitzer <snitzer(a)redhat.com>
CommitterDate: Tue Jul 2 16:26:03 2013 -0400
snapshot: Rename snapshot segment returning methods from find_*_cow to find_*_snapshot
find_cow -> find_snapshot, find_merging_cow -> find_merging_snapshot.
Will thin snapshot code to reuse these methods without confusion.
---
WHATS_NEW | 1 +
lib/activate/activate.c | 2 +-
lib/activate/dev_manager.c | 20 ++++++++++----------
lib/display/display.c | 2 +-
lib/metadata/lv.c | 4 ++--
lib/metadata/lv_manip.c | 2 +-
lib/metadata/metadata-exported.h | 6 +++---
lib/metadata/snapshot_manip.c | 35 +++++++++++++++++------------------
tools/lvconvert.c | 8 ++++----
9 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 5d9d27a..60b2fac 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Rename snapshot segment returning methods from find_*_cow to find_*_snapshot.
liblvm/python API: Additions: PV create/removal/resize/listing
liblvm/python API: Additions: LV attr/origin/Thin pool/Thin LV creation
Add vgs/lvs -o vg_profile/lv_profile to report profiles attached to VG/LV.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 2f1718b..204cceb 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -74,7 +74,7 @@ int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
return_0;
if (lv_is_cow(seg->lv)) {
- snap_seg = find_cow(seg->lv);
+ snap_seg = find_snapshot(seg->lv);
if (snap_seg->segtype->ops->modules_needed &&
!snap_seg->segtype->ops->modules_needed(mem, snap_seg,
modules)) {
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 85bd724..74afaac 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1162,7 +1162,7 @@ static int _belong_to_vg(const char *vgname, const char *name)
return 0;
}
- if (!(snap_seg = find_cow(lv)))
+ if (!(snap_seg = find_snapshot(lv)))
return 1;
old_origin = snap_seg->origin;
@@ -1170,7 +1170,7 @@ static int _belong_to_vg(const char *vgname, const char *name)
/* Was this the last active snapshot with this origin? */
dm_list_iterate_items(lvl, active_head) {
active = lvl->lv;
- if ((snap_seg = find_cow(active)) &&
+ if ((snap_seg = find_snapshot(active)) &&
snap_seg->origin == old_origin) {
return 1;
}
@@ -1977,20 +1977,20 @@ static int _add_snapshot_merge_target_to_dtree(struct dev_manager *dm,
struct logical_volume *lv)
{
const char *origin_dlid, *cow_dlid, *merge_dlid;
- struct lv_segment *merging_cow_seg = find_merging_cow(lv);
+ struct lv_segment *merging_snap_seg = find_merging_snapshot(lv);
if (!(origin_dlid = build_dm_uuid(dm->mem, lv->lvid.s, "real")))
return_0;
- if (!(cow_dlid = build_dm_uuid(dm->mem, merging_cow_seg->cow->lvid.s, "cow")))
+ if (!(cow_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow->lvid.s, "cow")))
return_0;
- if (!(merge_dlid = build_dm_uuid(dm->mem, merging_cow_seg->cow->lvid.s, NULL)))
+ if (!(merge_dlid = build_dm_uuid(dm->mem, merging_snap_seg->cow->lvid.s, NULL)))
return_0;
if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid,
cow_dlid, merge_dlid,
- merging_cow_seg->chunk_size))
+ merging_snap_seg->chunk_size))
return_0;
return 1;
@@ -2006,7 +2006,7 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
struct lv_segment *snap_seg;
uint64_t size;
- if (!(snap_seg = find_cow(lv))) {
+ if (!(snap_seg = find_snapshot(lv))) {
log_error("Couldn't find snapshot for '%s'.", lv->name);
return 0;
}
@@ -2165,7 +2165,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
const char *target_name;
/* Ensure required device-mapper targets are loaded */
- seg_present = find_cow(seg->lv) ? : seg;
+ seg_present = find_snapshot(seg->lv) ? : seg;
target_name = (seg_present->segtype->ops->target_name ?
seg_present->segtype->ops->target_name(seg_present, laopts) :
seg_present->segtype->name);
@@ -2310,7 +2310,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (((dinfo = _cached_info(dm->mem, dtree, lv, NULL)) &&
dinfo->open_count) ||
((dinfo = _cached_info(dm->mem, dtree,
- find_merging_cow(lv)->cow, NULL)) &&
+ find_merging_snapshot(lv)->cow, NULL)) &&
dinfo->open_count)) {
/* FIXME Is there anything simpler to check for instead? */
if (!lv_has_target_type(dm->mem, lv, NULL, "snapshot-merge"))
@@ -2369,7 +2369,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
return_0;
if (!laopts->no_merging && lv_is_merging_origin(lv)) {
if (!_add_new_lv_to_dtree(dm, dtree,
- find_merging_cow(lv)->cow, laopts, "cow"))
+ find_merging_snapshot(lv)->cow, laopts, "cow"))
return_0;
/*
* Must also add "real" LV for use when
diff --git a/lib/display/display.c b/lib/display/display.c
index 121a85e..e2b0f76 100644
--- a/lib/display/display.c
+++ b/lib/display/display.c
@@ -569,7 +569,7 @@ int lvdisplay_full(struct cmd_context *cmd,
snap_active ? "active" : "INACTIVE");
}
snap_seg = NULL;
- } else if ((snap_seg = find_cow(lv))) {
+ } else if ((snap_seg = find_snapshot(lv))) {
if (inkernel &&
(snap_active = lv_snapshot_percent(snap_seg->cow,
&snap_percent)))
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 475a514..0742562 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -169,7 +169,7 @@ uint64_t lvseg_chunksize(const struct lv_segment *seg)
uint64_t size;
if (lv_is_cow(seg->lv))
- size = (uint64_t) find_cow(seg->lv)->chunk_size;
+ size = (uint64_t) find_snapshot(seg->lv)->chunk_size;
else if (seg_is_thin_pool(seg))
size = (uint64_t) seg->chunk_size;
else
@@ -324,7 +324,7 @@ uint64_t lv_origin_size(const struct logical_volume *lv)
struct lv_segment *seg;
if (lv_is_cow(lv))
- return (uint64_t) find_cow(lv)->len * lv->vg->extent_size;
+ return (uint64_t) find_snapshot(lv)->len * lv->vg->extent_size;
if (lv_is_thin_volume(lv) && (seg = first_seg(lv)) &&
seg->external_lv)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 38f5b45..4c3beb0 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3634,7 +3634,7 @@ int lv_resize(struct cmd_context *cmd, struct volume_group *vg,
}
lp->extents += lv->le_count;
if (lv_is_cow(lv)) {
- extents_used = cow_max_extents(origin_from_cow(lv), find_cow(lv)->chunk_size);
+ extents_used = cow_max_extents(origin_from_cow(lv), find_snapshot(lv)->chunk_size);
if (extents_used < lp->extents) {
log_print_unless_silent("Reached maximum COW size %s.",
display_size(vg->cmd, (uint64_t) vg->extent_size * extents_used));
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d6c6acb..7b7ac3c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -801,10 +801,10 @@ int lv_is_visible(const struct logical_volume *lv);
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
-struct lv_segment *find_merging_cow(const struct logical_volume *origin);
+struct lv_segment *find_merging_snapshot(const struct logical_volume *origin);
/* Given a cow LV, return return the snapshot lv_segment that uses it */
-struct lv_segment *find_cow(const struct logical_volume *lv);
+struct lv_segment *find_snapshot(const struct logical_volume *lv);
/* Given a cow LV, return its origin */
struct logical_volume *origin_from_cow(const struct logical_volume *lv);
@@ -812,7 +812,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv);
void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
struct logical_volume *cow, uint32_t chunk_size, int merge);
-int init_snapshot_merge(struct lv_segment *cow_seg, struct logical_volume *origin);
+int init_snapshot_merge(struct lv_segment *snap_seg, struct logical_volume *origin);
void clear_snapshot_merge(struct logical_volume *origin);
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index e0d2f5b..f949b23 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -70,7 +70,7 @@ uint32_t cow_max_extents(const struct logical_volume *origin, uint32_t chunk_siz
int lv_is_cow_covering_origin(const struct logical_volume *lv)
{
return lv_is_cow(lv) &&
- (lv->size >= _cow_max_size(origin_from_cow(lv)->size, find_cow(lv)->chunk_size));
+ (lv->size >= _cow_max_size(origin_from_cow(lv)->size, find_snapshot(lv)->chunk_size));
}
int lv_is_visible(const struct logical_volume *lv)
@@ -101,22 +101,21 @@ int lv_is_merging_origin(const struct logical_volume *origin)
return (origin->status & MERGING) ? 1 : 0;
}
-struct lv_segment *find_merging_cow(const struct logical_volume *origin)
+struct lv_segment *find_merging_snapshot(const struct logical_volume *origin)
{
if (!lv_is_merging_origin(origin))
return NULL;
- return find_cow(origin);
+ return find_snapshot(origin);
}
int lv_is_merging_cow(const struct logical_volume *snapshot)
{
/* checks lv_segment's status to see if cow is merging */
- return (find_cow(snapshot)->status & MERGING) ? 1 : 0;
+ return (find_snapshot(snapshot)->status & MERGING) ? 1 : 0;
}
-/* Given a cow LV, return the snapshot lv_segment that uses it */
-struct lv_segment *find_cow(const struct logical_volume *lv)
+struct lv_segment *find_snapshot(const struct logical_volume *lv)
{
return lv->snapshot;
}
@@ -153,27 +152,27 @@ void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
dm_list_add(&origin->snapshot_segs, &seg->origin_list);
}
-int init_snapshot_merge(struct lv_segment *cow_seg,
+int init_snapshot_merge(struct lv_segment *snap_seg,
struct logical_volume *origin)
{
/*
- * Even though lv_is_visible(cow_seg->lv) returns 0,
- * the cow_seg->lv (name: snapshotX) is _not_ hidden;
+ * Even though lv_is_visible(snap_seg->lv) returns 0,
+ * the snap_seg->lv (name: snapshotX) is _not_ hidden;
* this is part of the lvm2 snapshot fiction. Must
* clear VISIBLE_LV directly (lv_set_visible can't)
- * - cow_seg->lv->status is used to control whether 'lv'
+ * - snap_seg->lv->status is used to control whether 'lv'
* (with user provided snapshot LV name) is visible
* - this also enables vg_validate() to succeed with
- * merge metadata (cow_seg->lv is now "internal")
+ * merge metadata (snap_seg->lv is now "internal")
*/
- cow_seg->lv->status &= ~VISIBLE_LV;
- cow_seg->status |= MERGING;
- origin->snapshot = cow_seg;
+ snap_seg->lv->status &= ~VISIBLE_LV;
+ snap_seg->status |= MERGING;
+ origin->snapshot = snap_seg;
origin->status |= MERGING;
- if (cow_seg->segtype->ops->target_present &&
- !cow_seg->segtype->ops->target_present(cow_seg->lv->vg->cmd,
- cow_seg, NULL))
+ if (snap_seg->segtype->ops->target_present &&
+ !snap_seg->segtype->ops->target_present(snap_seg->lv->vg->cmd,
+ snap_seg, NULL))
return 0;
return 1;
@@ -231,7 +230,7 @@ int vg_remove_snapshot(struct logical_volume *cow)
dm_list_del(&cow->snapshot->origin_list);
origin->origin_count--;
- if (find_merging_cow(origin) == find_cow(cow)) {
+ if (find_merging_snapshot(origin) == find_snapshot(cow)) {
clear_snapshot_merge(origin);
/*
* preload origin IFF "snapshot-merge" target is active
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 542c71d..4ac7e54 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -603,7 +603,7 @@ static int _finish_lvconvert_merge(struct cmd_context *cmd,
struct logical_volume *lv,
struct dm_list *lvs_changed __attribute__((unused)))
{
- struct lv_segment *snap_seg = find_merging_cow(lv);
+ struct lv_segment *snap_seg = find_merging_snapshot(lv);
if (!snap_seg) {
log_error("Logical volume %s has no merging snapshot.", lv->name);
return 0;
@@ -1784,7 +1784,7 @@ static int lvconvert_merge(struct cmd_context *cmd,
int r = 0;
int merge_on_activate = 0;
struct logical_volume *origin = origin_from_cow(lv);
- struct lv_segment *cow_seg = find_cow(lv);
+ struct lv_segment *snap_seg = find_snapshot(lv);
struct lvinfo info;
/* Check if merge is possible */
@@ -1794,7 +1794,7 @@ static int lvconvert_merge(struct cmd_context *cmd,
}
if (lv_is_merging_origin(origin)) {
log_error("Snapshot %s is already merging into the origin",
- find_merging_cow(origin)->cow->name);
+ find_merging_snapshot(origin)->cow->name);
return 0;
}
@@ -1821,7 +1821,7 @@ static int lvconvert_merge(struct cmd_context *cmd,
}
}
- if (!init_snapshot_merge(cow_seg, origin)) {
+ if (!init_snapshot_merge(snap_seg, origin)) {
log_error("Can't initialize snapshot merge. "
"Missing support in kernel?");
return_0;
10 years, 11 months
master - liblvm/python-lvm New additions
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=79106f73940762...
Commit: 79106f73940762ccde7fa536f37f922ba4773b70
Parent: 04efe869a440590d99a886cda74aaf259b8067d7
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Mon Jul 1 17:23:06 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
liblvm/python-lvm New additions
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
WHATS_NEW | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index b68360f..5d9d27a 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
Version 2.02.99 -
===================================
+ liblvm/python API: Additions: PV create/removal/resize/listing
+ liblvm/python API: Additions: LV attr/origin/Thin pool/Thin LV creation
Add vgs/lvs -o vg_profile/lv_profile to report profiles attached to VG/LV.
Add default.profile configuration profile and install it on make install.
Create a new 'conf' subdir for configuration files including profiles.
10 years, 11 months
master - python-lvm: Improve unit test case(s)
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=04efe869a44059...
Commit: 04efe869a440590d99a886cda74aaf259b8067d7
Parent: 50db109e2068d8d5645bd4117b6022acf4b7f8ba
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Mon Jul 1 17:01:48 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
python-lvm: Improve unit test case(s)
Create/remove PV
Create/remove snapshots (old type & thin)
PV lookups based on name and UUID
PV resize
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
test/api/pytest.sh | 7 +-
test/api/python_lvm_unit.py | 332 +++++++++++++++++++++++++++++++++----------
2 files changed, 259 insertions(+), 80 deletions(-)
diff --git a/test/api/pytest.sh b/test/api/pytest.sh
index ad99624..a1a3cb4 100644
--- a/test/api/pytest.sh
+++ b/test/api/pytest.sh
@@ -13,15 +13,16 @@
. lib/test
-aux prepare_vg 1
-lvcreate -n test -l 5 $vg
+#If you change this change the unit test case too.
+aux prepare_pvs 6
#Locate the python binding library to use.
python_lib=`find $abs_top_builddir -name lvm.so`
if [ "$python_lib" != "" ]
then
export PYTHONPATH=`dirname $python_lib`:$PYTHONPATH
- python_lvm_unit.py
+ python_lvm_unit.py -v
+ #nemiver python ../api/python_lvm_unit.py -v -f
else
echo "Unable to test python bindings as library not available"
fi
diff --git a/test/api/python_lvm_unit.py b/test/api/python_lvm_unit.py
index c4d7983..6491413 100755
--- a/test/api/python_lvm_unit.py
+++ b/test/api/python_lvm_unit.py
@@ -27,8 +27,130 @@ def rs(l=10):
class TestLvm(unittest.TestCase):
+ (FULL_PV, THIN_PV_A, THIN_PV_B, RESIZE_PV) = (0, 1, 2, 3)
+
+
+ def _get_pv_devices(self):
+ rc = []
+ with lvm.listPvs() as pvs:
+ for p in pvs:
+ name = p.getName()
+ self.assertTrue(name is not None and len(name) > 0)
+ rc.append(name)
+ p = None
+ return rc
+
+ def _createThick(self, device_list):
+ vg = lvm.vgCreate('full_vg')
+
+ for d in device_list:
+ vg.extend(d)
+
+ new_extent = 1024 * 1024 * 2
+ vg.setExtentSize(new_extent)
+ self.assertEqual(vg.getExtentSize(), new_extent)
+
+ vg.createLvLinear('thick_lv', vg.getSize()/2)
+ vg.close()
+ vg = None
+
+ def _removeThick(self):
+ vg_name = 'full_vg'
+ vg = lvm.vgOpen(vg_name, 'w')
+
+ pvs = vg.listPVs()
+ lvs = vg.listLVs()
+
+ pe_devices = []
+
+ #Remove old snapshots first, then lv
+ for l in lvs:
+ attr = l.getAttr()
+ if attr[0] == 's':
+ l.remove()
+
+ for l in vg.listLVs():
+ l.remove()
+
+ for p in pvs:
+ pe_devices.append(p.getName())
+
+ for pv in pe_devices:
+ vg.reduce(pv)
+
+ vg.remove()
+ vg.close()
+
def setUp(self):
- pass
+ device_list = self._get_pv_devices()
+
+ #Make sure our prepare script is doing as expected.
+ self.assertTrue(len(device_list) >= 4)
+
+ vg_names = lvm.listVgNames()
+
+ #If we don't have any volume groups lets setup one for
+ #those tests that are expecting one
+ if len(vg_names) == 0:
+ self._createThick([device_list[TestLvm.FULL_PV]])
+
+ vg = lvm.vgCreate('thin_vg')
+ vg.extend(device_list[TestLvm.THIN_PV_A])
+ vg.extend(device_list[TestLvm.THIN_PV_B])
+ vg.createLvThinpool('thin_pool', vg.getSize()/2, 0, 0,
+ lvm.THIN_DISCARDS_PASSDOWN, 1)
+ vg.createLvThin('thin_pool', 'thin_lv', vg.getSize()/3)
+ vg.close()
+ vg = None
+
+ def testPVresize(self):
+ with lvm.listPvs() as pvs:
+ pv = pvs[TestLvm.RESIZE_PV]
+ curr_size = pv.getSize()
+ dev_size = pv.getDevSize()
+ self.assertTrue(curr_size == dev_size)
+ pv.resize(curr_size/2)
+ with lvm.listPvs() as pvs:
+ pv = pvs[TestLvm.RESIZE_PV]
+ resized_size = pv.getSize()
+ self.assertTrue(resized_size != curr_size)
+ pv.resize(dev_size)
+
+ def testPVlifecycle(self):
+ """
+ Test removing and re-creating a PV
+ """
+ target = None
+
+ with lvm.listPvs() as pvs:
+ pv = pvs[TestLvm.RESIZE_PV]
+ target = pv.getName()
+ lvm.pvRemove(target)
+
+ with lvm.listPvs() as pvs:
+ for p in pvs:
+ self.assertTrue(p.getName() != target)
+
+ lvm.pvCreate(target, 0)
+
+ with lvm.listPvs() as pvs:
+ found = False
+ for p in pvs:
+ if p.getName() == target:
+ found = True
+
+ self.assertTrue(found)
+
+ def testPvMethods(self):
+ with lvm.listPvs() as pvs:
+ for p in pvs:
+ p.getName()
+ p.getUuid()
+ p.getMdaCount()
+ p.getSize()
+ p.getDevSize()
+ p.getFree()
+ p = None
def tearDown(self):
pass
@@ -49,26 +171,35 @@ class TestLvm(unittest.TestCase):
vg = lvm.vgOpen(i)
vg.close()
- def _get_lv_test(self, mode='r'):
+ def _get_lv_test(self, lv_vol_type=None, lv_name=None):
vg_name_list = lvm.listVgNames()
for vgname in vg_name_list:
- vg = lvm.vgOpen(vgname, mode)
+ vg = lvm.vgOpen(vgname, "w")
lvs = vg.listLVs()
- if len(lvs):
- return lvs[0]
- return None
- def _get_pv_test(self, mode='r'):
+ for l in lvs:
+ attr = l.getAttr()
+ if lv_vol_type or lv_name:
+ if lv_vol_type is not None and attr[0] == lv_vol_type:
+ return l, vg
+ elif lv_name is not None and lv_name == l.getName():
+ return l, vg
+ else:
+ return l, vg
+ vg.close()
+ return None, None
+
+ def _get_pv_test(self):
vg_name_list = lvm.listVgNames()
for vgname in vg_name_list:
- vg = lvm.vgOpen(vgname, mode)
+ vg = lvm.vgOpen(vgname, "w")
pvs = vg.listPVs()
if len(pvs):
- return pvs[0]
- return None
+ return pvs[0], vg
+ return None, None
def testPvGetters(self):
- pv = self._get_pv_test()
+ pv, vg = self._get_pv_test()
self.assertEqual(type(pv.getName()), str)
self.assertTrue(len(pv.getName()) > 0)
@@ -84,6 +215,8 @@ class TestLvm(unittest.TestCase):
self.assertTrue(type(pv.getFree()) == int or type(pv.getFree()) == long)
+ vg.close()
+
def _test_prop(self, prop_obj, prop, var_type, settable):
result = prop_obj.getProperty(prop)
@@ -92,7 +225,7 @@ class TestLvm(unittest.TestCase):
self.assertTrue(result[1] == settable)
def testPvSegs(self):
- pv = self._get_pv_test("r")
+ pv, vg = self._get_pv_test()
pv_segs = pv.listPVsegs()
#LVsegs returns a tuple, (value, bool settable)
@@ -101,53 +234,96 @@ class TestLvm(unittest.TestCase):
for i in pv_segs:
self._test_prop(i, 'pvseg_start', long, False)
+ vg.close()
+
def testPvProperty(self):
- pv = self._get_pv_test("r")
+ pv, vg = self._get_pv_test()
self._test_prop(pv, 'pv_mda_count', long, False)
+ vg.close()
def testLvProperty(self):
- lv = self._get_lv_test("r")
+ lv, vg = self._get_lv_test()
self._test_prop(lv, 'seg_count', long, False)
+ vg.close()
def testLvTags(self):
- lv = self._get_lv_test("w")
+ lv, vg = self._get_lv_test()
self._testTags(lv)
+ vg.close()
def testLvActiveInactive(self):
- lv = self._get_lv_test("w")
+ lv, vg = self._get_lv_test()
lv.deactivate()
self.assertTrue(lv.isActive() == False)
lv.activate()
self.assertTrue(lv.isActive() == True)
+ vg.close()
def testLvRename(self):
- lv = self._get_lv_test("w")
+ lv, vg = self._get_lv_test()
current_name = lv.getName()
new_name = rs()
lv.rename(new_name)
self.assertEqual(lv.getName(), new_name)
lv.rename(current_name)
+ vg.close()
+
+ def testLvSnapshot(self):
+
+ #Cleanup existing if already present
+ to_remove = [ 'thick_lv_snapshot', 'thin_lv_snapshot']
+
+ for ss in to_remove:
+ snap, vg = self._get_lv_test(None, ss)
+ if snap:
+ snap.remove()
+ vg.close()
+
+
+ thick_lv, vg = self._get_lv_test(None, 'thick_lv')
+
+ self.assertEqual('thick_lv', thick_lv.getName())
+
+ thick_lv.snapshot('thick_lv_snapshot', 1024*1024)
+ vg.close()
+
+ thin_lv, vg = self._get_lv_test(None, 'thin_lv')
+ thin_lv.snapshot('thin_lv_snapshot')
+
+ vg.close()
+
+ thin_ss, vg = self._get_lv_test(None, 'thin_lv_snapshot')
+ self.assertTrue(thin_ss is not None)
+
+ origin = thin_ss.getOrigin()
+ self.assertTrue('thin_lv', origin)
+
+ vg.close()
+
def testLvSuspend(self):
- lv = self._get_lv_test("r")
+ lv, vg = self._get_lv_test()
result = lv.isSuspended()
- self.assertTrue(type(result), bool)
+ self.assertTrue(type(result) == bool)
+ vg.close()
def testLvSize(self):
- lv = self._get_lv_test("r")
+ lv, vg = self._get_lv_test()
result = lv.getSize()
- self.assertTrue(type(result), bool)
+ self.assertTrue(type(result) == int or type(result)== long)
+ vg.close()
def testLvResize(self):
- pass #Not implemented!
-
- def testPvResize(self):
- pass #Patch available, not committed
+ lv, vg = self._get_lv_test('V')
+ curr_size = lv.getSize()
+ lv.resize(curr_size+(1024*1024))
+ latest = lv.getSize()
+ self.assertTrue(curr_size != latest)
def testLvSeg(self):
- lv = self._get_lv_test("r")
+ lv, vg = self._get_lv_test()
lv_segs = lv.listLVsegs()
@@ -157,62 +333,31 @@ class TestLvm(unittest.TestCase):
for i in lv_segs:
self._test_prop(i, 'seg_start_pe', long, False)
- def testLvMisc(self):
- #Need to look at lack of vg_write in vg create
-
- #For this to work cleanly we will remove an existing lv & vg and then
- #put it back so that the test framework can clean it up.
- vg_name_list = lvm.listVgNames()
+ vg.close()
- if len(vg_name_list):
- vg_name = vg_name_list[0]
-
- vg = lvm.vgOpen(vg_name, "w")
+ def testVGsetGetProp(self):
+ vg_name = 'full_vg'
+ vg = lvm.vgOpen(vg_name, 'w')
+ self.assertTrue(vg is not None)
+ if vg:
vg_mda_copies = vg.getProperty('vg_mda_copies')
vg.setProperty('vg_mda_copies', vg_mda_copies[0])
-
- pvs = vg.listPVs()
- lvs = vg.listLVs()
-
- pe_devices = []
- for p in pvs:
- pe_devices.append(p.getName())
-
- self.assertEquals(len(lvs), 1)
-
- lv = lvs[0]
-
- lv_name = lv.getName()
- lv_size = lv.getSize()
-
- lv.remove()
- lv = None
-
- vg.reduce(pe_devices[0])
-
- vg.remove()
vg.close()
- nvg = lvm.vgCreate(vg_name)
- for p in pe_devices:
- nvg.extend(p)
-
- #2MiB extent size
- new_extent = 1024 * 1024 * 2
-
- nvg.setExtentSize(new_extent)
- self.assertEqual(nvg.getExtentSize(), new_extent)
-
- v = nvg.createLvLinear(lv_name, lv_size)
+ def testVGremoveRestore(self):
- lv_find_name = nvg.lvFromName(lv_name)
- lv_find_uuid = nvg.lvFromUuid(v.getUuid())
+ #Store off the list of physical devices
+ pe_devices = []
+ vg = lvm.vgOpen('full_vg', 'w')
- self.assertTrue(lv_find_name.getName() == v.getName())
- self.assertTrue(lv_find_uuid.getUuid() == v.getUuid())
+ pvs = vg.listPVs()
+ for p in pvs:
+ pe_devices.append(p.getName())
+ vg.close()
- nvg.close()
+ self._removeThick()
+ self._createThick(pe_devices)
def testVgNames(self):
vg = lvm.listVgNames()
@@ -234,7 +379,8 @@ class TestLvm(unittest.TestCase):
if len(lvs):
lv = lvs[0]
lv_name = lv.getName()
- self.assertRaises(lvm.LibLVMError, vg.createLvLinear, lv_name,
+ self.assertRaises(lvm.LibLVMError,
+ vg.createLvLinear, lv_name,
lv.getSize())
def testVgUuids(self):
@@ -249,15 +395,46 @@ class TestLvm(unittest.TestCase):
for vg_name in vgs_names:
vg = lvm.vgOpen(vg_name, "r")
- #TODO Write/fix BUG, vg uuid don't match between lvm.listVgUuids
- # and vg.getUuid()
+ #TODO Write/fix BUG, vg uuid don't match between
+ #lvm.listVgUuids and vg.getUuid()
vg_uuid_search = vg.getUuid().replace('-', '')
self.assertTrue(vg_uuid_search in vgs_uuids)
vgs_uuids.remove(vg_uuid_search)
+ vg.close()
self.assertTrue(len(vgs_uuids) == 0)
+ def testPvLookupFromVG(self):
+ vg_names = lvm.listVgNames()
+
+ for vg_name in vg_names:
+ vg = lvm.vgOpen(vg_name, 'w')
+ pvs = vg.listPVs()
+
+ for p in pvs:
+ name = p.getName()
+ uuid = p.getUuid()
+
+ pv_name_lookup = vg.pvFromName(name)
+ pv_uuid_lookup = vg.pvFromUuid(uuid)
+
+ self.assertTrue(pv_name_lookup.getName() == \
+ pv_uuid_lookup.getName())
+ self.assertTrue(pv_name_lookup.getUuid() == \
+ pv_uuid_lookup.getUuid())
+
+ self.assertTrue(name == pv_name_lookup.getName())
+ self.assertTrue(uuid == pv_uuid_lookup.getUuid())
+
+ pv_name_lookup = None
+ pv_uuid_lookup = None
+ p = None
+
+ pvs = None
+ vg.close()
+
+
def testPercentToFloat(self):
self.assertEqual(lvm.percentToFloat(0), 0.0)
self.assertEqual(lvm.percentToFloat(1000000), 1.0)
@@ -273,8 +450,9 @@ class TestLvm(unittest.TestCase):
self.assertEquals(lvm.configOverride("global.test = 1"), None)
def testConfigFindBool(self):
+ either_or = lvm.configFindBool("global/fallback_to_local_locking")
+ self.assertTrue(type(either_or) == bool)
self.assertTrue(lvm.configFindBool("global/locking_type"))
- self.assertFalse(lvm.configFindBool("global/fallback_to_local_locking"))
def testVgFromPVLookups(self):
vgname_list = lvm.listVgNames()
10 years, 11 months
master - liblvm: Moved additional pv resize code
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=50db109e2068d8...
Commit: 50db109e2068d8d5645bd4117b6022acf4b7f8ba
Parent: 40feaa7bbeaca9a89f9b8e87b684c457cd10aa57
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Fri Jun 28 17:25:28 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
liblvm: Moved additional pv resize code
The pv resize code required that a lvm_vg_write be done
to commit the change. When the method to add the ability
to list all PVs, including ones that are not assocated with
a VG we had no way for the user to make the change persistent.
Thus additional resize code was move and now liblvm calls into
a resize function that does indeed write the changes out, thus
not requiring the user to explicitly write out he changes.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
lib/metadata/metadata-exported.h | 8 ++-
lib/metadata/metadata.c | 5 ++
lib/metadata/pv_manip.c | 115 +++++++++++++++++++++++++++++++++++++-
liblvm/lvm_pv.c | 2 +-
tools/pvresize.c | 112 +------------------------------------
5 files changed, 127 insertions(+), 115 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 7743c47..d6c6acb 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -560,8 +560,12 @@ struct physical_volume *pv_create(const struct cmd_context *cmd,
uint64_t pvmetadatasize,
unsigned metadataignore,
struct pvcreate_restorable_params *rp);
-int pv_resize(struct physical_volume *pv, struct volume_group *vg,
- uint64_t size);
+
+int pv_resize_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ const uint64_t new_size);
+
int pv_analyze(struct cmd_context *cmd, const char *pv_name,
uint64_t label_sector);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index e594f7c..2d3f5ec 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3755,6 +3755,11 @@ static int _get_pvs(struct cmd_context *cmd, int warnings,
*/
if (!vgslist) {
pvl_copy->pv->vg = NULL;
+ } else {
+ /* Make sure the vg mode indicates writeable */
+ /* We should rework this function to take a parameter */
+ /* so that we could control this ... */
+ pvl_copy->pv->vg->open_mode = 'w';
}
have_pv = 1;
dm_list_add(pvslist, &pvl_copy->list);
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 3ec20ef..5ab2d24 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -22,6 +22,7 @@
#include "lvmetad.h"
#include "display.h"
#include "label.h"
+#include "../../tools/tools.h"
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
struct physical_volume *pv,
@@ -487,7 +488,7 @@ static int _extend_pv(struct physical_volume *pv, struct volume_group *vg,
* Resize a PV in a VG, adding or removing segments as needed.
* New size must fit within pv->size.
*/
-int pv_resize(struct physical_volume *pv,
+static int pv_resize(struct physical_volume *pv,
struct volume_group *vg,
uint64_t size)
{
@@ -516,7 +517,8 @@ int pv_resize(struct physical_volume *pv,
/* pv->pe_count is 0 now! We need to recalculate! */
/* If there's a VG, calculate new PE count value. */
- if (vg) {
+ /* Don't do for orphan VG */
+ if (vg && !is_orphan_vg(vg->name)) {
/* FIXME: Maybe PE calculation should go into pv->fmt->resize?
(like it is for pv->fmt->setup) */
if (!(new_pe_count = pv_size(pv) / vg->extent_size)) {
@@ -546,6 +548,115 @@ int pv_resize(struct physical_volume *pv,
return 1;
}
+int pv_resize_single(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct physical_volume *pv,
+ const uint64_t new_size)
+{
+ struct pv_list *pvl;
+ uint64_t size = 0;
+ int r = 0;
+ const char *pv_name = pv_dev_name(pv);
+ const char *vg_name = pv_vg_name(pv);
+ struct volume_group *old_vg = vg;
+ int vg_needs_pv_write = 0;
+
+ if (is_orphan_vg(vg_name)) {
+ if (!lock_vol(cmd, vg_name, LCK_VG_WRITE, NULL)) {
+ log_error("Can't get lock for orphans");
+ return 0;
+ }
+
+ if (!(pv = pv_read(cmd, pv_name, 1, 0))) {
+ unlock_vg(cmd, vg_name);
+ log_error("Unable to read PV \"%s\"", pv_name);
+ return 0;
+ }
+ } else {
+ vg = vg_read_for_update(cmd, vg_name, NULL, 0);
+
+ if (vg_read_error(vg)) {
+ release_vg(vg);
+ log_error("Unable to read volume group \"%s\".",
+ vg_name);
+ return 0;
+ }
+
+ if (!(pvl = find_pv_in_vg(vg, pv_name))) {
+ log_error("Unable to find \"%s\" in volume group \"%s\"",
+ pv_name, vg->name);
+ goto out;
+ }
+
+ pv = pvl->pv;
+
+ if (!archive(vg))
+ goto out;
+ }
+
+ if (!(pv->fmt->features & FMT_RESIZE_PV)) {
+ log_error("Physical volume %s format does not support resizing.",
+ pv_name);
+ goto out;
+ }
+
+ /* Get new size */
+ if (!dev_get_size(pv_dev(pv), &size)) {
+ log_error("%s: Couldn't get size.", pv_name);
+ goto out;
+ }
+
+ if (new_size) {
+ if (new_size > size)
+ log_warn("WARNING: %s: Overriding real size. "
+ "You could lose data.", pv_name);
+ log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
+ " sectors.", pv_name, new_size, pv_size(pv));
+ size = new_size;
+ }
+
+ log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
+ pv_name, pv_size(pv));
+
+ if (!pv_resize(pv, vg, size))
+ goto_out;
+
+ 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) ||
+ (vg_needs_pv_write = (fid_get_mda_indexed(vg->fid,
+ (const char *) &pv->id, ID_LEN, 1) != NULL))) &&
+ !pv_write(cmd, pv, 1)) {
+ log_error("Failed to store physical volume \"%s\"",
+ pv_name);
+ goto out;
+ }
+
+ if (!is_orphan_vg(vg_name)) {
+ if (!vg_write(vg) || !vg_commit(vg)) {
+ log_error("Failed to store physical volume \"%s\" in "
+ "volume group \"%s\"", pv_name, vg_name);
+ goto out;
+ }
+ backup(vg);
+ }
+
+ log_print_unless_silent("Physical volume \"%s\" changed", pv_name);
+ r = 1;
+
+out:
+ if (!r && vg_needs_pv_write)
+ log_error("Use pvcreate and vgcfgrestore "
+ "to repair from archived metadata.");
+ unlock_vg(cmd, vg_name);
+ if (is_orphan_vg(vg_name))
+ free_pv_fid(pv);
+ if (!old_vg)
+ release_vg(vg);
+ return r;
+}
+
const char _really_wipe[] =
"Really WIPE LABELS from physical volume \"%s\" of volume group \"%s\" [y/n]? ";
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 9069f6f..8915e7c 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -219,7 +219,7 @@ int lvm_pv_resize(const pv_t pv, uint64_t new_size)
return -1;
}
- if (!pv_resize(pv, pv->vg, size)) {
+ if (!pv_resize_single(pv->vg->cmd, pv->vg, pv, size)) {
log_error("PV re-size failed!");
return -1;
} else {
diff --git a/tools/pvresize.c b/tools/pvresize.c
index 251cf9a..a5f81f8 100644
--- a/tools/pvresize.c
+++ b/tools/pvresize.c
@@ -16,6 +16,7 @@
#include "tools.h"
#include "metadata.h"
+#include "metadata-exported.h"
struct pvresize_params {
uint64_t new_size;
@@ -24,115 +25,6 @@ struct pvresize_params {
unsigned total;
};
-static int _pv_resize_single(struct cmd_context *cmd,
- struct volume_group *vg,
- struct physical_volume *pv,
- const uint64_t new_size)
-{
- struct pv_list *pvl;
- uint64_t size = 0;
- int r = 0;
- const char *pv_name = pv_dev_name(pv);
- const char *vg_name = pv_vg_name(pv);
- struct volume_group *old_vg = vg;
- int vg_needs_pv_write = 0;
-
- if (is_orphan_vg(vg_name)) {
- if (!lock_vol(cmd, vg_name, LCK_VG_WRITE, NULL)) {
- log_error("Can't get lock for orphans");
- return 0;
- }
-
- if (!(pv = pv_read(cmd, pv_name, 1, 0))) {
- unlock_vg(cmd, vg_name);
- log_error("Unable to read PV \"%s\"", pv_name);
- return 0;
- }
- } else {
- vg = vg_read_for_update(cmd, vg_name, NULL, 0);
-
- if (vg_read_error(vg)) {
- release_vg(vg);
- log_error("Unable to read volume group \"%s\".",
- vg_name);
- return 0;
- }
-
- if (!(pvl = find_pv_in_vg(vg, pv_name))) {
- log_error("Unable to find \"%s\" in volume group \"%s\"",
- pv_name, vg->name);
- goto out;
- }
-
- pv = pvl->pv;
-
- if (!archive(vg))
- goto out;
- }
-
- if (!(pv->fmt->features & FMT_RESIZE_PV)) {
- log_error("Physical volume %s format does not support resizing.",
- pv_name);
- goto out;
- }
-
- /* Get new size */
- if (!dev_get_size(pv_dev(pv), &size)) {
- log_error("%s: Couldn't get size.", pv_name);
- goto out;
- }
-
- if (new_size) {
- if (new_size > size)
- log_warn("WARNING: %s: Overriding real size. "
- "You could lose data.", pv_name);
- log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
- " sectors.", pv_name, new_size, pv_size(pv));
- size = new_size;
- }
-
- log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
- pv_name, pv_size(pv));
-
- if (!pv_resize(pv, vg, size))
- goto_out;
-
- 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) ||
- (vg_needs_pv_write = (fid_get_mda_indexed(vg->fid,
- (const char *) &pv->id, ID_LEN, 1) != NULL))) &&
- !pv_write(cmd, pv, 1)) {
- log_error("Failed to store physical volume \"%s\"",
- pv_name);
- goto out;
- }
-
- if (!is_orphan_vg(vg_name)) {
- if (!vg_write(vg) || !vg_commit(vg)) {
- log_error("Failed to store physical volume \"%s\" in "
- "volume group \"%s\"", pv_name, vg_name);
- goto out;
- }
- backup(vg);
- }
-
- log_print_unless_silent("Physical volume \"%s\" changed", pv_name);
- r = 1;
-
-out:
- if (!r && vg_needs_pv_write)
- log_error("Use pvcreate and vgcfgrestore "
- "to repair from archived metadata.");
- unlock_vg(cmd, vg_name);
- if (is_orphan_vg(vg_name))
- free_pv_fid(pv);
- if (!old_vg)
- release_vg(vg);
- return r;
-}
-
static int _pvresize_single(struct cmd_context *cmd,
struct volume_group *vg,
struct physical_volume *pv,
@@ -142,7 +34,7 @@ static int _pvresize_single(struct cmd_context *cmd,
params->total++;
- if (!_pv_resize_single(cmd, vg, pv, params->new_size))
+ if (!pv_resize_single(cmd, vg, pv, params->new_size))
return_ECMD_FAILED;
params->done++;
10 years, 11 months
master - python-lvm: Bug fixes from unit tests.
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=40feaa7bbeaca9...
Commit: 40feaa7bbeaca9a89f9b8e87b684c457cd10aa57
Parent: 8882480083f9b4f769cc8756a2f641ae0452040d
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Tue Jun 18 15:13:27 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
python-lvm: Bug fixes from unit tests.
After the last rebase, existing unit test case was
run which uncovered a number of errors that required
attention.
Uninitialized variables and changes to type of numeric
return type were addressed.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
liblvm/lvm_lv.c | 7 ++++-
liblvm/lvm_vg.c | 11 ++++++++
python/liblvm.c | 56 ++++++++++++++++++++++++++++++-------------
test/api/python_lvm_unit.py | 13 ++++-----
4 files changed, 62 insertions(+), 25 deletions(-)
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 081c73e..15bd813 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -611,7 +611,12 @@ lv_t lvm_lv_create(lv_create_params_t params)
}
if (!lv_create_single(params->vg, ¶ms->lvp))
return_NULL;
- if (!(lvl = find_lv_in_vg(params->vg, params->lvp.lv_name)))
+
+ /* In some case we are making a thin pool so lv_name is not valid, but
+ * pool is.
+ */
+ if (!(lvl = find_lv_in_vg(params->vg,
+ (params->lvp.lv_name) ? params->lvp.lv_name : params->lvp.pool)))
return_NULL;
return (lv_t) lvl->lv;
}
diff --git a/liblvm/lvm_vg.c b/liblvm/lvm_vg.c
index a707589..955afdb 100644
--- a/liblvm/lvm_vg.c
+++ b/liblvm/lvm_vg.c
@@ -345,6 +345,17 @@ struct lvm_property_value lvm_vg_get_property(const vg_t vg, const char *name)
int lvm_vg_set_property(const vg_t vg, const char *name,
struct lvm_property_value *value)
{
+ /* At this point it is unknown if all property set paths make the
+ * appropriate copy of the string. We will allocate a copy on the vg so
+ * that worst case we have two copies which will get freed when the vg gets
+ * released.
+ */
+
+ if (value->is_valid && value->is_string && value->value.string) {
+ value->value.string = dm_pool_strndup(vg->vgmem, value->value.string,
+ strlen(value->value.string) + 1);
+ }
+
return set_property(NULL, vg, NULL, NULL, name, value);
}
diff --git a/python/liblvm.c b/python/liblvm.c
index e696a81..cdeb4bf 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1,7 +1,7 @@
/*
* Liblvm -- Python interface to LVM2 API.
*
- * Copyright (C) 2010, 2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010, 2013 Red Hat, Inc. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -79,6 +79,31 @@ static PyObject *LibLVMError;
} \
} while (0)
+/**
+ * Ensure that we initialize all the bits to a sane state.
+ */
+static pvobject
+*create_py_pv(void)
+{
+ pvobject * pvobj = PyObject_New(pvobject, &LibLVMpvType);
+ if (pvobj) {
+ pvobj->pv = NULL;
+ pvobj->parent_vgobj = NULL;
+ pvobj->parent_pvslistobj = NULL;
+ }
+ return pvobj;
+}
+
+static vgobject
+*create_py_vg(void)
+{
+ vgobject *vgobj = PyObject_New(vgobject, &LibLVMvgType);
+ if (vgobj) {
+ vgobj->vg = NULL;
+ }
+ return vgobj;
+}
+
static PyObject *
liblvm_get_last_error(void)
{
@@ -179,7 +204,7 @@ liblvm_lvm_pvlist_get(pvslistobject *pvsobj)
dm_list_iterate_items(pvl, pvsobj->pvslist) {
/* Create and initialize the object */
- pvobj = PyObject_New(pvobject, &LibLVMpvType);
+ pvobj = create_py_pv();
if (!pvobj) {
Py_DECREF(pytuple);
return NULL;
@@ -434,7 +459,7 @@ liblvm_lvm_vg_open(PyObject *self, PyObject *args)
if (mode == NULL)
mode = "r";
- if ((vgobj = PyObject_New(vgobject, &LibLVMvgType)) == NULL)
+ if ((vgobj = create_py_vg()) == NULL)
return NULL;
if ((vgobj->vg = lvm_vg_open(libh, vgname, mode, 0))== NULL) {
@@ -458,7 +483,7 @@ liblvm_lvm_vg_create(PyObject *self, PyObject *args)
return NULL;
}
- if ((vgobj = PyObject_New(vgobject, &LibLVMvgType)) == NULL)
+ if ((vgobj = create_py_vg()) == NULL)
return NULL;
if ((vgobj->vg = lvm_vg_create(libh, vgname))== NULL) {
@@ -474,8 +499,10 @@ static void
liblvm_vg_dealloc(vgobject *self)
{
/* if already closed, don't reclose it */
- if (self->vg != NULL)
+ if (self->vg != NULL) {
lvm_vg_close(self->vg);
+ self->vg = NULL;
+ }
PyObject_Del(self);
}
@@ -822,9 +849,8 @@ liblvm_lvm_vg_set_property(vgobject *self, PyObject *args)
goto bail;
}
- /* Based on cursory code inspection this path may cause a memory
- leak when calling into set_property, need to verify*/
- string_value = strdup(PyString_AsString(variant_type_arg));
+ string_value = PyString_AsString(variant_type_arg);
+
lvm_property.value.string = string_value;
if (!lvm_property.value.string) {
PyErr_NoMemory();
@@ -853,7 +879,9 @@ liblvm_lvm_vg_set_property(vgobject *self, PyObject *args)
lvm_property.value.integer = temp_py_int;
} else if (PyObject_IsInstance(variant_type_arg, (PyObject*)&PyLong_Type)){
- /* This will fail on negative numbers */
+ /* If PyLong_AsUnsignedLongLong function fails an OverflowError is
+ * raised and (unsigned long long)-1 is returned
+ */
unsigned long long temp_py_long = PyLong_AsUnsignedLongLong(variant_type_arg);
if (temp_py_long == (unsigned long long)-1) {
goto bail;
@@ -874,18 +902,12 @@ liblvm_lvm_vg_set_property(vgobject *self, PyObject *args)
goto lvmerror;
}
- Py_DECREF(variant_type_arg);
Py_INCREF(Py_None);
return Py_None;
lvmerror:
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
bail:
- free(string_value);
- if (variant_type_arg) {
- Py_DECREF(variant_type_arg);
- variant_type_arg = NULL;
- }
return NULL;
}
@@ -1167,7 +1189,7 @@ liblvm_lvm_vg_list_pvs(vgobject *self)
dm_list_iterate_items(pvl, pvs) {
/* Create and initialize the object */
- pvobj = PyObject_New(pvobject, &LibLVMpvType);
+ pvobj = create_py_pv();
if (!pvobj) {
Py_DECREF(pytuple);
return NULL;
@@ -1247,7 +1269,7 @@ liblvm_lvm_pv_from_N(vgobject *self, PyObject *arg, pv_fetch_by_N method)
return NULL;
}
- rc = PyObject_New(pvobject, &LibLVMpvType);
+ rc = create_py_pv();
if (!rc) {
return NULL;
}
diff --git a/test/api/python_lvm_unit.py b/test/api/python_lvm_unit.py
index fdeca75..c4d7983 100755
--- a/test/api/python_lvm_unit.py
+++ b/test/api/python_lvm_unit.py
@@ -76,14 +76,13 @@ class TestLvm(unittest.TestCase):
self.assertEqual(type(pv.getUuid()), str)
self.assertTrue(len(pv.getUuid()) > 0)
- self.assertEqual(type(pv.getMdaCount()), int)
- self.assertEqual(type(pv.getMdaCount()), int)
+ self.assertTrue(type(pv.getMdaCount()) == int or type(pv.getMdaCount()) == long )
- self.assertEqual(type(pv.getSize()), int)
+ self.assertTrue(type(pv.getSize()) == int or type(pv.getSize()) == long)
- self.assertEqual(type(pv.getDevSize()), int)
+ self.assertTrue(type(pv.getDevSize()) == int or type(pv.getSize()) == long)
- self.assertEqual(type(pv.getFree()), int)
+ self.assertTrue(type(pv.getFree()) == int or type(pv.getFree()) == long)
def _test_prop(self, prop_obj, prop, var_type, settable):
result = prop_obj.getProperty(prop)
@@ -327,7 +326,7 @@ class TestLvm(unittest.TestCase):
for method_name in TestLvm.RETURN_NUMERIC:
method = getattr(vg, method_name)
result = method()
- self.assertTrue(type(result) == int)
+ self.assertTrue(type(result) == int or type(result)== long)
vg.close()
@@ -372,4 +371,4 @@ class TestLvm(unittest.TestCase):
vg.close()
if __name__ == "__main__":
- unittest.main()
\ No newline at end of file
+ unittest.main()
10 years, 11 months
master - python-lvm: Change snapshot call impl.
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8882480083f9b4...
Commit: 8882480083f9b4f769cc8756a2f641ae0452040d
Parent: 49e3eecc33dbe0a47d8dcdbf225ddd52a8a6b75d
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Thu Jun 6 16:41:35 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
python-lvm: Change snapshot call impl.
Using the new object parameter creation to create the snapshot.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
python/liblvm.c | 22 ++++++++++++++++------
1 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/python/liblvm.c b/python/liblvm.c
index e631ab1..e696a81 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1582,23 +1582,33 @@ liblvm_lvm_lv_list_lvsegs(lvobject *self)
static PyObject *
liblvm_lvm_lv_snapshot(lvobject *self, PyObject *args)
{
- const char *vgname;
- uint64_t size;
+ const char *snap_name;
+ uint64_t size = 0;
lvobject *lvobj;
+ lv_create_params_t lvp = NULL;
LV_VALID(self);
- if (!PyArg_ParseTuple(args, "sl", &vgname, &size)) {
+ if (!PyArg_ParseTuple(args, "s|K", &snap_name, &size)) {
return NULL;
}
if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
return NULL;
- if ((lvobj->lv = lvm_lv_snapshot(self->lv, vgname, size)) == NULL) {
+ lvobj->parent_vgobj = NULL;
+
+ lvp = lvm_lv_params_create_snapshot(self->lv, snap_name, size);
+ if (lvp) {
+ if ((lvobj->lv = lvm_lv_create(lvp)) == NULL) {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+ } else {
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
- Py_DECREF(lvobj);
- return NULL;
+ Py_DECREF(lvobj);
+ return NULL;
}
lvobj->parent_vgobj = self->parent_vgobj;
10 years, 11 months
master - lvm2app: Add thinp snapshot functionality
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=49e3eecc33dbe0...
Commit: 49e3eecc33dbe0a47d8dcdbf225ddd52a8a6b75d
Parent: 2a3472b2b34d2ef82cc04eb89bd29dfb456e2d47
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Thu Jun 6 16:40:51 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
lvm2app: Add thinp snapshot functionality
Added parameter object constructor for thinp and
changed the shapshot function to use it.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
liblvm/lvm2app.h | 21 +++++++++++-
liblvm/lvm_lv.c | 100 ++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 88 insertions(+), 33 deletions(-)
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 65dc340..f4475c0 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1538,7 +1538,26 @@ lv_create_params_t lvm_lv_params_create_thin_pool(vg_t vg,
LVM_THIN_DISCARDS_PASSDOWN)
-
+/**
+ * Creates the snapshot parameter passing object for the specified lv.
+ *
+ * \param lv
+ * The logical volume to snapshot
+ *
+ * \param snap_name
+ * Name of snapshot
+ *
+ * \param max_snap_size
+ * Used for old snap shots max size, set to zero for thinp
+ *
+ * \return
+ * Valid lv_create_params pointer on success, else NULL on error.
+ * Note: Memory is associated with the vg, it will get reclaimed when vg is
+ * closed.
+ */
+lv_create_params_t lvm_lv_params_create_snapshot(const lv_t lv,
+ const char *snap_name,
+ uint64_t max_snap_size);
/**
* Get the specific value of a lv create parameter by name
*
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 9f59210..081c73e 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -347,41 +347,16 @@ int lvm_lv_resize(const lv_t lv, uint64_t new_size)
return 0;
}
-lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name, uint64_t max_snap_size)
+lv_t lvm_lv_snapshot(const lv_t lv, const char *snap_name,
+ uint64_t max_snap_size)
{
- struct lvcreate_params lp = { 0 };
- uint64_t extents = 0;
- uint64_t size = 0;
- struct lv_list *lvl = NULL;
-
- if (vg_read_error(lv->vg))
- return NULL;
- if (!vg_check_write_mode(lv->vg))
- return NULL;
-
- size = max_snap_size >> SECTOR_SHIFT;
+ struct lvm_lv_create_params *lvcp = NULL;
- if (!(extents = extents_from_size(lv->vg->cmd, size,
- lv->vg->extent_size))) {
- log_error("Unable to create LV snapshot without size.");
- return NULL;
+ lvcp = lvm_lv_params_create_snapshot(lv, snap_name, max_snap_size);
+ if (lvcp) {
+ return lvm_lv_create(lvcp);
}
-
- _lv_set_default_params(&lp, lv->vg, snap_name, extents);
-
- /* Fill out required default input values */
- lp.snapshot = 1;
- lp.segtype = _get_segtype(lv->vg->cmd);
- lp.stripes = 1;
- lp.origin = lv->name;
-
- if (!lp.segtype)
- return_NULL;
- if (!lv_create_single(lv->vg, &lp))
- return_NULL;
- if (!(lvl = find_lv_in_vg(lv->vg, snap_name)))
- return NULL;
- return (lv_t) lvl->lv;
+ return NULL;
}
/* Set defaults for thin pool specific LV parameters */
@@ -496,6 +471,67 @@ static void _lv_set_thin_params(struct lvcreate_params *lp,
lp->stripes = 1;
}
+lv_create_params_t lvm_lv_params_create_snapshot(const lv_t lv,
+ const char *snap_name,
+ uint64_t max_snap_size)
+{
+ uint64_t size = 0;
+ uint64_t extents = 0;
+ struct lvm_lv_create_params *lvcp = NULL;
+
+ if (vg_read_error(lv->vg)) {
+ return NULL;
+ }
+
+ if (!vg_check_write_mode(lv->vg))
+ return NULL;
+
+ if (snap_name == NULL || !strlen(snap_name)) {
+ log_error("snap_name invalid");
+ return NULL;
+ }
+
+ if (max_snap_size) {
+ size = max_snap_size >> SECTOR_SHIFT;
+ extents = extents_from_size(lv->vg->cmd, size, lv->vg->extent_size);
+ }
+
+ if (!size && !lv_is_thin_volume(lv) ) {
+ log_error("Origin is not thin, specify size of snapshot");
+ return NULL;
+ }
+
+ lvcp = dm_pool_zalloc(lv->vg->vgmem, sizeof (struct lvm_lv_create_params));
+ if (lvcp) {
+ lvcp->vg = lv->vg;
+ _lv_set_default_params(&lvcp->lvp, lv->vg, snap_name, extents);
+ lvcp->lvp.snapshot = 1;
+
+
+ if (size) {
+ lvcp->lvp.segtype = _get_segtype(lvcp->vg->cmd);
+ lvcp->lvp.chunk_size = 8;
+ } else {
+ lvcp->lvp.segtype = get_segtype_from_string(lv->vg->cmd, "thin");
+
+ if (!lvcp->lvp.segtype) {
+ log_error(INTERNAL_ERROR "Segtype thin not found.");
+ return NULL;
+ }
+
+ lvcp->lvp.pool = first_seg(lv)->pool_lv->name;
+ }
+
+ lvcp->lvp.stripes = 1;
+ lvcp->lvp.origin = lv->name;
+
+ lvcp->magic = LV_CREATE_PARAMS_MAGIC;
+ }
+
+ return lvcp;
+}
+
+
lv_create_params_t lvm_lv_params_create_thin(const vg_t vg, const char *pool_name,
const char *lvname, uint64_t size)
{
10 years, 11 months
master - python-lvm: Bindings for thin pool, thin lv creation V3
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2a3472b2b34d2e...
Commit: 2a3472b2b34d2ef82cc04eb89bd29dfb456e2d47
Parent: f576b32203e4c1001764d26225fc6dffa97e4da0
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Fri May 3 19:37:52 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
python-lvm: Bindings for thin pool, thin lv creation V3
V2: Bug fix.
V3: Use updated property interface, add constants for discard.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
python/liblvm.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/python/liblvm.c b/python/liblvm.c
index 305fd50..e631ab1 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1032,6 +1032,109 @@ liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args)
return (PyObject *)lvobj;
}
+static PyObject *
+liblvm_lvm_vg_create_lv_thinpool(vgobject *self, PyObject *args)
+{
+ const char *pool_name;
+ uint64_t size = 0;
+ uint32_t chunk_size = 0;
+ uint64_t meta_size = 0;
+ int skip_zero = 0;
+ lvm_thin_discards_t discard = LVM_THIN_DISCARDS_PASSDOWN;
+ lvobject *lvobj;
+ lv_create_params_t lvp = NULL;
+ struct lvm_property_value prop_value;
+
+ VG_VALID(self);
+
+ if (!PyArg_ParseTuple(args, "sK|kKii", &pool_name, &size, &chunk_size,
+ &meta_size, &discard, &skip_zero)) {
+ return NULL;
+ }
+
+ if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
+ return NULL;
+
+ /* Initialize the parent ptr in case lv create fails and we dealloc lvobj */
+ lvobj->parent_vgobj = NULL;
+
+ lvp = lvm_lv_params_create_thin_pool(self->vg, pool_name, size, chunk_size,
+ meta_size, discard);
+
+ if (lvp) {
+ if (skip_zero) {
+ prop_value = lvm_lv_params_get_property(lvp, "skip_zero");
+
+ if (prop_value.is_valid) {
+ prop_value.value.integer = 1;
+
+ if( -1 == lvm_lv_params_set_property(lvp, "skip_zero",
+ &prop_value)) {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+ }
+ }
+
+ if ((lvobj->lv = lvm_lv_create(lvp)) == NULL) {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+ } else {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+
+ lvobj->parent_vgobj = self;
+ Py_INCREF(lvobj->parent_vgobj);
+
+ return (PyObject *)lvobj;
+}
+
+static PyObject *
+liblvm_lvm_vg_create_lv_thin(vgobject *self, PyObject *args)
+{
+ const char *pool_name;
+ const char *lv_name;
+ uint64_t size = 0;
+ lvobject *lvobj;
+ lv_create_params_t lvp = NULL;
+
+ VG_VALID(self);
+
+ if (!PyArg_ParseTuple(args, "ssK", &pool_name, &lv_name, &size)) {
+ return NULL;
+ }
+
+ if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
+ return NULL;
+
+ /* Initialize the parent ptr in case lv create fails and we dealloc lvobj */
+ lvobj->parent_vgobj = NULL;
+
+ lvp = lvm_lv_params_create_thin(self->vg, pool_name, lv_name,size);
+
+ if (lvp) {
+ if ((lvobj->lv = lvm_lv_create(lvp)) == NULL) {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+ } else {
+ PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(lvobj);
+ return NULL;
+ }
+
+ lvobj->parent_vgobj = self;
+ Py_INCREF(lvobj->parent_vgobj);
+
+ return (PyObject *)lvobj;
+}
+
static void
liblvm_lv_dealloc(lvobject *self)
{
@@ -1759,6 +1862,8 @@ static PyMethodDef liblvm_vg_methods[] = {
{ "pvFromUuid", (PyCFunction)liblvm_lvm_pv_from_uuid, METH_VARARGS },
{ "getTags", (PyCFunction)liblvm_lvm_vg_get_tags, METH_NOARGS },
{ "createLvLinear", (PyCFunction)liblvm_lvm_vg_create_lv_linear, METH_VARARGS },
+ { "createLvThinpool", (PyCFunction)liblvm_lvm_vg_create_lv_thinpool, METH_VARARGS },
+ { "createLvThin", (PyCFunction)liblvm_lvm_vg_create_lv_thin, METH_VARARGS },
{ NULL, NULL } /* sentinel */
};
@@ -1915,6 +2020,22 @@ initlvm(void)
if (m == NULL)
return;
+
+ if (-1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_IGNORE",
+ LVM_THIN_DISCARDS_IGNORE)) {
+ return;
+ }
+
+ if (-1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_NO_PASSDOWN",
+ LVM_THIN_DISCARDS_NO_PASSDOWN)) {
+ return;
+ }
+
+ if ( -1 == PyModule_AddIntConstant(m, "THIN_DISCARDS_PASSDOWN",
+ LVM_THIN_DISCARDS_PASSDOWN)) {
+ return;
+ }
+
LibLVMError = PyErr_NewException("Liblvm.LibLVMError",
NULL, NULL);
if (LibLVMError) {
10 years, 11 months
master - python-lvm: Added lv method getOrigin
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f576b32203e4c1...
Commit: f576b32203e4c1001764d26225fc6dffa97e4da0
Parent: a7f3dbf904f369338657785e845ebc8a6f479983
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Thu Apr 11 16:49:08 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
python-lvm: Added lv method getOrigin
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
python/liblvm.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/python/liblvm.c b/python/liblvm.c
index 381af62..305fd50 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -1202,6 +1202,14 @@ liblvm_lvm_lv_get_attr(lvobject *self)
}
static PyObject *
+liblvm_lvm_lv_get_origin(lvobject *self)
+{
+ LV_VALID(self);
+
+ return Py_BuildValue("s", lvm_lv_get_origin(self->lv));
+}
+
+static PyObject *
liblvm_lvm_lv_get_name(lvobject *self)
{
LV_VALID(self);
@@ -1758,6 +1766,7 @@ static PyMethodDef liblvm_lv_methods[] = {
/* lv methods */
{ "getAttr", (PyCFunction)liblvm_lvm_lv_get_attr, METH_NOARGS },
{ "getName", (PyCFunction)liblvm_lvm_lv_get_name, METH_NOARGS },
+ { "getOrigin", (PyCFunction)liblvm_lvm_lv_get_origin, METH_NOARGS },
{ "getUuid", (PyCFunction)liblvm_lvm_lv_get_uuid, METH_NOARGS },
{ "activate", (PyCFunction)liblvm_lvm_lv_activate, METH_NOARGS },
{ "deactivate", (PyCFunction)liblvm_lvm_lv_deactivate, METH_NOARGS },
10 years, 11 months
master - lvm2app: Add function to retrieve the origin.
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a7f3dbf904f369...
Commit: a7f3dbf904f369338657785e845ebc8a6f479983
Parent: 9e0260c2e34f1b7150fb2fac3e780c3e75cd411e
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Thu Apr 11 16:48:40 2013 -0400
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Tue Jul 2 14:24:34 2013 -0500
lvm2app: Add function to retrieve the origin.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
liblvm/lvm2app.h | 16 ++++++++++++++++
liblvm/lvm_lv.c | 5 +++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/liblvm/lvm2app.h b/liblvm/lvm2app.h
index 4a0844e..65dc340 100644
--- a/liblvm/lvm2app.h
+++ b/liblvm/lvm2app.h
@@ -1232,6 +1232,22 @@ const char *lvm_lv_get_name(const lv_t lv);
const char *lvm_lv_get_attr(const lv_t lv);
/**
+ * Get the origin of a snapshot.
+ *
+ * \memberof lv_t
+ *
+ * The memory allocated for the name is tied to the vg_t handle and will be
+ * released when lvm_vg_close() is called.
+ *
+ * \param lv
+ * Logical volume handle.
+ *
+ * \return
+ * Null if the logical volume is not a snapshot, else origin name.
+ */
+const char *lvm_lv_get_origin(const lv_t lv);
+
+/**
* Get the current size in bytes of a logical volume.
*
* \memberof lv_t
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index 6226eac..9f59210 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -62,6 +62,11 @@ const char *lvm_lv_get_attr(const lv_t lv)
return lv_attr_dup(lv->vg->vgmem, lv);
}
+const char *lvm_lv_get_origin(const lv_t lv)
+{
+ return lv_origin_dup(lv->vg->vgmem, lv);
+}
+
struct lvm_property_value lvm_lv_get_property(const lv_t lv, const char *name)
{
return get_property(NULL, NULL, lv, NULL, NULL, NULL, name);
10 years, 11 months