UBI: create ubi_wl_entry slab on initialization

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue Jan 8 02:59:02 EST 2008


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=06b68ba15671f32a3aa3bbddf04b0d2dd7fbf902
Commit:     06b68ba15671f32a3aa3bbddf04b0d2dd7fbf902
Parent:     3a8d4642861fb69b62401949e490c0bcb19ceb40
Author:     Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
AuthorDate: Sun Dec 16 12:49:01 2007 +0200
Committer:  Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
CommitDate: Wed Dec 26 19:15:14 2007 +0200

    UBI: create ubi_wl_entry slab on initialization
    
    Similarly to ltree_entry_slab, it makes more sense to create
    and destroy ubi_wl_entry slab on module initialization/exit.
    
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/ubi/build.c |   13 ++++++++++
 drivers/mtd/ubi/ubi.h   |   17 +++++++++++++
 drivers/mtd/ubi/wl.c    |   58 +++++++++++-----------------------------------
 3 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 44c8521..7f6820b 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -70,6 +70,10 @@ struct class *ubi_class;
 /* Slab cache for lock-tree entries */
 struct kmem_cache *ubi_ltree_slab;
 
+/* Slab cache for wear-leveling entries */
+struct kmem_cache *ubi_wl_entry_slab;
+
+
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
 static ssize_t ubi_version_show(struct class *class, char *buf)
 {
@@ -732,6 +736,12 @@ static int __init ubi_init(void)
 	if (!ubi_ltree_slab)
 		goto out_version;
 
+	ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
+						sizeof(struct ubi_wl_entry),
+						0, 0, NULL);
+	if (!ubi_wl_entry_slab)
+		goto out_ltree;
+
 	/* Attach MTD devices */
 	for (i = 0; i < mtd_devs; i++) {
 		struct mtd_dev_param *p = &mtd_dev_param[i];
@@ -747,6 +757,8 @@ static int __init ubi_init(void)
 out_detach:
 	for (k = 0; k < i; k++)
 		detach_mtd_dev(ubi_devices[k]);
+	kmem_cache_destroy(ubi_wl_entry_slab);
+out_ltree:
 	kmem_cache_destroy(ubi_ltree_slab);
 out_version:
 	class_remove_file(ubi_class, &ubi_version);
@@ -762,6 +774,7 @@ static void __exit ubi_exit(void)
 
 	for (i = 0; i < n; i++)
 		detach_mtd_dev(ubi_devices[i]);
+	kmem_cache_destroy(ubi_wl_entry_slab);
 	kmem_cache_destroy(ubi_ltree_slab);
 	class_remove_file(ubi_class, &ubi_version);
 	class_destroy(ubi_class);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 0f2ea81..b7c9317 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -98,6 +98,22 @@ extern int ubi_devices_cnt;
 extern struct ubi_device *ubi_devices[];
 
 /**
+ * struct ubi_wl_entry - wear-leveling entry.
+ * @rb: link in the corresponding RB-tree
+ * @ec: erase counter
+ * @pnum: physical eraseblock number
+ *
+ * This data structure is used in the WL unit. Each physical eraseblock has a
+ * corresponding &struct wl_entry object which may be kept in different
+ * RB-trees. See WL unit for details.
+ */
+struct ubi_wl_entry {
+	struct rb_node rb;
+	int ec;
+	int pnum;
+};
+
+/**
  * struct ubi_ltree_entry - an entry in the lock tree.
  * @rb: links RB-tree nodes
  * @vol_id: volume ID of the locked logical eraseblock
@@ -382,6 +398,7 @@ struct ubi_device {
 };
 
 extern struct kmem_cache *ubi_ltree_slab;
+extern struct kmem_cache *ubi_wl_entry_slab;
 extern struct file_operations ubi_cdev_operations;
 extern struct file_operations ubi_vol_cdev_operations;
 extern struct class *ubi_class;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 6330c8c..a405d40 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -117,21 +117,6 @@
 #define WL_MAX_FAILURES 32
 
 /**
- * struct ubi_wl_entry - wear-leveling entry.
- * @rb: link in the corresponding RB-tree
- * @ec: erase counter
- * @pnum: physical eraseblock number
- *
- * Each physical eraseblock has a corresponding &struct wl_entry object which
- * may be kept in different RB-trees.
- */
-struct ubi_wl_entry {
-	struct rb_node rb;
-	int ec;
-	int pnum;
-};
-
-/**
  * struct ubi_wl_prot_entry - PEB protection entry.
  * @rb_pnum: link in the @wl->prot.pnum RB-tree
  * @rb_aec: link in the @wl->prot.aec RB-tree
@@ -216,9 +201,6 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 #define paranoid_check_in_wl_tree(e, root)
 #endif
 
-/* Slab cache for wear-leveling entries */
-static struct kmem_cache *wl_entries_slab;
-
 /**
  * wl_tree_add - add a wear-leveling entry to a WL RB-tree.
  * @e: the wear-leveling entry to add
@@ -878,14 +860,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 		dbg_wl("PEB %d was put meanwhile, erase", e2->pnum);
 		err = schedule_erase(ubi, e2, 0);
 		if (err) {
-			kmem_cache_free(wl_entries_slab, e2);
+			kmem_cache_free(ubi_wl_entry_slab, e2);
 			ubi_ro_mode(ubi);
 		}
 	}
 
 	err = schedule_erase(ubi, e1, 0);
 	if (err) {
-		kmem_cache_free(wl_entries_slab, e1);
+		kmem_cache_free(ubi_wl_entry_slab, e1);
 		ubi_ro_mode(ubi);
 	}
 
@@ -920,14 +902,14 @@ error:
 		dbg_wl("PEB %d was put meanwhile, erase", e1->pnum);
 		err = schedule_erase(ubi, e1, 0);
 		if (err) {
-			kmem_cache_free(wl_entries_slab, e1);
+			kmem_cache_free(ubi_wl_entry_slab, e1);
 			ubi_ro_mode(ubi);
 		}
 	}
 
 	err = schedule_erase(ubi, e2, 0);
 	if (err) {
-		kmem_cache_free(wl_entries_slab, e2);
+		kmem_cache_free(ubi_wl_entry_slab, e2);
 		ubi_ro_mode(ubi);
 	}
 
@@ -1020,7 +1002,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
 	if (cancel) {
 		dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
 		kfree(wl_wrk);
-		kmem_cache_free(wl_entries_slab, e);
+		kmem_cache_free(ubi_wl_entry_slab, e);
 		return 0;
 	}
 
@@ -1049,7 +1031,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
 
 	ubi_err("failed to erase PEB %d, error %d", pnum, err);
 	kfree(wl_wrk);
-	kmem_cache_free(wl_entries_slab, e);
+	kmem_cache_free(ubi_wl_entry_slab, e);
 
 	if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
 	    err == -EBUSY) {
@@ -1294,7 +1276,7 @@ static void tree_destroy(struct rb_root *root)
 					rb->rb_right = NULL;
 			}
 
-			kmem_cache_free(wl_entries_slab, e);
+			kmem_cache_free(ubi_wl_entry_slab, e);
 		}
 	}
 }
@@ -1407,14 +1389,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 		return err;
 	}
 
-	if (ubi_devices_cnt == 0) {
-		wl_entries_slab = kmem_cache_create("ubi_wl_entry_slab",
-						    sizeof(struct ubi_wl_entry),
-						    0, 0, NULL);
-		if (!wl_entries_slab)
-			return -ENOMEM;
-	}
-
 	err = -ENOMEM;
 	ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL);
 	if (!ubi->lookuptbl)
@@ -1423,7 +1397,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 	list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
 		cond_resched();
 
-		e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL);
+		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
 		if (!e)
 			goto out_free;
 
@@ -1431,7 +1405,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 		e->ec = seb->ec;
 		ubi->lookuptbl[e->pnum] = e;
 		if (schedule_erase(ubi, e, 0)) {
-			kmem_cache_free(wl_entries_slab, e);
+			kmem_cache_free(ubi_wl_entry_slab, e);
 			goto out_free;
 		}
 	}
@@ -1439,7 +1413,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 	list_for_each_entry(seb, &si->free, u.list) {
 		cond_resched();
 
-		e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL);
+		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
 		if (!e)
 			goto out_free;
 
@@ -1453,7 +1427,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 	list_for_each_entry(seb, &si->corr, u.list) {
 		cond_resched();
 
-		e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL);
+		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
 		if (!e)
 			goto out_free;
 
@@ -1461,7 +1435,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 		e->ec = seb->ec;
 		ubi->lookuptbl[e->pnum] = e;
 		if (schedule_erase(ubi, e, 0)) {
-			kmem_cache_free(wl_entries_slab, e);
+			kmem_cache_free(ubi_wl_entry_slab, e);
 			goto out_free;
 		}
 	}
@@ -1470,7 +1444,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
 			cond_resched();
 
-			e = kmem_cache_alloc(wl_entries_slab, GFP_KERNEL);
+			e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
 			if (!e)
 				goto out_free;
 
@@ -1510,8 +1484,6 @@ out_free:
 	tree_destroy(&ubi->free);
 	tree_destroy(&ubi->scrub);
 	kfree(ubi->lookuptbl);
-	if (ubi_devices_cnt == 0)
-		kmem_cache_destroy(wl_entries_slab);
 	return err;
 }
 
@@ -1541,7 +1513,7 @@ static void protection_trees_destroy(struct ubi_device *ubi)
 					rb->rb_right = NULL;
 			}
 
-			kmem_cache_free(wl_entries_slab, pe->e);
+			kmem_cache_free(ubi_wl_entry_slab, pe->e);
 			kfree(pe);
 		}
 	}
@@ -1565,8 +1537,6 @@ void ubi_wl_close(struct ubi_device *ubi)
 	tree_destroy(&ubi->free);
 	tree_destroy(&ubi->scrub);
 	kfree(ubi->lookuptbl);
-	if (ubi_devices_cnt == 1)
-		kmem_cache_destroy(wl_entries_slab);
 }
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID



More information about the linux-mtd-cvs mailing list