yaffs trying to recreate timothy_tests after I deleated them.
[yaffs2.git] / yaffs_allocator.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
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.
12  */
13
14 #include "yaffs_allocator.h"
15 #include "yaffs_guts.h"
16 #include "yaffs_trace.h"
17 #include "yportenv.h"
18
19 #ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR
20
21 void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
22 {
23         dev = dev;
24 }
25
26 void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
27 {
28         dev = dev;
29 }
30
31 struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
32 {
33         return (struct yaffs_tnode *)YMALLOC(dev->tnode_size);
34 }
35
36 void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
37 {
38         dev = dev;
39         YFREE(tn);
40 }
41
42 void yaffs_init_raw_objs(struct yaffs_dev *dev)
43 {
44         dev = dev;
45 }
46
47 void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
48 {
49         dev = dev;
50 }
51
52 struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
53 {
54         dev = dev;
55         return (struct yaffs_obj *)YMALLOC(sizeof(struct yaffs_obj));
56 }
57
58 void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
59 {
60
61         dev = dev;
62         YFREE(obj);
63 }
64
65 #else
66
67 struct yaffs_tnode_list {
68         struct yaffs_tnode_list *next;
69         struct yaffs_tnode *tnodes;
70 };
71
72 struct yaffs_obj_list {
73         struct yaffs_obj_list *next;
74         struct yaffs_obj *objects;
75 };
76
77 struct yaffs_allocator {
78         int n_tnodes_created;
79         struct yaffs_tnode *free_tnodes;
80         int n_free_tnodes;
81         struct yaffs_tnode_list *alloc_tnode_list;
82
83         int n_obj_created;
84         struct yaffs_obj *free_objs;
85         int n_free_objects;
86
87         struct yaffs_obj_list *allocated_obj_list;
88 };
89
90 static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
91 {
92
93         struct yaffs_allocator *allocator =
94             (struct yaffs_allocator *)dev->allocator;
95
96         struct yaffs_tnode_list *tmp;
97
98         if (!allocator) {
99                 YBUG();
100                 return;
101         }
102
103         while (allocator->alloc_tnode_list) {
104                 tmp = allocator->alloc_tnode_list->next;
105
106                 YFREE(allocator->alloc_tnode_list->tnodes);
107                 YFREE(allocator->alloc_tnode_list);
108                 allocator->alloc_tnode_list = tmp;
109
110         }
111
112         allocator->free_tnodes = NULL;
113         allocator->n_free_tnodes = 0;
114         allocator->n_tnodes_created = 0;
115 }
116
117 static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
118 {
119         struct yaffs_allocator *allocator = dev->allocator;
120
121         if (allocator) {
122                 allocator->alloc_tnode_list = NULL;
123                 allocator->free_tnodes = NULL;
124                 allocator->n_free_tnodes = 0;
125                 allocator->n_tnodes_created = 0;
126         } else
127                 YBUG();
128 }
129
130 static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
131 {
132         struct yaffs_allocator *allocator =
133             (struct yaffs_allocator *)dev->allocator;
134         int i;
135         struct yaffs_tnode *new_tnodes;
136         u8 *mem;
137         struct yaffs_tnode *curr;
138         struct yaffs_tnode *next;
139         struct yaffs_tnode_list *tnl;
140
141         if (!allocator) {
142                 YBUG();
143                 return YAFFS_FAIL;
144         }
145
146         if (n_tnodes < 1)
147                 return YAFFS_OK;
148
149         /* make these things */
150
151         new_tnodes = YMALLOC(n_tnodes * dev->tnode_size);
152         mem = (u8 *) new_tnodes;
153
154         if (!new_tnodes) {
155                 T(YAFFS_TRACE_ERROR,
156                   (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
157                 return YAFFS_FAIL;
158         }
159
160         /* New hookup for wide tnodes */
161         for (i = 0; i < n_tnodes - 1; i++) {
162                 curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];
163                 next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];
164                 curr->internal[0] = next;
165         }
166
167         curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
168         curr->internal[0] = allocator->free_tnodes;
169         allocator->free_tnodes = (struct yaffs_tnode *)mem;
170
171         allocator->n_free_tnodes += n_tnodes;
172         allocator->n_tnodes_created += n_tnodes;
173
174         /* Now add this bunch of tnodes to a list for freeing up.
175          * NB If we can't add this to the management list it isn't fatal
176          * but it just means we can't free this bunch of tnodes later.
177          */
178
179         tnl = YMALLOC(sizeof(struct yaffs_tnode_list));
180         if (!tnl) {
181                 T(YAFFS_TRACE_ERROR,
182                   (TSTR
183                    ("yaffs: Could not add tnodes to management list" TENDSTR)));
184                 return YAFFS_FAIL;
185         } else {
186                 tnl->tnodes = new_tnodes;
187                 tnl->next = allocator->alloc_tnode_list;
188                 allocator->alloc_tnode_list = tnl;
189         }
190
191         T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
192
193         return YAFFS_OK;
194 }
195
196 struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
197 {
198         struct yaffs_allocator *allocator =
199             (struct yaffs_allocator *)dev->allocator;
200         struct yaffs_tnode *tn = NULL;
201
202         if (!allocator) {
203                 YBUG();
204                 return NULL;
205         }
206
207         /* If there are none left make more */
208         if (!allocator->free_tnodes)
209                 yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);
210
211         if (allocator->free_tnodes) {
212                 tn = allocator->free_tnodes;
213                 allocator->free_tnodes = allocator->free_tnodes->internal[0];
214                 allocator->n_free_tnodes--;
215         }
216
217         return tn;
218 }
219
220 /* FreeTnode frees up a tnode and puts it back on the free list */
221 void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
222 {
223         struct yaffs_allocator *allocator = dev->allocator;
224
225         if (!allocator) {
226                 YBUG();
227                 return;
228         }
229
230         if (tn) {
231                 tn->internal[0] = allocator->free_tnodes;
232                 allocator->free_tnodes = tn;
233                 allocator->n_free_tnodes++;
234         }
235         dev->checkpoint_blocks_required = 0;    /* force recalculation */
236 }
237
238 static void yaffs_init_raw_objs(struct yaffs_dev *dev)
239 {
240         struct yaffs_allocator *allocator = dev->allocator;
241
242         if (allocator) {
243                 allocator->allocated_obj_list = NULL;
244                 allocator->free_objs = NULL;
245                 allocator->n_free_objects = 0;
246         } else
247                 YBUG();
248 }
249
250 static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
251 {
252         struct yaffs_allocator *allocator = dev->allocator;
253         struct yaffs_obj_list *tmp;
254
255         if (!allocator) {
256                 YBUG();
257                 return;
258         }
259
260         while (allocator->allocated_obj_list) {
261                 tmp = allocator->allocated_obj_list->next;
262                 YFREE(allocator->allocated_obj_list->objects);
263                 YFREE(allocator->allocated_obj_list);
264
265                 allocator->allocated_obj_list = tmp;
266         }
267
268         allocator->free_objs = NULL;
269         allocator->n_free_objects = 0;
270         allocator->n_obj_created = 0;
271 }
272
273 static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
274 {
275         struct yaffs_allocator *allocator = dev->allocator;
276
277         int i;
278         struct yaffs_obj *new_objs;
279         struct yaffs_obj_list *list;
280
281         if (!allocator) {
282                 YBUG();
283                 return YAFFS_FAIL;
284         }
285
286         if (n_obj < 1)
287                 return YAFFS_OK;
288
289         /* make these things */
290         new_objs = YMALLOC(n_obj * sizeof(struct yaffs_obj));
291         list = YMALLOC(sizeof(struct yaffs_obj_list));
292
293         if (!new_objs || !list) {
294                 if (new_objs) {
295                         YFREE(new_objs);
296                         new_objs = NULL;
297                 }
298                 if (list) {
299                         YFREE(list);
300                         list = NULL;
301                 }
302                 T(YAFFS_TRACE_ALLOCATE,
303                   (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
304                 return YAFFS_FAIL;
305         }
306
307         /* Hook them into the free list */
308         for (i = 0; i < n_obj - 1; i++) {
309                 new_objs[i].siblings.next =
310                     (struct list_head *)(&new_objs[i + 1]);
311         }
312
313         new_objs[n_obj - 1].siblings.next = (void *)allocator->free_objs;
314         allocator->free_objs = new_objs;
315         allocator->n_free_objects += n_obj;
316         allocator->n_obj_created += n_obj;
317
318         /* Now add this bunch of Objects to a list for freeing up. */
319
320         list->objects = new_objs;
321         list->next = allocator->allocated_obj_list;
322         allocator->allocated_obj_list = list;
323
324         return YAFFS_OK;
325 }
326
327 struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
328 {
329         struct yaffs_obj *obj = NULL;
330         struct yaffs_allocator *allocator = dev->allocator;
331
332         if (!allocator) {
333                 YBUG();
334                 return obj;
335         }
336
337         /* If there are none left make more */
338         if (!allocator->free_objs)
339                 yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
340
341         if (allocator->free_objs) {
342                 obj = allocator->free_objs;
343                 allocator->free_objs =
344                     (struct yaffs_obj *)(allocator->free_objs->siblings.next);
345                 allocator->n_free_objects--;
346         }
347
348         return obj;
349 }
350
351 void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
352 {
353
354         struct yaffs_allocator *allocator = dev->allocator;
355
356         if (!allocator)
357                 YBUG();
358         else {
359                 /* Link into the free list. */
360                 obj->siblings.next = (struct list_head *)(allocator->free_objs);
361                 allocator->free_objs = obj;
362                 allocator->n_free_objects++;
363         }
364 }
365
366 void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
367 {
368         if (dev->allocator) {
369                 yaffs_deinit_raw_tnodes(dev);
370                 yaffs_deinit_raw_objs(dev);
371
372                 YFREE(dev->allocator);
373                 dev->allocator = NULL;
374         } else
375                 YBUG();
376 }
377
378 void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
379 {
380         struct yaffs_allocator *allocator;
381
382         if (!dev->allocator) {
383                 allocator = YMALLOC(sizeof(struct yaffs_allocator));
384                 if (allocator) {
385                         dev->allocator = allocator;
386                         yaffs_init_raw_tnodes(dev);
387                         yaffs_init_raw_objs(dev);
388                 }
389         } else
390                 YBUG();
391 }
392
393 #endif