yaffs Fix readdir locking
[yaffs2.git] / yaffs_linux_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 #include "yaffs_linux.h"
22 /*
23  * Start out with the same allocator as yaffs direct.
24  * Todo: Change to Linux slab allocator.
25  */
26
27
28
29 #define NAMELEN  20
30 struct yaffs_AllocatorStruct {
31         char tnode_name[NAMELEN+1];
32         char object_name[NAMELEN+1];
33         struct kmem_cache *tnode_cache;
34         struct kmem_cache *object_cache;
35 };
36
37 typedef struct yaffs_AllocatorStruct yaffs_Allocator;
38
39 int mount_id;
40
41 void yaffs_DeinitialiseRawTnodesAndObjects(yaffs_Device *dev)
42 {
43         yaffs_Allocator *allocator = (yaffs_Allocator *)dev->allocator;
44
45         T(YAFFS_TRACE_ALLOCATE,(TSTR("Deinitialising yaffs allocator\n")));
46
47         if(allocator){
48                 if(allocator->tnode_cache){
49                         kmem_cache_destroy(allocator->tnode_cache);
50                         allocator->tnode_cache = NULL;
51                 } else {
52                         T(YAFFS_TRACE_ALWAYS,
53                                 (TSTR("NULL tnode cache\n")));
54                         YBUG();
55                 }
56
57                 if(allocator->object_cache){
58                         kmem_cache_destroy(allocator->object_cache);
59                         allocator->object_cache = NULL;
60                 } else {
61                         T(YAFFS_TRACE_ALWAYS,
62                                 (TSTR("NULL object cache\n")));
63                         YBUG();
64                 }
65                 
66                 YFREE(allocator);
67
68         } else {
69                 T(YAFFS_TRACE_ALWAYS,
70                         (TSTR("Deinitialising NULL allocator\n")));
71                 YBUG();
72         }               
73         dev->allocator = NULL;
74 }
75
76
77 static void fake_ctor0(void *data){data = data;}
78 static void fake_ctor1(void *data){data = data;}
79 static void fake_ctor2(void *data){data = data;}
80 static void fake_ctor3(void *data){data = data;}
81 static void fake_ctor4(void *data){data = data;}
82 static void fake_ctor5(void *data){data = data;}
83 static void fake_ctor6(void *data){data = data;}
84 static void fake_ctor7(void *data){data = data;}
85 static void fake_ctor8(void *data){data = data;}
86 static void fake_ctor9(void *data){data = data;}
87
88 static void (*fake_ctor_list[10]) (void *) = {
89         fake_ctor0,
90         fake_ctor1,
91         fake_ctor2,
92         fake_ctor3,
93         fake_ctor4,
94         fake_ctor5,
95         fake_ctor6,
96         fake_ctor7,
97         fake_ctor8,
98         fake_ctor9,
99 };
100
101 void yaffs_InitialiseRawTnodesAndObjects(yaffs_Device *dev)
102 {
103         yaffs_Allocator *allocator;
104         unsigned mount_id = yaffs_DeviceToContext(dev)->mount_id;
105         
106         T(YAFFS_TRACE_ALLOCATE,(TSTR("Initialising yaffs allocator\n")));
107
108         if(dev->allocator)
109                 YBUG();
110         else if(mount_id >= 10){
111                 T(YAFFS_TRACE_ALWAYS,(TSTR("Bad mount_id %u\n"),mount_id));
112         } else {
113                  allocator = YMALLOC(sizeof(yaffs_Allocator));
114                  memset(allocator,0,sizeof(yaffs_Allocator));
115                  dev->allocator = allocator;
116                 
117                 if(!dev->allocator){
118                         T(YAFFS_TRACE_ALWAYS,
119                                 (TSTR("yaffs allocator creation failed\n")));
120                         YBUG();
121                         return;
122                         
123                 }
124                 
125                 sprintf(allocator->tnode_name,"yaffs_t_%u",mount_id);
126                 sprintf(allocator->object_name,"yaffs_o_%u",mount_id);
127                 
128                 allocator->tnode_cache = 
129                         kmem_cache_create(allocator->tnode_name,
130                                 dev->tnodeSize,
131                                 0, 0,
132                                 fake_ctor_list[mount_id]);
133                 if(allocator->tnode_cache)
134                         T(YAFFS_TRACE_ALLOCATE,
135                                 (TSTR("tnode cache \"%s\" %p\n"),
136                                 allocator->tnode_name,allocator->tnode_cache));
137                 else {
138                         T(YAFFS_TRACE_ALWAYS,
139                                 (TSTR("yaffs cache creation failed\n")));
140                         YBUG();
141                 }
142
143
144                 allocator->object_cache = 
145                         kmem_cache_create(allocator->object_name,
146                                 sizeof(yaffs_Object),
147                                 0, 0,
148                                 fake_ctor_list[mount_id]);
149
150                 if(allocator->object_cache)
151                         T(YAFFS_TRACE_ALLOCATE,
152                                 (TSTR("object cache \"%s\" %p\n"),
153                                 allocator->object_name,allocator->object_cache));
154
155                 else {
156                         T(YAFFS_TRACE_ALWAYS,
157                                 (TSTR("yaffs cache creation failed\n")));
158                         YBUG();
159                 }
160         } 
161 }
162
163
164 yaffs_Tnode *yaffs_AllocateRawTnode(yaffs_Device *dev)
165 {
166         yaffs_Allocator *allocator = dev->allocator;
167         if(!allocator || !allocator->tnode_cache){
168                 YBUG();
169                 return NULL;
170         }
171         return kmem_cache_alloc(allocator->tnode_cache, GFP_NOFS);
172 }
173
174 void yaffs_FreeRawTnode(yaffs_Device *dev, yaffs_Tnode *tn)
175 {
176         yaffs_Allocator *allocator = dev->allocator;
177         kmem_cache_free(allocator->tnode_cache,tn);
178 }
179
180 yaffs_Object *yaffs_AllocateRawObject(yaffs_Device *dev)
181 {
182         yaffs_Allocator *allocator = dev->allocator;
183         if(!allocator){
184                 YBUG();
185                 return NULL;
186         }
187         if(!allocator->object_cache){
188                 YBUG();
189                 return NULL;
190         }
191         return kmem_cache_alloc(allocator->object_cache, GFP_NOFS);
192 }
193
194 void yaffs_FreeRawObject(yaffs_Device *dev, yaffs_Object *obj)
195 {
196         yaffs_Allocator *allocator = dev->allocator;
197         kmem_cache_free(allocator->object_cache,obj);
198 }