yaffs: Refactor allocator
authorCharles Manning <cdhmanning@gmail.com>
Tue, 8 Jun 2010 23:04:34 +0000 (11:04 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Sun, 13 Jun 2010 23:42:09 +0000 (11:42 +1200)
Refactoring the allocator allows alternate allocators to be switched in more easily

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
14 files changed:
Makefile
Makefile.kernel
direct/Makefile
direct/python/Makefile
direct/tests/Makefile
direct/yaffsfs.c
yaffs_allocator.c [new file with mode: 0644]
yaffs_allocator.h [new file with mode: 0644]
yaffs_fs.c
yaffs_guts.c
yaffs_guts.h
yaffs_linux.h
yaffs_linux_allocator.c [new file with mode: 0644]
yaffs_qsort.h

index 01195115b38acad73a5d4897402ddc6bb767b73b..cf2bcbbc51d049672c46d77d8ce5967c14d00f88 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,10 +21,11 @@ ifneq ($(KERNELRELEASE),)
        yaffs2-objs := yaffs_mtdif.o yaffs_mtdif2.o
        yaffs2-objs += yaffs_mtdif1.o yaffs_packedtags1.o
        yaffs2-objs += yaffs_ecc.o yaffs_fs.o yaffs_guts.o
-       yaffs2-objs += yaffs_packedtags2.o yaffs_qsort.o
+       yaffs2-objs += yaffs_packedtags2.o
        yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o
        yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o
        yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o
+       yaffs2-objs += yaffs_allocator.o
 
 else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
index 9c1e5990220eb34eec5de418d4a9328f1ec6fa1c..6f64b8d21ea4f8f9733eaae7962abef20e4e97ff 100644 (file)
@@ -9,3 +9,4 @@ yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
 yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
 yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
 yaffs-y += yaffs_nameval.o
+yaffs-y += yaffs_linux_allocator.o
index 4288c692cd9331a3a4fbb90eab4f5ee9a44206f4..45b388ebdccbf9c3654f83487fb1cefe6795dd3a 100644 (file)
@@ -34,7 +34,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
                 yaffs_checkptrw.o  yaffs_qsort.o\
                 yaffs_nameval.o \
-                yaffs_norif1.o  ynorsim.o
+                yaffs_norif1.o  ynorsim.o \
+                yaffs_allocator.o
 #               yaffs_checkptrwtest.o\
 
 DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
@@ -50,7 +51,8 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsin
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_nameval.h yaffs_nameval.c \
-          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h
+          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
+          yaffs_allocator.c yaffs_allocator.h
 
 #all: directtest2k boottest
 
index 4697420a54100e0e43c822e6fb22a872576be62f..2d615fbcc2a763db2154b6b592115a0428099dbc 100644 (file)
@@ -46,7 +46,8 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_nameval.c yaffs_nameval.h \
-          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h
+          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
+          yaffs_allocator.c yaffs_allocator.h
 
 YAFFSDIRECTSYMLINKS =  yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
index 0bd093eb2e176894d15a86ce6fe44628ff3b3b85..1cc23443bdc760ce9cf39dc4da68cc3bbab7f2a3 100644 (file)
@@ -35,7 +35,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
                 yaffs_checkptrw.o  yaffs_qsort.o\
                 yaffs_nameval.o \
-                yaffs_norif1.o  ynorsim.o nor_stress.o yaffs_fsx.o
+                yaffs_norif1.o  ynorsim.o nor_stress.o yaffs_fsx.o \
+                yaffs_allocator.o
 
 #               yaffs_checkptrwtest.o\
 
@@ -51,7 +52,8 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_nameval.c yaffs_nameval.h \
-          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h
+          yaffs_qsort.c yaffs_qsort.h yaffs_trace.h \
+          yaffs_allocator.c yaffs_allocator.h
 
 YAFFSDIRECTSYMLINKS =  yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
index 9f6008dbea91c4d2fef64ea93edffbaa83c670d0..c09513277c270eb2b70c46bb38c23fd6f51cc6c2 100644 (file)
@@ -1846,7 +1846,7 @@ int yaffs_inodecount(const YCHAR *path)
        yaffsfs_Lock();
        dev = yaffsfs_FindDevice(path,&dummy);
        if(dev  && dev->isMounted) {
-          int nObjects = dev->nObjectsCreated - dev->nFreeObjects;
+          int nObjects = dev->nObjects;
           if(nObjects > dev->nHardLinks)
                retVal = nObjects - dev->nHardLinks;
        }
diff --git a/yaffs_allocator.c b/yaffs_allocator.c
new file mode 100644 (file)
index 0000000..b181dd5
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#include "yaffs_allocator.h"
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yportenv.h"
+
+#ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR
+
+void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       dev = dev;
+}
+
+void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       dev = dev;
+}
+
+yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
+{
+       return (yaffs_Tnode *)YMALLOC(dev->tnodeSize);
+}
+
+void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
+{
+       dev = dev;
+       YFREE(tn);
+}
+
+void yaffs_InitialiseRawObjects(yaffs_Device *dev)
+{
+       dev = dev;
+}
+
+void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
+{
+       dev = dev;
+}
+
+yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
+{
+       dev = dev;
+       return (yaffs_Object *) YMALLOC(sizeof(yaffs_Object));
+}
+
+
+void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
+{
+
+       dev = dev;      
+       YFREE(obj);
+}
+
+#else
+
+struct yaffs_TnodeList_struct {
+       struct yaffs_TnodeList_struct *next;
+       yaffs_Tnode *tnodes;
+};
+
+typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
+
+struct yaffs_ObjectList_struct {
+       yaffs_Object *objects;
+       struct yaffs_ObjectList_struct *next;
+};
+
+typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
+
+                
+struct yaffs_AllocatorStruct {
+       int nTnodesCreated;
+       yaffs_Tnode *freeTnodes;
+       int nFreeTnodes;
+       yaffs_TnodeList *allocatedTnodeList;
+
+       int nObjectsCreated;
+       yaffs_Object *freeObjects;
+       int nFreeObjects;
+       
+       yaffs_ObjectList *allocatedObjectList;
+};
+
+typedef struct yaffs_AllocatorStruct yaffs_Allocator;
+
+
+static void yaffs_DeinitialiseRawTnodes(yaffs_Device *dev)
+{
+
+       yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
+
+       yaffs_TnodeList *tmp;
+       
+       if(!allocator){
+               YBUG();
+               return;
+       }
+
+       while (allocator->allocatedTnodeList) {
+               tmp = allocator->allocatedTnodeList->next;
+
+               YFREE(allocator->allocatedTnodeList->tnodes);
+               YFREE(allocator->allocatedTnodeList);
+               allocator->allocatedTnodeList = tmp;
+
+       }
+
+       allocator->freeTnodes = NULL;
+       allocator->nFreeTnodes = 0;
+       allocator->nTnodesCreated = 0;
+}
+
+static void yaffs_InitialiseRawTnodes(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+
+       if(allocator){
+               allocator->allocatedTnodeList = NULL;
+               allocator->freeTnodes = NULL;
+               allocator->nFreeTnodes = 0;
+               allocator->nTnodesCreated = 0;
+       } else
+               YBUG();
+}
+
+static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
+{
+       yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
+       int i;
+       yaffs_Tnode *newTnodes;
+       __u8 *mem;
+       yaffs_Tnode *curr;
+       yaffs_Tnode *next;
+       yaffs_TnodeList *tnl;
+       
+       if(!allocator){
+               YBUG();
+               return YAFFS_FAIL;
+       }
+
+       if (nTnodes < 1)
+               return YAFFS_OK;
+
+
+       /* make these things */
+
+       newTnodes = YMALLOC(nTnodes * dev->tnodeSize);
+       mem = (__u8 *)newTnodes;
+
+       if (!newTnodes) {
+               T(YAFFS_TRACE_ERROR,
+                       (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
+               return YAFFS_FAIL;
+       }
+
+       /* Hook them into the free list */
+#if 0
+       for (i = 0; i < nTnodes - 1; i++) {
+               newTnodes[i].internal[0] = &newTnodes[i + 1];
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+               newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+       }
+
+       newTnodes[nTnodes - 1].internal[0] = allocator->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+       newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+       allocator->freeTnodes = newTnodes;
+#else
+       /* New hookup for wide tnodes */
+       for (i = 0; i < nTnodes - 1; i++) {
+               curr = (yaffs_Tnode *) &mem[i * dev->tnodeSize];
+               next = (yaffs_Tnode *) &mem[(i+1) * dev->tnodeSize];
+               curr->internal[0] = next;
+       }
+
+       curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * dev->tnodeSize];
+       curr->internal[0] = allocator->freeTnodes;
+       allocator->freeTnodes = (yaffs_Tnode *)mem;
+
+#endif
+
+
+       allocator->nFreeTnodes += nTnodes;
+       allocator->nTnodesCreated += nTnodes;
+
+       /* Now add this bunch of tnodes to a list for freeing up.
+        * 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 = YMALLOC(sizeof(yaffs_TnodeList));
+       if (!tnl) {
+               T(YAFFS_TRACE_ERROR,
+                 (TSTR
+                  ("yaffs: Could not add tnodes to management list" TENDSTR)));
+                  return YAFFS_FAIL;
+       } else {
+               tnl->tnodes = newTnodes;
+               tnl->next = allocator->allocatedTnodeList;
+               allocator->allocatedTnodeList = tnl;
+       }
+
+       T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
+
+       return YAFFS_OK;
+}
+
+
+yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
+       yaffs_Tnode *tn = NULL;
+       
+       if(!allocator){
+               YBUG();
+               return NULL;
+       }
+
+       /* If there are none left make more */
+       if (!allocator->freeTnodes)
+               yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
+
+       if (allocator->freeTnodes) {
+               tn = allocator->freeTnodes;
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+               if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
+                       /* Hoosterman, this thing looks like it isn't in the list */
+                       T(YAFFS_TRACE_ALWAYS,
+                         (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
+               }
+#endif
+               allocator->freeTnodes = allocator->freeTnodes->internal[0];
+               allocator->nFreeTnodes--;
+       }
+
+       return tn;
+}
+
+/* FreeTnode frees up a tnode and puts it back on the free list */
+void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+
+       if(!allocator){
+               YBUG();
+               return;
+       }
+
+       if (tn) {
+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
+               if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
+                       /* Hoosterman, this thing looks like it is already in the list */
+                       T(YAFFS_TRACE_ALWAYS,
+                         (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
+               }
+               tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
+#endif
+               tn->internal[0] = allocator->freeTnodes;
+               allocator->freeTnodes = tn;
+               allocator->nFreeTnodes++;
+       }
+       dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+}
+
+
+
+static void yaffs_InitialiseRawObjects(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+
+       if(allocator) {
+               allocator->allocatedObjectList = NULL;
+               allocator->freeObjects = NULL;
+               allocator->nFreeObjects = 0;
+       } else
+               YBUG();
+}
+
+static void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+       yaffs_ObjectList *tmp;
+
+       if(!allocator){
+               YBUG();
+               return;
+       }
+
+       while (allocator->allocatedObjectList) {
+               tmp = allocator->allocatedObjectList->next;
+               YFREE(allocator->allocatedObjectList->objects);
+               YFREE(allocator->allocatedObjectList);
+
+               allocator->allocatedObjectList = tmp;
+       }
+
+       allocator->freeObjects = NULL;
+       allocator->nFreeObjects = 0;
+       allocator->nObjectsCreated = 0;
+}
+
+
+static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+
+       int i;
+       yaffs_Object *newObjects;
+       yaffs_ObjectList *list;
+
+       if(!allocator){
+               YBUG();
+               return YAFFS_FAIL;
+       }
+
+       if (nObjects < 1)
+               return YAFFS_OK;
+
+       /* make these things */
+       newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
+       list = YMALLOC(sizeof(yaffs_ObjectList));
+
+       if (!newObjects || !list) {
+               if (newObjects){
+                       YFREE(newObjects);
+                       newObjects = NULL;
+               }
+               if (list){
+                       YFREE(list);
+                       list = NULL;
+               }
+               T(YAFFS_TRACE_ALLOCATE,
+                 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
+               return YAFFS_FAIL;
+       }
+
+       /* Hook them into the free list */
+       for (i = 0; i < nObjects - 1; i++) {
+               newObjects[i].siblings.next =
+                               (struct ylist_head *)(&newObjects[i + 1]);
+       }
+
+       newObjects[nObjects - 1].siblings.next = (void *)allocator->freeObjects;
+       allocator->freeObjects = newObjects;
+       allocator->nFreeObjects += nObjects;
+       allocator->nObjectsCreated += nObjects;
+
+       /* Now add this bunch of Objects to a list for freeing up. */
+
+       list->objects = newObjects;
+       list->next = allocator->allocatedObjectList;
+       allocator->allocatedObjectList = list;
+
+       return YAFFS_OK;
+}
+
+yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
+{
+       yaffs_Object *obj = NULL;
+       yaffs_Allocator *allocator = dev->allocator;
+
+       if(!allocator) {
+               YBUG();
+               return obj;
+       }
+
+       /* If there are none left make more */
+       if (!allocator->freeObjects)
+               yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
+
+       if (allocator->freeObjects) {
+               obj = allocator->freeObjects;
+               allocator->freeObjects =
+                       (yaffs_Object *) (allocator->freeObjects->siblings.next);
+               allocator->nFreeObjects--;
+       }
+
+       return obj;
+}
+
+
+void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
+{
+
+       yaffs_Allocator *allocator = dev->allocator;
+
+       if(!allocator)
+               YBUG();
+       else {   
+               /* Link into the free list. */
+               obj->siblings.next = (struct ylist_head *)(allocator->freeObjects);
+               allocator->freeObjects = obj;
+               allocator->nFreeObjects++;
+       }
+}
+
+void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       if(dev->allocator){
+               yaffs_DeinitialiseRawTnodes(dev);
+               yaffs_DeinitialiseRawObjects(dev);
+       
+               YFREE(dev->allocator);
+               dev->allocator=NULL;
+       } else
+               YBUG();
+}
+
+void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator;
+       
+       if(!dev->allocator){
+               allocator = YMALLOC(sizeof(yaffs_Allocator));
+               if(allocator){
+                       dev->allocator = allocator;
+                       yaffs_InitialiseRawTnodes(dev);
+                       yaffs_InitialiseRawObjects(dev);
+               }
+       } else
+               YBUG();
+}
+
+
+#endif
diff --git a/yaffs_allocator.h b/yaffs_allocator.h
new file mode 100644 (file)
index 0000000..b0a5d11
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_ALLOCATOR_H__
+#define __YAFFS_ALLOCATOR_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev);
+void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev);
+
+yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev);
+void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn);
+
+yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev);
+void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj);
+
+#endif
index b4ee69edf1f9642cc9ffc8bbc12bc931d3bb4b24..91d3a8170c7edaf9dac7833aaa57bfa9ff7a984a 100644 (file)
@@ -2242,7 +2242,7 @@ static int yaffs_BackgroundStart(yaffs_Device *dev)
        context->bgRunning = 1;
 
        context->bgThread = kthread_run(yaffs_BackgroundThread,
-                               (void *)dev,"yaffs-bg");
+                               (void *)dev,"yaffs-bg-%d",context->mount_id);
 
        if(IS_ERR(context->bgThread)){
                retval = PTR_ERR(context->bgThread);
@@ -2559,6 +2559,11 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        yaffs_DeviceParam *param;
 
        yaffs_options options;
+       
+       unsigned mount_id;
+       int found;
+       struct yaffs_LinuxContext *context_iterator;
+       struct ylist_head *l;
 
        sb->s_magic = YAFFS_MAGIC;
        sb->s_op = &yaffs_super_ops;
@@ -2861,8 +2866,19 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        param->skipCheckpointRead = options.skip_checkpoint_read;
        param->skipCheckpointWrite = options.skip_checkpoint_write;
 
-       /* we assume this is protected by lock_kernel() in mount/umount */
        down(&yaffs_context_lock);
+       /* Get a mount id */
+       found = 0;
+       for(mount_id=0; ! found; mount_id++){
+               found = 1;
+               ylist_for_each(l,&yaffs_context_list){
+                       context_iterator = ylist_entry(l,struct yaffs_LinuxContext,contextList);
+                       if(context_iterator->mount_id == mount_id)
+                               found = 0;
+               }
+       }
+       context->mount_id = mount_id;
+       
        ylist_add_tail(&(yaffs_DeviceToContext(dev)->contextList), &yaffs_context_list);
        up(&yaffs_context_lock);
 
@@ -3048,10 +3064,8 @@ static char *yaffs_dump_dev_part1(char *buf, yaffs_Device * dev)
        buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
        buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
        buf += sprintf(buf, "\n");
-       buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
-       buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
-       buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated);
-       buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects);
+       buf += sprintf(buf, "nTnodes............ %d\n", dev->nTnodes);
+       buf += sprintf(buf, "nObjects........... %d\n", dev->nObjects);
        buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks);
        buf += sprintf(buf, "\n");
        buf += sprintf(buf, "nPageWrites........ %u\n", dev->nPageWrites);
