yaffs: Clean up as per Ryan's comments
[yaffs2.git] / yaffs_allocator.c
index 9af15c7..695c254 100644 (file)
 #include "yaffs_trace.h"
 #include "yportenv.h"
 
-#ifdef CONFIG_YAFFS_KMALLOC_ALLOCATOR
-
-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 (struct yaffs_tnode *)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 (struct yaffs_obj *)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;
@@ -81,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;
@@ -89,14 +55,12 @@ struct yaffs_allocator {
 
 static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
 {
-
        struct yaffs_allocator *allocator =
            (struct yaffs_allocator *)dev->allocator;
-
        struct yaffs_tnode_list *tmp;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return;
        }
 
@@ -106,7 +70,6 @@ static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
                kfree(allocator->alloc_tnode_list->tnodes);
                kfree(allocator->alloc_tnode_list);
                allocator->alloc_tnode_list = tmp;
-
        }
 
        allocator->free_tnodes = NULL;
@@ -118,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)
@@ -140,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;
        }
 
@@ -148,13 +112,12 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
                return YAFFS_OK;
 
        /* make these things */
-
        new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);
        mem = (u8 *) new_tnodes;
 
        if (!new_tnodes) {
-               T(YAFFS_TRACE_ERROR,
-                 (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
+               yaffs_trace(YAFFS_TRACE_ERROR,
+                       "yaffs: Could not allocate Tnodes");
                return YAFFS_FAIL;
        }
 
@@ -176,12 +139,10 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
         * NB If we can't add this to the management list it isn't fatal
         * but it just means we can't free this bunch of tnodes later.
         */
-
        tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
        if (!tnl) {
-               T(YAFFS_TRACE_ERROR,
-                 (TSTR
-                  ("yaffs: Could not add tnodes to management list" TENDSTR)));
+               yaffs_trace(YAFFS_TRACE_ERROR,
+                       "Could not add tnodes to management list");
                return YAFFS_FAIL;
        } else {
                tnl->tnodes = new_tnodes;
@@ -189,7 +150,7 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
                allocator->alloc_tnode_list = tnl;
        }
 
-       T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
+       yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added");
 
        return YAFFS_OK;
 }
@@ -201,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;
        }
 
@@ -224,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;
        }
 
@@ -236,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)
@@ -255,7 +223,7 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
        struct yaffs_obj_list *tmp;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return;
        }
 
@@ -263,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,13 +242,12 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
 static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
 {
        struct yaffs_allocator *allocator = dev->allocator;
-
        int i;
        struct yaffs_obj *new_objs;
        struct yaffs_obj_list *list;
 
        if (!allocator) {
-               YBUG();
+               BUG();
                return YAFFS_FAIL;
        }
 
@@ -293,27 +259,19 @@ static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
        list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS);
 
        if (!new_objs || !list) {
-               if (new_objs) {
-                       kfree(new_objs);
-                       new_objs = NULL;
-               }
-               if (list) {
-                       kfree(list);
-                       list = NULL;
-               }
-               T(YAFFS_TRACE_ALLOCATE,
-                 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
+               kfree(new_objs);
+               new_objs = NULL;
+               kfree(list);
+               list = NULL;
+               yaffs_trace(YAFFS_TRACE_ALLOCATE,
+                       "Could not allocate more objects");
                return YAFFS_FAIL;
        }
 
        /* 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;
 
@@ -329,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--;
        }
 
@@ -355,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