2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2010 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
16 #include "yaffs_allocator.h"
17 #include "yaffs_guts.h"
18 #include "yaffs_trace.h"
21 #ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR
23 void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
28 void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
33 yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
35 return (yaffs_Tnode *)YMALLOC(dev->tnodeSize);
38 void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
44 void yaffs_InitialiseRawObjects(yaffs_Device *dev)
49 void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
54 yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
57 return (yaffs_Object *) YMALLOC(sizeof(yaffs_Object));
61 void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
70 struct yaffs_TnodeList_struct {
71 struct yaffs_TnodeList_struct *next;
75 typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
77 struct yaffs_ObjectList_struct {
78 yaffs_Object *objects;
79 struct yaffs_ObjectList_struct *next;
82 typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
85 struct yaffs_AllocatorStruct {
87 yaffs_Tnode *freeTnodes;
89 yaffs_TnodeList *allocatedTnodeList;
92 yaffs_Object *freeObjects;
95 yaffs_ObjectList *allocatedObjectList;
98 typedef struct yaffs_AllocatorStruct yaffs_Allocator;
101 static void yaffs_DeinitialiseRawTnodes(yaffs_Device *dev)
104 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
106 yaffs_TnodeList *tmp;
113 while (allocator->allocatedTnodeList) {
114 tmp = allocator->allocatedTnodeList->next;
116 YFREE(allocator->allocatedTnodeList->tnodes);
117 YFREE(allocator->allocatedTnodeList);
118 allocator->allocatedTnodeList = tmp;
122 allocator->freeTnodes = NULL;
123 allocator->nFreeTnodes = 0;
124 allocator->nTnodesCreated = 0;
127 static void yaffs_InitialiseRawTnodes(yaffs_Device *dev)
129 yaffs_Allocator *allocator = dev->allocator;
132 allocator->allocatedTnodeList = NULL;
133 allocator->freeTnodes = NULL;
134 allocator->nFreeTnodes = 0;
135 allocator->nTnodesCreated = 0;
140 static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
142 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
144 yaffs_Tnode *newTnodes;
148 yaffs_TnodeList *tnl;
159 /* make these things */
161 newTnodes = YMALLOC(nTnodes * dev->tnodeSize);
162 mem = (__u8 *)newTnodes;
166 (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
170 /* New hookup for wide tnodes */
171 for (i = 0; i < nTnodes - 1; i++) {
172 curr = (yaffs_Tnode *) &mem[i * dev->tnodeSize];
173 next = (yaffs_Tnode *) &mem[(i+1) * dev->tnodeSize];
174 curr->internal[0] = next;
177 curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * dev->tnodeSize];
178 curr->internal[0] = allocator->freeTnodes;
179 allocator->freeTnodes = (yaffs_Tnode *)mem;
181 allocator->nFreeTnodes += nTnodes;
182 allocator->nTnodesCreated += nTnodes;
184 /* Now add this bunch of tnodes to a list for freeing up.
185 * NB If we can't add this to the management list it isn't fatal
186 * but it just means we can't free this bunch of tnodes later.
189 tnl = YMALLOC(sizeof(yaffs_TnodeList));
193 ("yaffs: Could not add tnodes to management list" TENDSTR)));
196 tnl->tnodes = newTnodes;
197 tnl->next = allocator->allocatedTnodeList;
198 allocator->allocatedTnodeList = tnl;
201 T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
207 yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
209 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
210 yaffs_Tnode *tn = NULL;
217 /* If there are none left make more */
218 if (!allocator->freeTnodes)
219 yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
221 if (allocator->freeTnodes) {
222 tn = allocator->freeTnodes;
223 allocator->freeTnodes = allocator->freeTnodes->internal[0];
224 allocator->nFreeTnodes--;
230 /* FreeTnode frees up a tnode and puts it back on the free list */
231 void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
233 yaffs_Allocator *allocator = dev->allocator;
241 tn->internal[0] = allocator->freeTnodes;
242 allocator->freeTnodes = tn;
243 allocator->nFreeTnodes++;
245 dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
250 static void yaffs_InitialiseRawObjects(yaffs_Device *dev)
252 yaffs_Allocator *allocator = dev->allocator;
255 allocator->allocatedObjectList = NULL;
256 allocator->freeObjects = NULL;
257 allocator->nFreeObjects = 0;
262 static void yaffs_DeinitialiseRawObjects(yaffs_Device *dev)
264 yaffs_Allocator *allocator = dev->allocator;
265 yaffs_ObjectList *tmp;
272 while (allocator->allocatedObjectList) {
273 tmp = allocator->allocatedObjectList->next;
274 YFREE(allocator->allocatedObjectList->objects);
275 YFREE(allocator->allocatedObjectList);
277 allocator->allocatedObjectList = tmp;
280 allocator->freeObjects = NULL;
281 allocator->nFreeObjects = 0;
282 allocator->nObjectsCreated = 0;
286 static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
288 yaffs_Allocator *allocator = dev->allocator;
291 yaffs_Object *newObjects;
292 yaffs_ObjectList *list;
302 /* make these things */
303 newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
304 list = YMALLOC(sizeof(yaffs_ObjectList));
306 if (!newObjects || !list) {
315 T(YAFFS_TRACE_ALLOCATE,
316 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
320 /* Hook them into the free list */
321 for (i = 0; i < nObjects - 1; i++) {
322 newObjects[i].siblings.next =
323 (struct ylist_head *)(&newObjects[i + 1]);
326 newObjects[nObjects - 1].siblings.next = (void *)allocator->freeObjects;
327 allocator->freeObjects = newObjects;
328 allocator->nFreeObjects += nObjects;
329 allocator->nObjectsCreated += nObjects;
331 /* Now add this bunch of Objects to a list for freeing up. */
333 list->objects = newObjects;
334 list->next = allocator->allocatedObjectList;
335 allocator->allocatedObjectList = list;
340 yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
342 yaffs_Object *obj = NULL;
343 yaffs_Allocator *allocator = dev->allocator;
350 /* If there are none left make more */
351 if (!allocator->freeObjects)
352 yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
354 if (allocator->freeObjects) {
355 obj = allocator->freeObjects;
356 allocator->freeObjects =
357 (yaffs_Object *) (allocator->freeObjects->siblings.next);
358 allocator->nFreeObjects--;
365 void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
368 yaffs_Allocator *allocator = dev->allocator;
373 /* Link into the free list. */
374 obj->siblings.next = (struct ylist_head *)(allocator->freeObjects);
375 allocator->freeObjects = obj;
376 allocator->nFreeObjects++;
380 void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
383 yaffs_DeinitialiseRawTnodes(dev);
384 yaffs_DeinitialiseRawObjects(dev);
386 YFREE(dev->allocator);
392 void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
394 yaffs_Allocator *allocator;
397 allocator = YMALLOC(sizeof(yaffs_Allocator));
399 dev->allocator = allocator;
400 yaffs_InitialiseRawTnodes(dev);
401 yaffs_InitialiseRawObjects(dev);