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_deinit_raw_tnodes_and_objs(yaffs_dev_t *dev)
28 void yaffs_init_raw_tnodes_and_objs(yaffs_dev_t *dev)
33 yaffs_tnode_t *yaffs_alloc_raw_tnode(yaffs_dev_t *dev)
35 return (yaffs_tnode_t *)YMALLOC(dev->tnode_size);
38 void yaffs_free_raw_tnode(yaffs_dev_t *dev, yaffs_tnode_t *tn)
44 void yaffs_init_raw_objs(yaffs_dev_t *dev)
49 void yaffs_deinit_raw_objs(yaffs_dev_t *dev)
54 yaffs_obj_t *yaffs_alloc_raw_obj(yaffs_dev_t *dev)
57 return (yaffs_obj_t *) YMALLOC(sizeof(yaffs_obj_t));
61 void yaffs_free_raw_obj(yaffs_dev_t *dev, yaffs_obj_t *obj)
70 struct yaffs_tnode_list {
71 struct yaffs_tnode_list *next;
72 yaffs_tnode_t *tnodes;
75 typedef struct yaffs_tnode_list yaffs_tnodelist_t;
77 struct yaffs_obj_tList_struct {
79 struct yaffs_obj_tList_struct *next;
82 typedef struct yaffs_obj_tList_struct yaffs_obj_tList;
85 struct yaffs_AllocatorStruct {
87 yaffs_tnode_t *freeTnodes;
89 yaffs_tnodelist_t *allocatedTnodeList;
92 yaffs_obj_t *freeObjects;
95 yaffs_obj_tList *allocatedObjectList;
98 typedef struct yaffs_AllocatorStruct yaffs_Allocator;
101 static void yaffs_deinit_raw_tnodes(yaffs_dev_t *dev)
104 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
106 yaffs_tnodelist_t *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->n_tnodesCreated = 0;
127 static void yaffs_init_raw_tnodes(yaffs_dev_t *dev)
129 yaffs_Allocator *allocator = dev->allocator;
132 allocator->allocatedTnodeList = NULL;
133 allocator->freeTnodes = NULL;
134 allocator->nFreeTnodes = 0;
135 allocator->n_tnodesCreated = 0;
140 static int yaffs_create_tnodes(yaffs_dev_t *dev, int n_tnodes)
142 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
144 yaffs_tnode_t *newTnodes;
148 yaffs_tnodelist_t *tnl;
159 /* make these things */
161 newTnodes = YMALLOC(n_tnodes * dev->tnode_size);
162 mem = (__u8 *)newTnodes;
166 (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
170 /* New hookup for wide tnodes */
171 for (i = 0; i < n_tnodes - 1; i++) {
172 curr = (yaffs_tnode_t *) &mem[i * dev->tnode_size];
173 next = (yaffs_tnode_t *) &mem[(i+1) * dev->tnode_size];
174 curr->internal[0] = next;
177 curr = (yaffs_tnode_t *) &mem[(n_tnodes - 1) * dev->tnode_size];
178 curr->internal[0] = allocator->freeTnodes;
179 allocator->freeTnodes = (yaffs_tnode_t *)mem;
181 allocator->nFreeTnodes += n_tnodes;
182 allocator->n_tnodesCreated += n_tnodes;
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_t));
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_t *yaffs_alloc_raw_tnode(yaffs_dev_t *dev)
209 yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
210 yaffs_tnode_t *tn = NULL;
217 /* If there are none left make more */
218 if (!allocator->freeTnodes)
219 yaffs_create_tnodes(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_free_raw_tnode(yaffs_dev_t *dev, yaffs_tnode_t *tn)
233 yaffs_Allocator *allocator = dev->allocator;
241 tn->internal[0] = allocator->freeTnodes;
242 allocator->freeTnodes = tn;
243 allocator->nFreeTnodes++;
245 dev->checkpoint_blocks_required = 0; /* force recalculation*/
250 static void yaffs_init_raw_objs(yaffs_dev_t *dev)
252 yaffs_Allocator *allocator = dev->allocator;
255 allocator->allocatedObjectList = NULL;
256 allocator->freeObjects = NULL;
257 allocator->nFreeObjects = 0;
262 static void yaffs_deinit_raw_objs(yaffs_dev_t *dev)
264 yaffs_Allocator *allocator = dev->allocator;
265 yaffs_obj_tList *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->n_objCreated = 0;
286 static int yaffs_create_free_objs(yaffs_dev_t *dev, int n_obj)
288 yaffs_Allocator *allocator = dev->allocator;
291 yaffs_obj_t *newObjects;
292 yaffs_obj_tList *list;
302 /* make these things */
303 newObjects = YMALLOC(n_obj * sizeof(yaffs_obj_t));
304 list = YMALLOC(sizeof(yaffs_obj_tList));
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 < n_obj - 1; i++) {
322 newObjects[i].siblings.next =
323 (struct ylist_head *)(&newObjects[i + 1]);
326 newObjects[n_obj - 1].siblings.next = (void *)allocator->freeObjects;
327 allocator->freeObjects = newObjects;
328 allocator->nFreeObjects += n_obj;
329 allocator->n_objCreated += n_obj;
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_obj_t *yaffs_alloc_raw_obj(yaffs_dev_t *dev)
342 yaffs_obj_t *obj = NULL;
343 yaffs_Allocator *allocator = dev->allocator;
350 /* If there are none left make more */
351 if (!allocator->freeObjects)
352 yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
354 if (allocator->freeObjects) {
355 obj = allocator->freeObjects;
356 allocator->freeObjects =
357 (yaffs_obj_t *) (allocator->freeObjects->siblings.next);
358 allocator->nFreeObjects--;
365 void yaffs_free_raw_obj(yaffs_dev_t *dev, yaffs_obj_t *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_deinit_raw_tnodes_and_objs(yaffs_dev_t *dev)
383 yaffs_deinit_raw_tnodes(dev);
384 yaffs_deinit_raw_objs(dev);
386 YFREE(dev->allocator);
392 void yaffs_init_raw_tnodes_and_objs(yaffs_dev_t *dev)
394 yaffs_Allocator *allocator;
397 allocator = YMALLOC(sizeof(yaffs_Allocator));
399 dev->allocator = allocator;
400 yaffs_init_raw_tnodes(dev);
401 yaffs_init_raw_objs(dev);