470 lines
12 KiB
Diff
470 lines
12 KiB
Diff
commit 0e47639a44e1630250ea10643f5a440281edfdce
|
|
Author: Andy Grover <agrover@redhat.com>
|
|
Date: Wed Oct 17 12:55:25 2012 -0700
|
|
|
|
python-lvm: Implement proper refcounting for parent objects
|
|
|
|
Our object nesting:
|
|
|
|
lib -> VG -> LV -> lvseg
|
|
-> PV -> pvseg
|
|
|
|
Implement refcounting and checks to ensure parent objects are not
|
|
dealloced before their children. Also ensure calls to self or child's
|
|
methods are handled cleanly for objects that have been closed or removed.
|
|
|
|
Ensure all functions that are object methods have a first parameter named
|
|
'self', for consistency
|
|
|
|
Rename local vars that reference a Python object to '*obj', in order to
|
|
differentiate from liblvm handles
|
|
|
|
Fix a misspelled pv method name
|
|
|
|
Signed-off-by: Andy Grover <agrover@redhat.com>
|
|
---
|
|
python/liblvm.c | 152 +++++++++++++++++++++++++++++++++++++++-----------------
|
|
1 file changed, 106 insertions(+), 46 deletions(-)
|
|
|
|
diff --git a/python/liblvm.c b/python/liblvm.c
|
|
index 8a73ced..024d769 100644
|
|
--- a/python/liblvm.c
|
|
+++ b/python/liblvm.c
|
|
@@ -35,21 +35,25 @@ typedef struct {
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
lv_t lv; /* lv handle */
|
|
+ vgobject *parent_vgobj;
|
|
} lvobject;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
pv_t pv; /* pv handle */
|
|
+ vgobject *parent_vgobj;
|
|
} pvobject;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
lvseg_t lv_seg; /* lv segment handle */
|
|
+ lvobject *parent_lvobj;
|
|
} lvsegobject;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
pvseg_t pv_seg; /* pv segment handle */
|
|
+ pvobject *parent_pvobj;
|
|
} pvsegobject;
|
|
|
|
static PyTypeObject LibLVMvgType;
|
|
@@ -347,6 +351,7 @@ liblvm_vg_dealloc(vgobject *self)
|
|
|
|
#define VG_VALID(vgobject) \
|
|
do { \
|
|
+ LVM_VALID(); \
|
|
if (!vgobject->vg) { \
|
|
PyErr_SetString(PyExc_UnboundLocalError, "VG object invalid"); \
|
|
return NULL; \
|
|
@@ -785,18 +790,18 @@ liblvm_lvm_vg_set_extent_size(vgobject *self, PyObject *args)
|
|
}
|
|
|
|
static PyObject *
|
|
-liblvm_lvm_vg_list_lvs(vgobject *vg)
|
|
+liblvm_lvm_vg_list_lvs(vgobject *self)
|
|
{
|
|
struct dm_list *lvs;
|
|
struct lvm_lv_list *lvl;
|
|
PyObject * pytuple;
|
|
- lvobject * self;
|
|
+ lvobject * lvobj;
|
|
int i = 0;
|
|
|
|
- VG_VALID(vg);
|
|
+ VG_VALID(self);
|
|
|
|
/* unlike other LVM api calls, if there are no results, we get NULL */
|
|
- lvs = lvm_vg_list_lvs(vg->vg);
|
|
+ lvs = lvm_vg_list_lvs(self->vg);
|
|
if (!lvs)
|
|
return Py_BuildValue("()");
|
|
|
|
@@ -806,14 +811,17 @@ liblvm_lvm_vg_list_lvs(vgobject *vg)
|
|
|
|
dm_list_iterate_items(lvl, lvs) {
|
|
/* Create and initialize the object */
|
|
- self = PyObject_New(lvobject, &LibLVMlvType);
|
|
- if (!self) {
|
|
+ lvobj = PyObject_New(lvobject, &LibLVMlvType);
|
|
+ if (!lvobj) {
|
|
Py_DECREF(pytuple);
|
|
return NULL;
|
|
}
|
|
|
|
- self->lv = lvl->lv;
|
|
- PyTuple_SET_ITEM(pytuple, i, (PyObject *) self);
|
|
+ lvobj->parent_vgobj = self;
|
|
+ Py_INCREF(lvobj->parent_vgobj);
|
|
+
|
|
+ lvobj->lv = lvl->lv;
|
|
+ PyTuple_SET_ITEM(pytuple, i, (PyObject *) lvobj);
|
|
i++;
|
|
}
|
|
|
|
@@ -849,49 +857,53 @@ liblvm_lvm_vg_get_tags(vgobject *self)
|
|
}
|
|
|
|
static PyObject *
|
|
-liblvm_lvm_vg_create_lv_linear(vgobject *vg, PyObject *args)
|
|
+liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args)
|
|
{
|
|
const char *vgname;
|
|
uint64_t size;
|
|
- lvobject *self;
|
|
+ lvobject *lvobj;
|
|
|
|
- VG_VALID(vg);
|
|
+ VG_VALID(self);
|
|
|
|
if (!PyArg_ParseTuple(args, "sl", &vgname, &size)) {
|
|
return NULL;
|
|
}
|
|
|
|
- if ((self = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
|
|
+ if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
|
|
return NULL;
|
|
|
|
- if ((self->lv = lvm_vg_create_lv_linear(vg->vg, vgname, size))== NULL) {
|
|
+ if ((lvobj->lv = lvm_vg_create_lv_linear(self->vg, vgname, size)) == NULL) {
|
|
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
|
|
- Py_DECREF(self);
|
|
+ Py_DECREF(lvobj);
|
|
return NULL;
|
|
}
|
|
|
|
- return (PyObject *)self;
|
|
+ lvobj->parent_vgobj = self;
|
|
+ Py_INCREF(lvobj->parent_vgobj);
|
|
+
|
|
+ return (PyObject *)lvobj;
|
|
}
|
|
|
|
static void
|
|
liblvm_lv_dealloc(lvobject *self)
|
|
{
|
|
+ Py_DECREF(self->parent_vgobj);
|
|
PyObject_Del(self);
|
|
}
|
|
|
|
static PyObject *
|
|
-liblvm_lvm_vg_list_pvs(vgobject *vg)
|
|
+liblvm_lvm_vg_list_pvs(vgobject *self)
|
|
{
|
|
struct dm_list *pvs;
|
|
struct lvm_pv_list *pvl;
|
|
PyObject * pytuple;
|
|
- pvobject * self;
|
|
+ pvobject * pvobj;
|
|
int i = 0;
|
|
|
|
- VG_VALID(vg);
|
|
+ VG_VALID(self);
|
|
|
|
/* unlike other LVM api calls, if there are no results, we get NULL */
|
|
- pvs = lvm_vg_list_pvs(vg->vg);
|
|
+ pvs = lvm_vg_list_pvs(self->vg);
|
|
if (!pvs)
|
|
return Py_BuildValue("()");
|
|
|
|
@@ -901,14 +913,17 @@ liblvm_lvm_vg_list_pvs(vgobject *vg)
|
|
|
|
dm_list_iterate_items(pvl, pvs) {
|
|
/* Create and initialize the object */
|
|
- self = PyObject_New(pvobject, &LibLVMpvType);
|
|
- if (!self) {
|
|
+ pvobj = PyObject_New(pvobject, &LibLVMpvType);
|
|
+ if (!pvobj) {
|
|
Py_DECREF(pytuple);
|
|
return NULL;
|
|
}
|
|
|
|
- self->pv = pvl->pv;
|
|
- PyTuple_SET_ITEM(pytuple, i, (PyObject *) self);
|
|
+ pvobj->parent_vgobj = self;
|
|
+ Py_INCREF(pvobj->parent_vgobj);
|
|
+
|
|
+ pvobj->pv = pvl->pv;
|
|
+ PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvobj);
|
|
i++;
|
|
}
|
|
|
|
@@ -922,7 +937,7 @@ static PyObject *
|
|
liblvm_lvm_lv_from_N(vgobject *self, PyObject *arg, lv_fetch_by_N method)
|
|
{
|
|
const char *id;
|
|
- lvobject *rc;
|
|
+ lvobject *lvobj;
|
|
lv_t lv = NULL;
|
|
|
|
VG_VALID(self);
|
|
@@ -936,13 +951,16 @@ liblvm_lvm_lv_from_N(vgobject *self, PyObject *arg, lv_fetch_by_N method)
|
|
return NULL;
|
|
}
|
|
|
|
- rc = PyObject_New(lvobject, &LibLVMlvType);
|
|
- if (!rc) {
|
|
+ lvobj = PyObject_New(lvobject, &LibLVMlvType);
|
|
+ if (!lvobj) {
|
|
return NULL;
|
|
}
|
|
|
|
- rc->lv = lv;
|
|
- return (PyObject *)rc;
|
|
+ lvobj->parent_vgobj = self;
|
|
+ Py_INCREF(lvobj->parent_vgobj);
|
|
+
|
|
+ lvobj->lv = lv;
|
|
+ return (PyObject *)lvobj;
|
|
}
|
|
|
|
static PyObject *
|
|
@@ -980,6 +998,7 @@ liblvm_lvm_pv_from_N(vgobject *self, PyObject *arg, pv_fetch_by_N method)
|
|
return NULL;
|
|
}
|
|
|
|
+ Py_INCREF(self);
|
|
rc->pv = pv;
|
|
return (PyObject *)rc;
|
|
}
|
|
@@ -999,6 +1018,7 @@ liblvm_lvm_pv_from_uuid(vgobject *self, PyObject *arg)
|
|
static void
|
|
liblvm_pv_dealloc(pvobject *self)
|
|
{
|
|
+ Py_DECREF(self->parent_vgobj);
|
|
PyObject_Del(self);
|
|
}
|
|
|
|
@@ -1006,6 +1026,7 @@ liblvm_pv_dealloc(pvobject *self)
|
|
|
|
#define LV_VALID(lvobject) \
|
|
do { \
|
|
+ VG_VALID(lvobject->parent_vgobj); \
|
|
if (!lvobject->lv) { \
|
|
PyErr_SetString(PyExc_UnboundLocalError, "LV object invalid"); \
|
|
return NULL; \
|
|
@@ -1242,17 +1263,17 @@ liblvm_lvm_lv_resize(lvobject *self, PyObject *args)
|
|
}
|
|
|
|
static PyObject *
|
|
-liblvm_lvm_lv_list_lvsegs(lvobject *lv)
|
|
+liblvm_lvm_lv_list_lvsegs(lvobject *self)
|
|
{
|
|
struct dm_list *lvsegs;
|
|
lvseg_list_t *lvsegl;
|
|
PyObject * pytuple;
|
|
- lvsegobject *self;
|
|
+ lvsegobject *lvsegobj;
|
|
int i = 0;
|
|
|
|
- LV_VALID(lv);
|
|
+ LV_VALID(self);
|
|
|
|
- lvsegs = lvm_lv_list_lvsegs(lv->lv);
|
|
+ lvsegs = lvm_lv_list_lvsegs(self->lv);
|
|
if (!lvsegs) {
|
|
return Py_BuildValue("()");
|
|
}
|
|
@@ -1263,14 +1284,17 @@ liblvm_lvm_lv_list_lvsegs(lvobject *lv)
|
|
|
|
dm_list_iterate_items(lvsegl, lvsegs) {
|
|
/* Create and initialize the object */
|
|
- self = PyObject_New(lvsegobject, &LibLVMlvsegType);
|
|
- if (!self) {
|
|
+ lvsegobj = PyObject_New(lvsegobject, &LibLVMlvsegType);
|
|
+ if (!lvsegobj) {
|
|
Py_DECREF(pytuple);
|
|
return NULL;
|
|
}
|
|
|
|
- self->lv_seg = lvsegl->lvseg;
|
|
- PyTuple_SET_ITEM(pytuple, i, (PyObject *) self);
|
|
+ lvsegobj->parent_lvobj = self;
|
|
+ Py_INCREF(lvsegobj->parent_lvobj);
|
|
+
|
|
+ lvsegobj->lv_seg = lvsegl->lvseg;
|
|
+ PyTuple_SET_ITEM(pytuple, i, (PyObject *) lvsegobj);
|
|
i++;
|
|
}
|
|
|
|
@@ -1281,7 +1305,8 @@ liblvm_lvm_lv_list_lvsegs(lvobject *lv)
|
|
|
|
#define PV_VALID(pvobject) \
|
|
do { \
|
|
- if (!pvobject->pv || !libh) { \
|
|
+ VG_VALID(pvobject->parent_vgobj); \
|
|
+ if (!pvobject->pv) { \
|
|
PyErr_SetString(PyExc_UnboundLocalError, "PV object invalid"); \
|
|
return NULL; \
|
|
} \
|
|
@@ -1290,18 +1315,24 @@ liblvm_lvm_lv_list_lvsegs(lvobject *lv)
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_name(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("s", lvm_pv_get_name(self->pv));
|
|
}
|
|
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_uuid(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("s", lvm_pv_get_uuid(self->pv));
|
|
}
|
|
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_mda_count(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("l", lvm_pv_get_mda_count(self->pv));
|
|
}
|
|
|
|
@@ -1323,18 +1354,24 @@ liblvm_lvm_pv_get_property(pvobject *self, PyObject *args)
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_dev_size(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("l", lvm_pv_get_dev_size(self->pv));
|
|
}
|
|
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_size(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("l", lvm_pv_get_size(self->pv));
|
|
}
|
|
|
|
static PyObject *
|
|
liblvm_lvm_pv_get_free(pvobject *self)
|
|
{
|
|
+ PV_VALID(self);
|
|
+
|
|
return Py_BuildValue("l", lvm_pv_get_free(self->pv));
|
|
}
|
|
|
|
@@ -1344,6 +1381,8 @@ liblvm_lvm_pv_resize(pvobject *self, PyObject *args)
|
|
uint64_t new_size;
|
|
int rval;
|
|
|
|
+ PV_VALID(self);
|
|
+
|
|
if (!PyArg_ParseTuple(args, "l", &new_size)) {
|
|
return NULL;
|
|
}
|
|
@@ -1358,17 +1397,17 @@ liblvm_lvm_pv_resize(pvobject *self, PyObject *args)
|
|
}
|
|
|
|
static PyObject *
|
|
-liblvm_lvm_lv_list_pvsegs(pvobject *pv)
|
|
+liblvm_lvm_pv_list_pvsegs(pvobject *self)
|
|
{
|
|
struct dm_list *pvsegs;
|
|
pvseg_list_t *pvsegl;
|
|
PyObject *pytuple;
|
|
- pvsegobject *self;
|
|
+ pvsegobject *pvsegobj;
|
|
int i = 0;
|
|
|
|
- PV_VALID(pv);
|
|
+ PV_VALID(self);
|
|
|
|
- pvsegs = lvm_pv_list_pvsegs(pv->pv);
|
|
+ pvsegs = lvm_pv_list_pvsegs(self->pv);
|
|
if (!pvsegs) {
|
|
return Py_BuildValue("()");
|
|
}
|
|
@@ -1379,14 +1418,17 @@ liblvm_lvm_lv_list_pvsegs(pvobject *pv)
|
|
|
|
dm_list_iterate_items(pvsegl, pvsegs) {
|
|
/* Create and initialize the object */
|
|
- self = PyObject_New(pvsegobject, &LibLVMpvsegType);
|
|
- if (!self) {
|
|
+ pvsegobj = PyObject_New(pvsegobject, &LibLVMpvsegType);
|
|
+ if (!pvsegobj) {
|
|
Py_DECREF(pytuple);
|
|
return NULL;
|
|
}
|
|
|
|
- self->pv_seg = pvsegl->pvseg;
|
|
- PyTuple_SET_ITEM(pytuple, i, (PyObject *) self);
|
|
+ pvsegobj->parent_pvobj = self;
|
|
+ Py_INCREF(pvsegobj->parent_pvobj);
|
|
+
|
|
+ pvsegobj->pv_seg = pvsegl->pvseg;
|
|
+ PyTuple_SET_ITEM(pytuple, i, (PyObject *) pvsegobj);
|
|
i++;
|
|
}
|
|
|
|
@@ -1395,9 +1437,16 @@ liblvm_lvm_lv_list_pvsegs(pvobject *pv)
|
|
|
|
/* LV seg methods */
|
|
|
|
+/*
|
|
+ * No way to close/destroy an lvseg, just need to make sure parents are
|
|
+ * still good
|
|
+ */
|
|
+#define LVSEG_VALID(lvsegobject) LV_VALID(lvsegobject->parent_lvobj)
|
|
+
|
|
static void
|
|
liblvm_lvseg_dealloc(lvsegobject *self)
|
|
{
|
|
+ Py_DECREF(self->parent_lvobj);
|
|
PyObject_Del(self);
|
|
}
|
|
|
|
@@ -1407,6 +1456,8 @@ liblvm_lvm_lvseg_get_property(lvsegobject *self, PyObject *args)
|
|
const char *name;
|
|
struct lvm_property_value prop_value;
|
|
|
|
+ LVSEG_VALID(self);
|
|
+
|
|
if (!PyArg_ParseTuple(args, "s", &name))
|
|
return NULL;
|
|
|
|
@@ -1416,9 +1467,16 @@ liblvm_lvm_lvseg_get_property(lvsegobject *self, PyObject *args)
|
|
|
|
/* PV seg methods */
|
|
|
|
+/*
|
|
+ * No way to close/destroy a pvseg, just need to make sure parents are
|
|
+ * still good
|
|
+ */
|
|
+#define PVSEG_VALID(pvsegobject) PV_VALID(pvsegobject->parent_pvobj)
|
|
+
|
|
static void
|
|
liblvm_pvseg_dealloc(pvsegobject *self)
|
|
{
|
|
+ Py_DECREF(self->parent_pvobj);
|
|
PyObject_Del(self);
|
|
}
|
|
|
|
@@ -1428,6 +1486,8 @@ liblvm_lvm_pvseg_get_property(pvsegobject *self, PyObject *args)
|
|
const char *name;
|
|
struct lvm_property_value prop_value;
|
|
|
|
+ PVSEG_VALID(self);
|
|
+
|
|
if (!PyArg_ParseTuple(args, "s", &name))
|
|
return NULL;
|
|
|
|
@@ -1522,7 +1582,7 @@ static PyMethodDef liblvm_pv_methods[] = {
|
|
{ "getDevSize", (PyCFunction)liblvm_lvm_pv_get_dev_size, METH_NOARGS },
|
|
{ "getFree", (PyCFunction)liblvm_lvm_pv_get_free, METH_NOARGS },
|
|
{ "resize", (PyCFunction)liblvm_lvm_pv_resize, METH_VARARGS },
|
|
- { "listPVsegs", (PyCFunction)liblvm_lvm_lv_list_pvsegs, METH_NOARGS },
|
|
+ { "listPVsegs", (PyCFunction)liblvm_lvm_pv_list_pvsegs, METH_NOARGS },
|
|
{ NULL, NULL} /* sentinel */
|
|
};
|
|
|