xref: /OK3568_Linux_fs/kernel/fs/jffs2/malloc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * JFFS2 -- Journalling Flash File System, Version 2.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright © 2001-2007 Red Hat, Inc.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Created by David Woodhouse <dwmw2@infradead.org>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * For licensing information, see the file 'LICENCE' in this directory.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/jffs2.h>
18*4882a593Smuzhiyun #include "nodelist.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /* These are initialised to NULL in the kernel startup code.
21*4882a593Smuzhiyun    If you're porting to other operating systems, beware */
22*4882a593Smuzhiyun static struct kmem_cache *full_dnode_slab;
23*4882a593Smuzhiyun static struct kmem_cache *raw_dirent_slab;
24*4882a593Smuzhiyun static struct kmem_cache *raw_inode_slab;
25*4882a593Smuzhiyun static struct kmem_cache *tmp_dnode_info_slab;
26*4882a593Smuzhiyun static struct kmem_cache *raw_node_ref_slab;
27*4882a593Smuzhiyun static struct kmem_cache *node_frag_slab;
28*4882a593Smuzhiyun static struct kmem_cache *inode_cache_slab;
29*4882a593Smuzhiyun #ifdef CONFIG_JFFS2_FS_XATTR
30*4882a593Smuzhiyun static struct kmem_cache *xattr_datum_cache;
31*4882a593Smuzhiyun static struct kmem_cache *xattr_ref_cache;
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
jffs2_create_slab_caches(void)34*4882a593Smuzhiyun int __init jffs2_create_slab_caches(void)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	full_dnode_slab = kmem_cache_create("jffs2_full_dnode",
37*4882a593Smuzhiyun 					    sizeof(struct jffs2_full_dnode),
38*4882a593Smuzhiyun 					    0, 0, NULL);
39*4882a593Smuzhiyun 	if (!full_dnode_slab)
40*4882a593Smuzhiyun 		goto err;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent",
43*4882a593Smuzhiyun 					    sizeof(struct jffs2_raw_dirent),
44*4882a593Smuzhiyun 					    0, SLAB_HWCACHE_ALIGN, NULL);
45*4882a593Smuzhiyun 	if (!raw_dirent_slab)
46*4882a593Smuzhiyun 		goto err;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	raw_inode_slab = kmem_cache_create("jffs2_raw_inode",
49*4882a593Smuzhiyun 					   sizeof(struct jffs2_raw_inode),
50*4882a593Smuzhiyun 					   0, SLAB_HWCACHE_ALIGN, NULL);
51*4882a593Smuzhiyun 	if (!raw_inode_slab)
52*4882a593Smuzhiyun 		goto err;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode",
55*4882a593Smuzhiyun 						sizeof(struct jffs2_tmp_dnode_info),
56*4882a593Smuzhiyun 						0, 0, NULL);
57*4882a593Smuzhiyun 	if (!tmp_dnode_info_slab)
58*4882a593Smuzhiyun 		goto err;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
61*4882a593Smuzhiyun 					      sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
62*4882a593Smuzhiyun 					      0, 0, NULL);
63*4882a593Smuzhiyun 	if (!raw_node_ref_slab)
64*4882a593Smuzhiyun 		goto err;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	node_frag_slab = kmem_cache_create("jffs2_node_frag",
67*4882a593Smuzhiyun 					   sizeof(struct jffs2_node_frag),
68*4882a593Smuzhiyun 					   0, 0, NULL);
69*4882a593Smuzhiyun 	if (!node_frag_slab)
70*4882a593Smuzhiyun 		goto err;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
73*4882a593Smuzhiyun 					     sizeof(struct jffs2_inode_cache),
74*4882a593Smuzhiyun 					     0, 0, NULL);
75*4882a593Smuzhiyun 	if (!inode_cache_slab)
76*4882a593Smuzhiyun 		goto err;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #ifdef CONFIG_JFFS2_FS_XATTR
79*4882a593Smuzhiyun 	xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
80*4882a593Smuzhiyun 					     sizeof(struct jffs2_xattr_datum),
81*4882a593Smuzhiyun 					     0, 0, NULL);
82*4882a593Smuzhiyun 	if (!xattr_datum_cache)
83*4882a593Smuzhiyun 		goto err;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
86*4882a593Smuzhiyun 					   sizeof(struct jffs2_xattr_ref),
87*4882a593Smuzhiyun 					   0, 0, NULL);
88*4882a593Smuzhiyun 	if (!xattr_ref_cache)
89*4882a593Smuzhiyun 		goto err;
90*4882a593Smuzhiyun #endif
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	return 0;
93*4882a593Smuzhiyun  err:
94*4882a593Smuzhiyun 	jffs2_destroy_slab_caches();
95*4882a593Smuzhiyun 	return -ENOMEM;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
jffs2_destroy_slab_caches(void)98*4882a593Smuzhiyun void jffs2_destroy_slab_caches(void)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	kmem_cache_destroy(full_dnode_slab);
101*4882a593Smuzhiyun 	kmem_cache_destroy(raw_dirent_slab);
102*4882a593Smuzhiyun 	kmem_cache_destroy(raw_inode_slab);
103*4882a593Smuzhiyun 	kmem_cache_destroy(tmp_dnode_info_slab);
104*4882a593Smuzhiyun 	kmem_cache_destroy(raw_node_ref_slab);
105*4882a593Smuzhiyun 	kmem_cache_destroy(node_frag_slab);
106*4882a593Smuzhiyun 	kmem_cache_destroy(inode_cache_slab);
107*4882a593Smuzhiyun #ifdef CONFIG_JFFS2_FS_XATTR
108*4882a593Smuzhiyun 	kmem_cache_destroy(xattr_datum_cache);
109*4882a593Smuzhiyun 	kmem_cache_destroy(xattr_ref_cache);
110*4882a593Smuzhiyun #endif
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
jffs2_alloc_full_dirent(int namesize)113*4882a593Smuzhiyun struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	struct jffs2_full_dirent *ret;
116*4882a593Smuzhiyun 	ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL);
117*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
118*4882a593Smuzhiyun 	return ret;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
jffs2_free_full_dirent(struct jffs2_full_dirent * x)121*4882a593Smuzhiyun void jffs2_free_full_dirent(struct jffs2_full_dirent *x)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
124*4882a593Smuzhiyun 	kfree(x);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
jffs2_alloc_full_dnode(void)127*4882a593Smuzhiyun struct jffs2_full_dnode *jffs2_alloc_full_dnode(void)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct jffs2_full_dnode *ret;
130*4882a593Smuzhiyun 	ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL);
131*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
132*4882a593Smuzhiyun 	return ret;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
jffs2_free_full_dnode(struct jffs2_full_dnode * x)135*4882a593Smuzhiyun void jffs2_free_full_dnode(struct jffs2_full_dnode *x)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
138*4882a593Smuzhiyun 	kmem_cache_free(full_dnode_slab, x);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
jffs2_alloc_raw_dirent(void)141*4882a593Smuzhiyun struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct jffs2_raw_dirent *ret;
144*4882a593Smuzhiyun 	ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL);
145*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
146*4882a593Smuzhiyun 	return ret;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
jffs2_free_raw_dirent(struct jffs2_raw_dirent * x)149*4882a593Smuzhiyun void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
152*4882a593Smuzhiyun 	kmem_cache_free(raw_dirent_slab, x);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
jffs2_alloc_raw_inode(void)155*4882a593Smuzhiyun struct jffs2_raw_inode *jffs2_alloc_raw_inode(void)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct jffs2_raw_inode *ret;
158*4882a593Smuzhiyun 	ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL);
159*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
160*4882a593Smuzhiyun 	return ret;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
jffs2_free_raw_inode(struct jffs2_raw_inode * x)163*4882a593Smuzhiyun void jffs2_free_raw_inode(struct jffs2_raw_inode *x)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
166*4882a593Smuzhiyun 	kmem_cache_free(raw_inode_slab, x);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
jffs2_alloc_tmp_dnode_info(void)169*4882a593Smuzhiyun struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct jffs2_tmp_dnode_info *ret;
172*4882a593Smuzhiyun 	ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL);
173*4882a593Smuzhiyun 	dbg_memalloc("%p\n",
174*4882a593Smuzhiyun 		ret);
175*4882a593Smuzhiyun 	return ret;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info * x)178*4882a593Smuzhiyun void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
181*4882a593Smuzhiyun 	kmem_cache_free(tmp_dnode_info_slab, x);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
jffs2_alloc_refblock(void)184*4882a593Smuzhiyun static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	struct jffs2_raw_node_ref *ret;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
189*4882a593Smuzhiyun 	if (ret) {
190*4882a593Smuzhiyun 		int i = 0;
191*4882a593Smuzhiyun 		for (i=0; i < REFS_PER_BLOCK; i++) {
192*4882a593Smuzhiyun 			ret[i].flash_offset = REF_EMPTY_NODE;
193*4882a593Smuzhiyun 			ret[i].next_in_ino = NULL;
194*4882a593Smuzhiyun 		}
195*4882a593Smuzhiyun 		ret[i].flash_offset = REF_LINK_NODE;
196*4882a593Smuzhiyun 		ret[i].next_in_ino = NULL;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 	return ret;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
jffs2_prealloc_raw_node_refs(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb,int nr)201*4882a593Smuzhiyun int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
202*4882a593Smuzhiyun 				 struct jffs2_eraseblock *jeb, int nr)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	struct jffs2_raw_node_ref **p, *ref;
205*4882a593Smuzhiyun 	int i = nr;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	dbg_memalloc("%d\n", nr);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	p = &jeb->last_node;
210*4882a593Smuzhiyun 	ref = *p;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	/* If jeb->last_node is really a valid node then skip over it */
215*4882a593Smuzhiyun 	if (ref && ref->flash_offset != REF_EMPTY_NODE)
216*4882a593Smuzhiyun 		ref++;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	while (i) {
219*4882a593Smuzhiyun 		if (!ref) {
220*4882a593Smuzhiyun 			dbg_memalloc("Allocating new refblock linked from %p\n", p);
221*4882a593Smuzhiyun 			ref = *p = jffs2_alloc_refblock();
222*4882a593Smuzhiyun 			if (!ref)
223*4882a593Smuzhiyun 				return -ENOMEM;
224*4882a593Smuzhiyun 		}
225*4882a593Smuzhiyun 		if (ref->flash_offset == REF_LINK_NODE) {
226*4882a593Smuzhiyun 			p = &ref->next_in_ino;
227*4882a593Smuzhiyun 			ref = *p;
228*4882a593Smuzhiyun 			continue;
229*4882a593Smuzhiyun 		}
230*4882a593Smuzhiyun 		i--;
231*4882a593Smuzhiyun 		ref++;
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 	jeb->allocated_refs = nr;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n",
236*4882a593Smuzhiyun 		  nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset,
237*4882a593Smuzhiyun 		  jeb->last_node->next_in_ino);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
jffs2_free_refblock(struct jffs2_raw_node_ref * x)242*4882a593Smuzhiyun void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
245*4882a593Smuzhiyun 	kmem_cache_free(raw_node_ref_slab, x);
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
jffs2_alloc_node_frag(void)248*4882a593Smuzhiyun struct jffs2_node_frag *jffs2_alloc_node_frag(void)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	struct jffs2_node_frag *ret;
251*4882a593Smuzhiyun 	ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL);
252*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
253*4882a593Smuzhiyun 	return ret;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
jffs2_free_node_frag(struct jffs2_node_frag * x)256*4882a593Smuzhiyun void jffs2_free_node_frag(struct jffs2_node_frag *x)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
259*4882a593Smuzhiyun 	kmem_cache_free(node_frag_slab, x);
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun 
jffs2_alloc_inode_cache(void)262*4882a593Smuzhiyun struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	struct jffs2_inode_cache *ret;
265*4882a593Smuzhiyun 	ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL);
266*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ret);
267*4882a593Smuzhiyun 	return ret;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
jffs2_free_inode_cache(struct jffs2_inode_cache * x)270*4882a593Smuzhiyun void jffs2_free_inode_cache(struct jffs2_inode_cache *x)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	dbg_memalloc("%p\n", x);
273*4882a593Smuzhiyun 	kmem_cache_free(inode_cache_slab, x);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun #ifdef CONFIG_JFFS2_FS_XATTR
jffs2_alloc_xattr_datum(void)277*4882a593Smuzhiyun struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	struct jffs2_xattr_datum *xd;
280*4882a593Smuzhiyun 	xd = kmem_cache_zalloc(xattr_datum_cache, GFP_KERNEL);
281*4882a593Smuzhiyun 	dbg_memalloc("%p\n", xd);
282*4882a593Smuzhiyun 	if (!xd)
283*4882a593Smuzhiyun 		return NULL;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	xd->class = RAWNODE_CLASS_XATTR_DATUM;
286*4882a593Smuzhiyun 	xd->node = (void *)xd;
287*4882a593Smuzhiyun 	INIT_LIST_HEAD(&xd->xindex);
288*4882a593Smuzhiyun 	return xd;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
jffs2_free_xattr_datum(struct jffs2_xattr_datum * xd)291*4882a593Smuzhiyun void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	dbg_memalloc("%p\n", xd);
294*4882a593Smuzhiyun 	kmem_cache_free(xattr_datum_cache, xd);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
jffs2_alloc_xattr_ref(void)297*4882a593Smuzhiyun struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct jffs2_xattr_ref *ref;
300*4882a593Smuzhiyun 	ref = kmem_cache_zalloc(xattr_ref_cache, GFP_KERNEL);
301*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ref);
302*4882a593Smuzhiyun 	if (!ref)
303*4882a593Smuzhiyun 		return NULL;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	ref->class = RAWNODE_CLASS_XATTR_REF;
306*4882a593Smuzhiyun 	ref->node = (void *)ref;
307*4882a593Smuzhiyun 	return ref;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
jffs2_free_xattr_ref(struct jffs2_xattr_ref * ref)310*4882a593Smuzhiyun void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun 	dbg_memalloc("%p\n", ref);
313*4882a593Smuzhiyun 	kmem_cache_free(xattr_ref_cache, ref);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun #endif
316