@@ -3144,18 +3158,13 @@ static int yaffs_stats_proc_read(char *page,
                yaffs_Device *dev = dc->dev;
 
                int erasedChunks;
-               int nObjects;
-               int nTnodes;
 
                erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
-               nObjects = dev->nObjectsCreated -dev->nFreeObjects;
-               nTnodes = dev->nTnodesCreated - dev->nFreeTnodes;
-               
                
-               buf += sprintf(buf,"%d, %d, %d, %u, %u, %d, %d\n",
+               buf += sprintf(buf,"%d, %d, %d, %u, %u, %u, %u\n",
                                n, dev->nFreeChunks, erasedChunks,
                                dev->backgroundGCs, dev->oldestDirtyGCs,
-                               nObjects, nTnodes);
+                               dev->nObjects, dev->nTnodes);
        }
        up(&yaffs_context_lock);
 
index 385b26778fbff66aa1e872800f4452ae5773ed17..604dc0910af9301d9b70d2feb304a9d9b1559b12 100644 (file)
@@ -30,7 +30,7 @@
 #include "yaffs_packedtags2.h"
 
 #include "yaffs_nameval.h"
-
+#include "yaffs_allocator.h"
 
 /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
 #define YAFFS_GC_GOOD_ENOUGH 2
@@ -1292,194 +1292,33 @@ static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name)
  * in the tnode.
  */
 
