yaffs: Clean up as per Ryan's comments
[yaffs2.git] / yaffs_allocator.c
index 59cce04a0ea8b2b57ce98047aab864f03b5ed33e..695c2541153e937580bbf2c87b72bc704425c7ba 100644 (file)
 #include "yaffs_trace.h"
 #include "yportenv.h"
 
-#ifdef CONFIG_YAFFS_KMALLOC_ALLOCATOR
-/* This is an alternative debug allocator. Don't use for production code. */
-
-void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
-{
-       dev = dev;
-}
-
-void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
-{
-       dev = dev;
-}
-
-struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
-{
-       return kmalloc(dev->tnode_size, GFP_NOFS);
-}
-
-void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
-{
-       dev = dev;
-       kfree(tn);
-}
-
-void yaffs_init_raw_objs(struct yaffs_dev *dev)
-{
-       dev = dev;
-}
-
-void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
-{
-       dev = dev;
-}
-
-struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
-{
-       dev = dev;
-       return kmalloc(sizeof(struct yaffs_obj));
-}
-
-void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
-{
-
-       dev = dev;
-       kfree(obj);
-}
-
-#else
+/*
+ * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks
+ * of approx 100 objects that are themn allocated singly.
+ * This is basically a simplified slab allocator.
+ *
+ * We don't use the Linux slab allocator because slab does not allow
+ * us to dump all the objects in one hit when we do a umount and tear
+ * down  all the tnodes and objects. slab requires that we first free
+ * the individual objects.
+ *
+ * Once yaffs has been mainlined I shall try to motivate for a change
+ * to slab to provide the extra features we need here.
+ */
 
 struct yaffs_tnode_list {
        struct yaffs_tnode_list *next;
@@ -82,7 +47,7 @@ struct yaffs_allocator {
        struct yaffs_tnode_list *alloc_tnode_list;
 
        int n_obj_created;
-       struct yaffs_obj *free_objs;
+       struct list_head free_objs;
        int n_free_objects;
 
        struct yaffs_obj_list *allocated_obj_list;
@@ -95,7 +60,7 @@ static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
        struct yaffs_tnode_list *tmp;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return;
        }
 
@@ -116,14 +81,15 @@ static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
 {
        struct yaffs_allocator *allocator = dev->allocator;
 
-       if (allocator) {
-               allocator->alloc_tnode_list = NULL;
-               allocator->free_tnodes = NULL;
-               allocator->n_free_tnodes = 0;
-               allocator->n_tnodes_created = 0;
-       } else {
-               YBUG();
+       if (!allocator) {
+               BUG();
+               return;
        }
+
+       allocator->alloc_tnode_list = NULL;
+       allocator->free_tnodes = NULL;
+       allocator->n_free_tnodes = 0;
+       allocator->n_tnodes_created = 0;
 }
 
 static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
@@ -138,7 +104,7 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
        struct yaffs_tnode_list *tnl;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return YAFFS_FAIL;
        }
 
@@ -196,7 +162,7 @@ struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
        struct yaffs_tnode *tn = NULL;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return NULL;
        }
 
@@ -219,7 +185,7 @@ void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
        struct yaffs_allocator *allocator = dev->allocator;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return;
        }
 
@@ -231,17 +197,24 @@ void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
        dev->checkpoint_blocks_required = 0;    /* force recalculation */
 }
 
+/*--------------- yaffs_obj alloaction ------------------------
+ *
+ * Free yaffs_objs are stored in a list using obj->siblings.
+ * The blocks of allocated objects are stored in a linked list.
+ */
+
 static void yaffs_init_raw_objs(struct yaffs_dev *dev)
 {
        struct yaffs_allocator *allocator = dev->allocator;
 
-       if (allocator) {
-               allocator->allocated_obj_list = NULL;
-               allocator->free_objs = NULL;
-               allocator->n_free_objects = 0;
-       } else {
-               YBUG();
+       if (!allocator) {
+               BUG();
+               return;
        }
+
+       allocator->allocated_obj_list = NULL;
+       INIT_LIST_HEAD(&allocator->free_objs);
+       allocator->n_free_objects = 0;
 }
 
 static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
@@ -250,7 +223,7 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
        struct yaffs_obj_list *tmp;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return;
        }
 
