From 2970c7cd9e2ac676f15fc995af724250f80ed6f5 Mon Sep 17 00:00:00 2001
From: Federico Vaga <federico.vaga@gmail.com>
Date: Thu, 2 Feb 2012 20:45:04 +0100
Subject: [PATCH] core: zio attribute (un)registration bugfix

Signed-off-by: Federico Vaga <federico.vaga@gmail.com>
---
 zio-sys.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/zio-sys.c b/zio-sys.c
index ca524b1..7f74cd3 100644
--- a/zio-sys.c
+++ b/zio-sys.c
@@ -950,7 +950,7 @@ static int __check_attr(struct attribute *attr,
 static int zattr_set_create(struct zio_obj_head *head,
 			    const struct zio_sysfs_operations *s_op)
 {
-	int n_attr, i, j, attr_count = 0, err;
+	int n_attr, i, j, attr_count = 0, err = 0;
 	struct zio_attribute_set *zattr_set;
 	struct attribute_group *group;
 
@@ -1006,7 +1006,10 @@ ext:
 		zattr_set->ext_zattr[j].flags |= ZATTR_TYPE_EXT;
 	}
 out:
-	return sysfs_create_group(&head->kobj, group);
+	err = sysfs_create_group(&head->kobj, group);
+	if (err)
+		kfree(group->attrs);
+	return err;
 }
 /* Remove an existent set of attributes */
 static void zattr_set_remove(struct zio_obj_head *head)
@@ -1061,6 +1064,7 @@ static void __bi_destroy(struct zio_buffer_type *zbuf, struct zio_bi *bi)
 {
 	pr_debug("%s\n", __func__);
 	zbuf->b_op->destroy(bi);
+	__zattr_set_free(&bi->zattr_set);
 }
 static int __bi_register(struct zio_buffer_type *zbuf,
 			 struct zio_channel *chan,
@@ -1090,7 +1094,6 @@ static int __bi_register(struct zio_buffer_type *zbuf,
 	return 0;
 
 out_sysfs:
-	__zattr_set_free(&bi->zattr_set);
 	kobject_del(&bi->head.kobj);
 out_kobj:
 	kobject_put(&bi->head.kobj);
@@ -1105,7 +1108,6 @@ static void __bi_unregister(struct zio_buffer_type *zbuf, struct zio_bi *bi)
 	spin_unlock(&zbuf->lock);
 	/* Remove from sysfs */
 	zattr_set_remove(&bi->head);
-	__zattr_set_free(&bi->zattr_set);
 	kobject_del(&bi->head.kobj);
 	kobject_put(&bi->head.kobj);
 }
@@ -1158,6 +1160,7 @@ static void __ti_destroy(struct zio_trigger_type *trig, struct zio_ti *ti)
 {
 	pr_debug("%s\n", __func__);
 	trig->t_op->destroy(ti);
+	__zattr_set_free(&ti->zattr_set);
 	zio_free_control(ti->current_ctrl);
 }
 static int __ti_register(struct zio_trigger_type *trig, struct zio_cset *cset,
@@ -1186,7 +1189,6 @@ static int __ti_register(struct zio_trigger_type *trig, struct zio_cset *cset,
 	return 0;
 
 out_sysfs:
-	__zattr_set_free(&ti->zattr_set);
 	kobject_del(&ti->head.kobj);
 out_kobj:
 	kobject_put(&ti->head.kobj);
@@ -1201,7 +1203,6 @@ static void __ti_unregister(struct zio_trigger_type *trig, struct zio_ti *ti)
 	spin_unlock(&trig->lock);
 	/* Remove from sysfs */
 	zattr_set_remove(&ti->head);
-	__zattr_set_free(&ti->zattr_set);
 	kobject_del(&ti->head.kobj);
 	kobject_put(&ti->head.kobj);
 }
@@ -1324,7 +1325,7 @@ static struct zio_channel *cset_alloc_chan(struct zio_cset *cset)
 	for (i = 0; i < cset->n_chan; ++i) {
 		memcpy(cset->chan + i, cset->chan_template,
 		       sizeof(struct zio_channel));
-		__zattr_set_copy(&cset->chan->zattr_set,
+		__zattr_set_copy(&cset->chan[i].zattr_set,
 				 &cset->chan_template->zattr_set);
 	}
 
@@ -1332,10 +1333,16 @@ static struct zio_channel *cset_alloc_chan(struct zio_cset *cset)
 }
 static inline void cset_free_chan(struct zio_cset *cset)
 {
+	int i;
+
 	pr_debug("%s:%d\n", __func__, __LINE__);
 	/* Only allocated channels need to be freed */
-	if (cset->flags & ZCSET_CHAN_ALLOC)
-		kfree(cset->chan);
+	if (!(cset->flags & ZCSET_CHAN_ALLOC))
+		return;
+	if(cset->chan_template)
+		for (i = 0; i < cset->n_chan; ++i)
+			__zattr_set_free(&cset->chan[i].zattr_set);
+	kfree(cset->chan);
 }
 
 static int cset_register(struct zio_cset *cset)
@@ -1488,6 +1495,8 @@ out_sysfs:
 out_add:
 	/* we must _put even if it returned error */
 	kobject_put(&cset->head.kobj);
+	/* Release a group of minors */
+	__zio_minorbase_put(cset);
 	return err;
 }
 
-- 
GitLab