yaffs: Clean up as per Ryan's comments
[yaffs2.git] / yaffs_allocator.c
index 1dd0c27b91682b8cd274d8d4a67d9ddf019566d2..695c2541153e937580bbf2c87b72bc704425c7ba 100644 (file)
 #include "yaffs_trace.h"
 #include "yportenv.h"
 
+/*
+ * 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;
@@ -34,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;
@@ -68,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 {
+       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)
@@ -183,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 {
+       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)
@@ -210,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;
 }
@@ -249,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;
 
@@ -271,6 +287,7 @@ 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) {
@@ -279,13 +296,13 @@ struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
        }
 
        /* 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--;
        }
 
@@ -297,42 +314,44 @@ void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
 
        struct yaffs_allocator *allocator = dev->allocator;
 
-       if (!allocator)
+       if (!allocator) {
                BUG();
-       else {
-               /* Link into the free list. */
-               obj->siblings.next = (struct list_head *)(allocator->free_objs);
-               allocator->free_objs = obj;
-               allocator->n_free_objects++;
+               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 {
+       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 {
+       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);
        }
 }