-/* yaffs_CreateTnodes creates a bunch more tnodes and
- * adds them to the tnode free list.
- * Don't use this function directly
- */
-static Y_INLINE int yaffs_CalcTnodeSize(yaffs_Device *dev)
-{
-       int tnodeSize;
-       /* Calculate the tnode size in bytes for variable width tnode support.
-        * Must be a multiple of 32-bits  */
-       tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
-
-       if (tnodeSize < sizeof(yaffs_Tnode))
-               tnodeSize = sizeof(yaffs_Tnode);
-       return tnodeSize;
-}
 
-static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
+static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
 {
-       int i;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
-       yaffs_Tnode *newTnodes;
-       __u8 *mem;
-       yaffs_Tnode *curr;
-       yaffs_Tnode *next;
-       yaffs_TnodeList *tnl;
-
-       if (nTnodes < 1)
-               return YAFFS_OK;
-
-
-       /* make these things */
-
-       newTnodes = YMALLOC(nTnodes * tnodeSize);
-       mem = (__u8 *)newTnodes;
-
-       if (!newTnodes) {
-               T(YAFFS_TRACE_ERROR,
-                       (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
-               return YAFFS_FAIL;
-       }
-
-       /* Hook them into the free list */
-#if 0
-       for (i = 0; i < nTnodes - 1; i++) {
-               newTnodes[i].internal[0] = &newTnodes[i + 1];
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-       }
-
-       newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-       newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-       dev->freeTnodes = newTnodes;
-#else
-       /* New hookup for wide tnodes */
-       for (i = 0; i < nTnodes - 1; i++) {
-               curr = (yaffs_Tnode *) &mem[i * tnodeSize];
-               next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
-               curr->internal[0] = next;
+       yaffs_Tnode *tn = yaffs_AllocateRawTnode(dev);
+       if (tn){
+               memset(tn, 0, dev->tnodeSize);
+               dev->nTnodes++;
        }
 
-       curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
-       curr->internal[0] = dev->freeTnodes;
-       dev->freeTnodes = (yaffs_Tnode *)mem;
-
-#endif
-
-
-       dev->nFreeTnodes += nTnodes;
-       dev->nTnodesCreated += nTnodes;
-
-       /* Now add this bunch of tnodes to a list for freeing up.
-        * 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 = YMALLOC(sizeof(yaffs_TnodeList));
-       if (!tnl) {
-               T(YAFFS_TRACE_ERROR,
-                 (TSTR
-                  ("yaffs: Could not add tnodes to management list" TENDSTR)));
-                  return YAFFS_FAIL;
-       } else {
-               tnl->tnodes = newTnodes;
-               tnl->next = dev->allocatedTnodeList;
-               dev->allocatedTnodeList = tnl;
-       }
-
-       T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
-
-       return YAFFS_OK;
-}
-
-/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */
-
-static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device *dev)
-{
-       yaffs_Tnode *tn = NULL;
-
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       tn = YMALLOC(yaffs_CalcTnodeSize(dev));
-       if(tn)
-               dev->nTnodesCreated++;
-#else
-       /* If there are none left make more */
-       if (!dev->freeTnodes)
-               yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
-
-       if (dev->freeTnodes) {
-               tn = dev->freeTnodes;
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
-                       /* Hoosterman, this thing looks like it isn't in the list */
-                       T(YAFFS_TRACE_ALWAYS,
-                         (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
-               }
-#endif
-               dev->freeTnodes = dev->freeTnodes->internal[0];
-               dev->nFreeTnodes--;
-       }
-#endif
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
        return tn;
 }
 
-static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
-{
-       yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
-
-       if (tn)
-               memset(tn, 0, tnodeSize);
-
-       return tn;
-}
-
 /* FreeTnode frees up a tnode and puts it back on the free list */
 static void yaffs_FreeTnode(yaffs_Device *dev, yaffs_Tnode *tn)
 {
-       if (tn) {
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-               YFREE(tn);
-               dev->nTnodesCreated--;
-#else
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
-                       /* Hoosterman, this thing looks like it is already in the list */
-                       T(YAFFS_TRACE_ALWAYS,
-                         (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
-               }
-               tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-               tn->internal[0] = dev->freeTnodes;
-               dev->freeTnodes = tn;
-               dev->nFreeTnodes++;
-#endif
-       }
+       yaffs_FreeRawTnode(dev,tn);
+       dev->nTnodes--;
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 }
 
-static void yaffs_DeinitialiseTnodes(yaffs_Device *dev)
+static void yaffs_DeinitialiseTnodesAndObjects(yaffs_Device *dev)
 {
-       /* Free the list of allocated tnodes */
-       yaffs_TnodeList *tmp;
-
-       while (dev->allocatedTnodeList) {
-               tmp = dev->allocatedTnodeList->next;
-
-               YFREE(dev->allocatedTnodeList->tnodes);
-               YFREE(dev->allocatedTnodeList);
-               dev->allocatedTnodeList = tmp;
-
-       }
-
-       dev->freeTnodes = NULL;
-       dev->nFreeTnodes = 0;
-       dev->nTnodesCreated = 0;
-}
-
-static void yaffs_InitialiseTnodes(yaffs_Device *dev)
-{
-       dev->allocatedTnodeList = NULL;
-       dev->freeTnodes = NULL;
-       dev->nFreeTnodes = 0;
-       dev->nTnodesCreated = 0;
+       yaffs_DeinitialiseRawTnodesAndObjects(dev);
+       dev->nObjects = 0;
+       dev->nTnodes = 0;
 }
 
 
@@ -1963,7 +1802,7 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn,
                                        hasData++;
                        }
                } else {
-                       int tnodeSize_u32 = yaffs_CalcTnodeSize(dev)/sizeof(__u32);
+                       int tnodeSize_u32 = dev->tnodeSize/sizeof(__u32);
                        __u32 *map = (__u32 *)tn;
 
                         for(i = 0; !hasData && i < tnodeSize_u32; i++){
@@ -2028,96 +1867,32 @@ static int yaffs_PruneFileStructure(yaffs_Device *dev,
 
 /*-------------------- End of File Structure functions.-------------------*/
 
-/* yaffs_CreateFreeObjects creates a bunch more objects and
- * adds them to the object free list.
- */
-static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
-{
-       int i;
-       yaffs_Object *newObjects;
-       yaffs_ObjectList *list;
-
-       if (nObjects < 1)
-               return YAFFS_OK;
-
-       /* make these things */
-       newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
-       list = YMALLOC(sizeof(yaffs_ObjectList));
-
-       if (!newObjects || !list) {
-               if (newObjects){
-                       YFREE(newObjects);
-                       newObjects = NULL;
-               }
-               if (list){
-                       YFREE(list);
-                       list = NULL;
-               }
-               T(YAFFS_TRACE_ALLOCATE,
-                 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
-               return YAFFS_FAIL;
-       }
-
-       /* Hook them into the free list */
-       for (i = 0; i < nObjects - 1; i++) {
-               newObjects[i].siblings.next =
-                               (struct ylist_head *)(&newObjects[i + 1]);
-       }
-
-       newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
-       dev->freeObjects = newObjects;
-       dev->nFreeObjects += nObjects;
-       dev->nObjectsCreated += nObjects;
-
-       /* Now add this bunch of Objects to a list for freeing up. */
-
-       list->objects = newObjects;
-       list->next = dev->allocatedObjectList;
-       dev->allocatedObjectList = list;
-
-       return YAFFS_OK;
-}
-
 
 /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
 static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
 {
-       yaffs_Object *tn = NULL;
+       yaffs_Object *obj = yaffs_AllocateRawObject(dev);
 
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       tn = YMALLOC(sizeof(yaffs_Object));
-       if(tn)
-               dev->nObjectsCreated++;
-#else
-       /* If there are none left make more */
-       if (!dev->freeObjects)
-               yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
+       if (obj) {
+               dev->nObjects++;
 
-       if (dev->freeObjects) {
-               tn = dev->freeObjects;
-               dev->freeObjects =
-                       (yaffs_Object *) (dev->freeObjects->siblings.next);
-               dev->nFreeObjects--;
-       }
-#endif
-       if (tn) {
                /* Now sweeten it up... */
 
-               memset(tn, 0, sizeof(yaffs_Object));
-               tn->beingCreated = 1;
+               memset(obj, 0, sizeof(yaffs_Object));
+               obj->beingCreated = 1;
 
-               tn->myDev = dev;
-               tn->hdrChunk = 0;
-               tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
-               YINIT_LIST_HEAD(&(tn->hardLinks));
-               YINIT_LIST_HEAD(&(tn->hashLink));
-               YINIT_LIST_HEAD(&tn->siblings);
+               obj->myDev = dev;
+               obj->hdrChunk = 0;
+               obj->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
+               YINIT_LIST_HEAD(&(obj->hardLinks));
+               YINIT_LIST_HEAD(&(obj->hashLink));
+               YINIT_LIST_HEAD(&obj->siblings);
 
 
                /* Now make the directory sane */
                if (dev->rootDir) {
-                       tn->parent = dev->rootDir;
-                       ylist_add(&(tn->siblings), &dev->rootDir->variant.directoryVariant.children);
+                       obj->parent = dev->rootDir;
+                       ylist_add(&(obj->siblings), &dev->rootDir->variant.directoryVariant.children);
                }
 
                /* Add it to the lost and found directory.
@@ -2125,14 +1900,14 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
                 * check if lostNFound exists first
                 */
                if (dev->lostNFoundDir)
-                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
+                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, obj);
 
-               tn->beingCreated = 0;
+               obj->beingCreated = 0;
        }
 
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
-       return tn;
+       return obj;
 }
 
 static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number,
@@ -2156,54 +1931,46 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number,
 
 }
 
-static void yaffs_UnhashObject(yaffs_Object *tn)
+static void yaffs_UnhashObject(yaffs_Object *obj)
 {
        int bucket;
-       yaffs_Device *dev = tn->myDev;
+       yaffs_Device *dev = obj->myDev;
 
        /* If it is still linked into the bucket list, free from the list */
-       if (!ylist_empty(&tn->hashLink)) {
-               ylist_del_init(&tn->hashLink);
-               bucket = yaffs_HashFunction(tn->objectId);
+       if (!ylist_empty(&obj->hashLink)) {
+               ylist_del_init(&obj->hashLink);
+               bucket = yaffs_HashFunction(obj->objectId);
                dev->objectBucket[bucket].count--;
        }
 }
 
 /*  FreeObject frees up a Object and puts it back on the free list */
-static void yaffs_FreeObject(yaffs_Object *tn)
+static void yaffs_FreeObject(yaffs_Object *obj)
 {
-       yaffs_Device *dev = tn->myDev;
+       yaffs_Device *dev = obj->myDev;
 
-       T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode));
+       T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), obj, obj->myInode));
 
-       if (!tn)
+       if (!obj)
                YBUG();
-       if (tn->parent)
+       if (obj->parent)
                YBUG();
-       if (!ylist_empty(&tn->siblings))
+       if (!ylist_empty(&obj->siblings))
                YBUG();
 
 
-       if (tn->myInode) {
+       if (obj->myInode) {
                /* We're still hooked up to a cached inode.
                 * Don't delete now, but mark for later deletion
                 */
-               tn->deferedFree = 1;
+               obj->deferedFree = 1;
                return;
        }
 
-       yaffs_UnhashObject(tn);
-
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       YFREE(tn);
-       dev->nObjectsCreated--;
-       tn = NULL;
-#else
-       /* Link into the free list. */
-       tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
-       dev->freeObjects = tn;
-       dev->nFreeObjects++;
-#endif
+       yaffs_UnhashObject(obj);
+       
+       yaffs_FreeRawObject(dev,obj);
+       dev->nObjects--;
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 }
 
@@ -2214,33 +1981,14 @@ void yaffs_HandleDeferedFree(yaffs_Object *obj)
                yaffs_FreeObject(obj);
 }
 
-
-static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
-{
-       /* Free the list of allocated Objects */
-
-       yaffs_ObjectList *tmp;
-
-       while (dev->allocatedObjectList) {
-               tmp = dev->allocatedObjectList->next;
-               YFREE(dev->allocatedObjectList->objects);
-               YFREE(dev->allocatedObjectList);
-
-               dev->allocatedObjectList = tmp;
-       }
-
-       dev->freeObjects = NULL;
-       dev->nFreeObjects = 0;
-       dev->nObjectsCreated = 0;
-}
-
-static void yaffs_InitialiseObjects(yaffs_Device *dev)
+static void yaffs_InitialiseTnodesAndObjects(yaffs_Device *dev)
 {
        int i;
 
-       dev->allocatedObjectList = NULL;
-       dev->freeObjects = NULL;
-       dev->nFreeObjects = 0;
+       dev->nObjects = 0;
+       dev->nTnodes = 0;
+
+       yaffs_InitialiseRawTnodesAndObjects(dev);
 
        for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
                YINIT_LIST_HEAD(&dev->objectBucket[i].list);
@@ -2992,14 +2740,13 @@ static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
                int nBytes = 0;
                int nBlocks;
                int devBlocks = (dev->param.endBlock - dev->param.startBlock + 1);
-               int tnodeSize = yaffs_CalcTnodeSize(dev);
 
                nBytes += sizeof(yaffs_CheckpointValidity);
                nBytes += sizeof(yaffs_CheckpointDevice);
                nBytes += devBlocks * sizeof(yaffs_BlockInfo);
                nBytes += devBlocks * dev->chunkBitmapStride;
-               nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
-               nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
+               nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjects);
+               nBytes += (dev->tnodeSize + sizeof(__u32)) * (dev->nTnodes);
                nBytes += sizeof(yaffs_CheckpointValidity);
                nBytes += sizeof(__u32); /* checksum*/
 
@@ -4700,7 +4447,6 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn,
        int i;
        yaffs_Device *dev = in->myDev;
        int ok = 1;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
 
        if (tn) {
                if (level > 0) {
@@ -4717,7 +4463,7 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn,
                        __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
                        ok = (yaffs_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset));
                        if (ok)
-                               ok = (yaffs_CheckpointWrite(dev, tn, tnodeSize) == tnodeSize);
+                               ok = (yaffs_CheckpointWrite(dev, tn, dev->tnodeSize) == dev->tnodeSize);
                }
        }
 
@@ -4751,7 +4497,6 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
        yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
        yaffs_Tnode *tn;
        int nread = 0;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
 
        ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
 
@@ -4760,10 +4505,10 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
                /* Read level 0 tnode */
 
 
-               tn = yaffs_GetTnodeRaw(dev);
-               if (tn)
-                       ok = (yaffs_CheckpointRead(dev, tn, tnodeSize) == tnodeSize);
-               else
+               tn = yaffs_GetTnode(dev);
+               if (tn){
+                       ok = (yaffs_CheckpointRead(dev, tn, dev->tnodeSize) == dev->tnodeSize);
+               else
                        ok = 0;
 
                if (tn && ok)
@@ -8030,6 +7775,9 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        else
                dev->chunkGroupBits = bits - dev->tnodeWidth;
 
+       dev->tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+       if(dev->tnodeSize < sizeof(yaffs_Tnode))
+               dev->tnodeSize = sizeof(yaffs_Tnode);
 
        dev->chunkGroupSize = 1 << dev->chunkGroupBits;
 
@@ -8119,8 +7867,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        if (!init_failed && !yaffs_InitialiseBlocks(dev))
                init_failed = 1;
 
-       yaffs_InitialiseTnodes(dev);
-       yaffs_InitialiseObjects(dev);
+       yaffs_InitialiseTnodesAndObjects(dev);
 
        if (!init_failed && !yaffs_CreateInitialDirectories(dev))
                init_failed = 1;
@@ -8139,9 +7886,8 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
                                 * and scan backwards.
                                 */
                                yaffs_DeinitialiseBlocks(dev);
-                               yaffs_DeinitialiseTnodes(dev);
-                               yaffs_DeinitialiseObjects(dev);
 
+                               yaffs_DeinitialiseTnodesAndObjects(dev);
 
                                dev->nErasedBlocks = 0;
                                dev->nFreeChunks = 0;
@@ -8154,8 +7900,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
                                if (!init_failed && !yaffs_InitialiseBlocks(dev))
                                        init_failed = 1;
 
-                               yaffs_InitialiseTnodes(dev);
-                               yaffs_InitialiseObjects(dev);
+                               yaffs_InitialiseTnodesAndObjects(dev);
 
                                if (!init_failed && !yaffs_CreateInitialDirectories(dev))
                                        init_failed = 1;
@@ -8209,8 +7954,7 @@ void yaffs_Deinitialise(yaffs_Device *dev)
                int i;
 
                yaffs_DeinitialiseBlocks(dev);
-               yaffs_DeinitialiseTnodes(dev);
-               yaffs_DeinitialiseObjects(dev);
+               yaffs_DeinitialiseTnodesAndObjects(dev);
                if (dev->param.nShortOpCaches > 0 &&
                    dev->srCache) {
 
index 84b53aacf05403fd2c9a927cbdf0b13b10fa8e13..d08a6f6e8126cbbbb93aacdc006537ee85b99a64 100644 (file)
@@ -361,12 +361,6 @@ union yaffs_Tnode_union {
 
 typedef union yaffs_Tnode_union yaffs_Tnode;
 
-struct yaffs_TnodeList_struct {
-       struct yaffs_TnodeList_struct *next;
-       yaffs_Tnode *tnodes;
-};
-
-typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
 
 /*------------------------  Object -----------------------------*/
 /* An object can be one of:
@@ -479,13 +473,6 @@ struct yaffs_ObjectStruct {
 
 typedef struct yaffs_ObjectStruct yaffs_Object;
 
-struct yaffs_ObjectList_struct {
-       yaffs_Object *objects;
-       struct yaffs_ObjectList_struct *next;
-};
-
-typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
-
 typedef struct {
        struct ylist_head list;
        int count;
@@ -635,6 +622,7 @@ struct yaffs_DeviceStruct {
        /* Stuff to support wide tnodes */
        __u32 tnodeWidth;
        __u32 tnodeMask;
+       __u32 tnodeSize;
 
        /* Stuff for figuring out file offset to chunk conversions */
        __u32 chunkShift; /* Shift value */
@@ -686,19 +674,13 @@ struct yaffs_DeviceStruct {
        __u32 allocationPage;
        int allocationBlockFinder;      /* Used to search for next allocation block */
 
-       int nTnodesCreated;
-       yaffs_Tnode *freeTnodes;
-       int nFreeTnodes;
-       yaffs_TnodeList *allocatedTnodeList;
-
-       int nObjectsCreated;
-       yaffs_Object *freeObjects;
-       int nFreeObjects;
+       /* Object and Tnode memory management */
+       void *allocator;
+       int nObjects;
+       int nTnodes;
 
        int nHardLinks;
 
-       yaffs_ObjectList *allocatedObjectList;
-
        yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
        __u32 bucketFinder;
 
index 4434e6c497b93598feacdcb91f139de3577e34c9..6832681d29bbacf9046d19a7fe0b6ddf5d938c35 100644 (file)
@@ -34,6 +34,7 @@ struct yaffs_LinuxContext {
        void (*putSuperFunc)(struct super_block *sb);
 
        struct task_struct *readdirProcess;
+       unsigned mount_id;
 };
 
 #define yaffs_DeviceToContext(dev) ((struct yaffs_LinuxContext *)((dev)->context))
diff --git a/yaffs_linux_allocator.c b/yaffs_linux_allocator.c
new file mode 100644 (file)
index 0000000..87de21b
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#include "yaffs_allocator.h"
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yportenv.h"
+#include "yaffs_linux.h"
+/*
+ * Start out with the same allocator as yaffs direct.
+ * Todo: Change to Linux slab allocator.
+ */
+
+
+
+#define NAMELEN  20
+struct yaffs_AllocatorStruct {
+       char tnode_name[NAMELEN+1];
+       char object_name[NAMELEN+1];
+       struct kmem_cache *tnode_cache;
+       struct kmem_cache *object_cache;
+};
+
+typedef struct yaffs_AllocatorStruct yaffs_Allocator;
+
+int mount_id;
+
+void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
+
+       T(YAFFS_TRACE_ALLOCATE,(TSTR("Deinitialising yaffs allocator\n")));
+
+       if(allocator){
+               if(allocator->tnode_cache){
+                       kmem_cache_destroy(allocator->tnode_cache);
+                       allocator->tnode_cache = NULL;
+               } else {
+                       T(YAFFS_TRACE_ALWAYS,
+                               (TSTR("NULL tnode cache\n")));
+                       YBUG();
+               }
+
+               if(allocator->object_cache){
+                       kmem_cache_destroy(allocator->object_cache);
+                       allocator->object_cache = NULL;
+               } else {
+                       T(YAFFS_TRACE_ALWAYS,
+                               (TSTR("NULL object cache\n")));
+                       YBUG();
+               }
+               
+               YFREE(allocator);
+
+       } else {
+               T(YAFFS_TRACE_ALWAYS,
+                       (TSTR("Deinitialising NULL allocator\n")));
+               YBUG();
+       }               
+       dev->allocator = NULL;
+}
+
+
+static void fake_ctor0(void *data){data = data;}
+static void fake_ctor1(void *data){data = data;}
+static void fake_ctor2(void *data){data = data;}
+static void fake_ctor3(void *data){data = data;}
+static void fake_ctor4(void *data){data = data;}
+static void fake_ctor5(void *data){data = data;}
+static void fake_ctor6(void *data){data = data;}
+static void fake_ctor7(void *data){data = data;}
+static void fake_ctor8(void *data){data = data;}
+static void fake_ctor9(void *data){data = data;}
+
+static void (*fake_ctor_list[10]) (void *) = {
+       fake_ctor0,
+       fake_ctor1,
+       fake_ctor2,
+       fake_ctor3,
+       fake_ctor4,
+       fake_ctor5,
+       fake_ctor6,
+       fake_ctor7,
+       fake_ctor8,
+       fake_ctor9,
+};
+
+void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator;
+       unsigned mount_id = yaffs_DeviceToContext(dev)->mount_id;
+       
+       T(YAFFS_TRACE_ALLOCATE,(TSTR("Initialising yaffs allocator\n")));
+
+       if(dev->allocator)
+               YBUG();
+       else if(mount_id >= 10){
+               T(YAFFS_TRACE_ALWAYS,(TSTR("Bad mount_id %u\n"),mount_id));
+       } else {
+                allocator = YMALLOC(sizeof(yaffs_Allocator));
+                memset(allocator,0,sizeof(yaffs_Allocator));
+                dev->allocator = allocator;
+               
+               if(!dev->allocator){
+                       T(YAFFS_TRACE_ALWAYS,
+                               (TSTR("yaffs allocator creation failed\n")));
+                       YBUG();
+                       return;
+                       
+               }
+               
+               sprintf(allocator->tnode_name,"yaffs_t_%u",mount_id);
+               sprintf(allocator->object_name,"yaffs_o_%u",mount_id);
+               
+               allocator->tnode_cache = 
+                       kmem_cache_create(allocator->tnode_name,
+                               dev->tnodeSize,
+                               0, 0,
+                               fake_ctor_list[mount_id]);
+               if(allocator->tnode_cache)
+                       T(YAFFS_TRACE_ALLOCATE,
+                               (TSTR("tnode cache \"%s\" %p\n"),
+                               allocator->tnode_name,allocator->tnode_cache));
+               else {
+                       T(YAFFS_TRACE_ALWAYS,
+                               (TSTR("yaffs cache creation failed\n")));
+                       YBUG();
+               }
+
+
+               allocator->object_cache = 
+                       kmem_cache_create(allocator->object_name,
+                               sizeof(yaffs_Object),
+                               0, 0,
+                               fake_ctor_list[mount_id]);
+
+               if(allocator->object_cache)
+                       T(YAFFS_TRACE_ALLOCATE,
+                               (TSTR("object cache \"%s\" %p\n"),
+                               allocator->object_name,allocator->object_cache));
+
+               else {
+                       T(YAFFS_TRACE_ALWAYS,
+                               (TSTR("yaffs cache creation failed\n")));
+                       YBUG();
+               }
+       } 
+}
+
+
+yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+       if(!allocator || !allocator->tnode_cache){
+               YBUG();
+               return NULL;
+       }
+       return kmem_cache_alloc(allocator->tnode_cache, GFP_NOFS);
+}
+
+void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+       kmem_cache_free(allocator->tnode_cache,tn);
+}
+
+yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+       if(!allocator){
+               YBUG();
+               return NULL;
+       }
+       if(!allocator->object_cache){
+               YBUG();
+               return NULL;
+       }
+       return kmem_cache_alloc(allocator->object_cache, GFP_NOFS);
+}
+
+void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
+{
+       yaffs_Allocator *allocator = dev->allocator;
+       kmem_cache_free(allocator->object_cache,obj);
+}
index a24d58e375831a4c079638b189e6d016a1f01ead..4a4981b3f9adb1ac1e7f110051c1835c2f1bc2e7 100644 (file)
 #ifndef __YAFFS_QSORT_H__
 #define __YAFFS_QSORT_H__
 
+#ifdef __KERNEL__
+#include <linux/sort.h>
+
+extern void yaffs_qsort(void *const base, size_t total_elems, size_t size,
+                       int (*cmp)(const void *, const void *)){
+       sort(base, total_elems, size, cmp, NULL);
+}
+
+#else
+
 extern void yaffs_qsort(void *const base, size_t total_elems, size_t size,
                        int (*cmp)(const void *, const void *));
 
 #endif
+#endif