@@ -258,11 +231,10 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
                tmp = allocator->allocated_obj_list->next;
                kfree(allocator->allocated_obj_list->objects);
                kfree(allocator->allocated_obj_list);
-
                allocator->allocated_obj_list = tmp;
        }
 
-       allocator->free_objs = NULL;
+       INIT_LIST_HEAD(&allocator->free_objs);
        allocator->n_free_objects = 0;
        allocator->n_obj_created = 0;
 }
@@ -275,7 +247,7 @@ static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
        struct yaffs_obj_list *list;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return YAFFS_FAIL;
        }
 
@@ -297,13 +269,9 @@ static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
        }
 
        /* Hook them into the free list */
-       for (i = 0; i < n_obj - 1; i++) {
-               new_objs[i].siblings.next =
-                   (struct list_head *)(&new_objs[i + 1]);
-       }
+       for (i = 0; i < n_obj; i++)
+               list_add(&new_objs[i].siblings, &allocator->free_objs);
 
-       new_objs[n_obj - 1].siblings.next = (void *)allocator->free_objs;
-       allocator->free_objs = new_objs;
        allocator->n_free_objects += n_obj;
        allocator->n_obj_created += n_obj;
 
@@ -319,21 +287,22 @@ static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
 struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
 {
        struct yaffs_obj *obj = NULL;
+       struct list_head *lh;
        struct yaffs_allocator *allocator = dev->allocator;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return obj;
        }
 
        /* If there are none left make more */
-       if (!allocator->free_objs)
+       if (list_empty(&allocator->free_objs))
                yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
 
-       if (allocator->free_objs) {
-               obj = allocator->free_objs;
-               allocator->free_objs =
-                   (struct yaffs_obj *)(allocator->free_objs->siblings.next);
+       if (!list_empty(&allocator->free_objs)) {
+               lh = allocator->free_objs.next;
+               obj = list_entry(lh, struct yaffs_obj, siblings);
+               list_del_init(lh);
                allocator->n_free_objects--;
        }
 
@@ -345,43 +314,44 @@ void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
 
        struct yaffs_allocator *allocator = dev->allocator;
 
-       if (!allocator)
-               YBUG();
-       else {
-               /* Link into the free list. */
-               obj->siblings.next = (struct list_head *)(allocator->free_objs);
-               allocator->free_objs = obj;
-               allocator->n_free_objects++;
+       if (!allocator) {
+               BUG();
+               return;
        }
+
+       /* Link into the free list. */
+       list_add(&obj->siblings, &allocator->free_objs);
+       allocator->n_free_objects++;
 }
 
 void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
 {
-       if (dev->allocator) {
-               yaffs_deinit_raw_tnodes(dev);
-               yaffs_deinit_raw_objs(dev);
 
-               kfree(dev->allocator);
-               dev->allocator = NULL;
-       } else {
-               YBUG();
+       if (!dev->allocator) {
+               BUG();
+               return;
        }
+
+       yaffs_deinit_raw_tnodes(dev);
+       yaffs_deinit_raw_objs(dev);
+       kfree(dev->allocator);
+       dev->allocator = NULL;
 }
 
 void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
 {
        struct yaffs_allocator *allocator;
 
-       if (!dev->allocator) {
-               allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
-               if (allocator) {
-                       dev->allocator = allocator;
-                       yaffs_init_raw_tnodes(dev);
-                       yaffs_init_raw_objs(dev);
-               }
-       } else {
-               YBUG();
+       if (dev->allocator) {
+               BUG();
+               return;
+       }
+
+       allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
+       if (allocator) {
+               dev->allocator = allocator;
+               yaffs_init_raw_tnodes(dev);
+               yaffs_init_raw_objs(dev);
        }
 }
 
-#endif