Refactoring the allocator allows alternate allocators to be switched in more easily
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
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
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
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
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
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 \
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\
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 \
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;
}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
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);
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;
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);
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);
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);
#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
* 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;
}
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++){
/*-------------------- 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.
* 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,
}
-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*/
}
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);
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*/
int i;
yaffs_Device *dev = in->myDev;
int ok = 1;
- int tnodeSize = yaffs_CalcTnodeSize(dev);
if (tn) {
if (level > 0) {
__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);
}
}
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));
/* 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)
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;
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;
* and scan backwards.
*/
yaffs_DeinitialiseBlocks(dev);
- yaffs_DeinitialiseTnodes(dev);
- yaffs_DeinitialiseObjects(dev);
+ yaffs_DeinitialiseTnodesAndObjects(dev);
dev->nErasedBlocks = 0;
dev->nFreeChunks = 0;
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;
int i;
yaffs_DeinitialiseBlocks(dev);
- yaffs_DeinitialiseTnodes(dev);
- yaffs_DeinitialiseObjects(dev);
+ yaffs_DeinitialiseTnodesAndObjects(dev);
if (dev->param.nShortOpCaches > 0 &&
dev->srCache) {
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:
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;
/* Stuff to support wide tnodes */
__u32 tnodeWidth;
__u32 tnodeMask;
+ __u32 tnodeSize;
/* Stuff for figuring out file offset to chunk conversions */
__u32 chunkShift; /* Shift value */
__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;
void (*putSuperFunc)(struct super_block *sb);
struct task_struct *readdirProcess;
+ unsigned mount_id;
};
#define yaffs_DeviceToContext(dev) ((struct yaffs_LinuxContext *)((dev)->context))
--- /dev/null
+/*
+ * 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);
+}
#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