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

Archive Download this file



interactive