[lvm-devel] master - python-lvm: Implement proper refcounting for parent objects

Andy Grover grover at fedoraproject.org
Wed Oct 17 19:57:20 UTC 2012


Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0e47639a44e1630250ea10643f5a440281edfdce
Commit:        0e47639a44e1630250ea10643f5a440281edfdce
Parent:        bf2741376d47411994d4065863acab8e405ff5c7
Author:        Andy Grover <agrover at redhat.com>
AuthorDate:    Wed Oct 17 12:55:25 2012 -0700
Committer:     Andy Grover <agrover at redhat.com>
CommitterDate: 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 at redhat.com>
---
 python/liblvm.c |  152 ++++++++++++++++++++++++++++++++++++++-----------------
 1 files 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 */
 };
 




More information about the lvm-devel mailing list