1 /* $NetBSD: chfs_malloc.c,v 1.4 2012/10/19 12:44:39 ttoth Exp $ */
4 * Copyright (c) 2010 Department of Software Engineering,
5 * University of Szeged, Hungary
6 * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
7 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by the Department of Software Engineering, University of Szeged, Hungary
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 pool_cache_t chfs_vnode_cache
;
39 pool_cache_t chfs_nrefs_cache
;
40 pool_cache_t chfs_flash_vnode_cache
;
41 pool_cache_t chfs_flash_dirent_cache
;
42 pool_cache_t chfs_flash_dnode_cache
;
43 pool_cache_t chfs_node_frag_cache
;
44 pool_cache_t chfs_tmp_dnode_cache
;
45 pool_cache_t chfs_tmp_dnode_info_cache
;
47 /* chfs_alloc_pool_caches - allocating pool caches */
49 chfs_alloc_pool_caches(void)
51 chfs_vnode_cache
= pool_cache_init(
52 sizeof(struct chfs_vnode_cache
),
53 0, 0, 0, "chfs_vnode_cache", NULL
, IPL_NONE
, NULL
, NULL
,
55 if (!chfs_vnode_cache
)
58 chfs_nrefs_cache
= pool_cache_init(
59 (REFS_BLOCK_LEN
+ 1) * sizeof(struct chfs_node_ref
), 0, 0,
60 0, "chfs_nrefs_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
61 if (!chfs_nrefs_cache
)
64 chfs_flash_vnode_cache
= pool_cache_init(
65 sizeof(struct chfs_flash_vnode
), 0, 0, 0,
66 "chfs_flash_vnode_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
67 if (!chfs_flash_vnode_cache
)
70 chfs_flash_dirent_cache
= pool_cache_init(
71 sizeof(struct chfs_flash_dirent_node
), 0, 0, 0,
72 "chfs_flash_dirent_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
73 if (!chfs_flash_dirent_cache
)
74 goto err_flash_dirent
;
76 chfs_flash_dnode_cache
= pool_cache_init(
77 sizeof(struct chfs_flash_data_node
), 0, 0, 0,
78 "chfs_flash_dnode_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
79 if (!chfs_flash_dnode_cache
)
82 chfs_node_frag_cache
= pool_cache_init(
83 sizeof(struct chfs_node_frag
), 0, 0, 0,
84 "chfs_node_frag_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
85 if (!chfs_node_frag_cache
)
88 chfs_tmp_dnode_cache
= pool_cache_init(
89 sizeof(struct chfs_tmp_dnode
), 0, 0, 0,
90 "chfs_tmp_dnode_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
91 if (!chfs_tmp_dnode_cache
)
94 chfs_tmp_dnode_info_cache
= pool_cache_init(
95 sizeof(struct chfs_tmp_dnode_info
), 0, 0, 0,
96 "chfs_tmp_dnode_info_pool", NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
97 if (!chfs_tmp_dnode_info_cache
)
98 goto err_tmp_dnode_info
;
103 pool_cache_destroy(chfs_tmp_dnode_cache
);
105 pool_cache_destroy(chfs_node_frag_cache
);
107 pool_cache_destroy(chfs_flash_dnode_cache
);
109 pool_cache_destroy(chfs_flash_dirent_cache
);
111 pool_cache_destroy(chfs_flash_vnode_cache
);
113 pool_cache_destroy(chfs_nrefs_cache
);
115 pool_cache_destroy(chfs_vnode_cache
);
121 /* chfs_destroy_pool_caches - destroying pool caches */
123 chfs_destroy_pool_caches(void)
125 if (chfs_vnode_cache
)
126 pool_cache_destroy(chfs_vnode_cache
);
128 if (chfs_nrefs_cache
)
129 pool_cache_destroy(chfs_nrefs_cache
);
131 if (chfs_flash_vnode_cache
)
132 pool_cache_destroy(chfs_flash_vnode_cache
);
134 if (chfs_flash_dirent_cache
)
135 pool_cache_destroy(chfs_flash_dirent_cache
);
137 if (chfs_flash_dnode_cache
)
138 pool_cache_destroy(chfs_flash_dnode_cache
);
140 if (chfs_node_frag_cache
)
141 pool_cache_destroy(chfs_node_frag_cache
);
143 if (chfs_tmp_dnode_cache
)
144 pool_cache_destroy(chfs_tmp_dnode_cache
);
146 if (chfs_tmp_dnode_info_cache
)
147 pool_cache_destroy(chfs_tmp_dnode_info_cache
);
150 /* chfs_vnode_cache_alloc - allocating and initializing a vnode cache */
151 struct chfs_vnode_cache
*
152 chfs_vnode_cache_alloc(ino_t vno
)
154 struct chfs_vnode_cache
* vc
;
155 vc
= pool_cache_get(chfs_vnode_cache
, PR_WAITOK
);
157 memset(vc
, 0, sizeof(*vc
));
159 /* vnode cache is the last element of all chain */
161 vc
->dirents
= (void *)vc
;
162 vc
->dnode
= (void *)vc
;
163 TAILQ_INIT(&vc
->scan_dirents
);
164 vc
->highest_version
= 0;
169 /* chfs_vnode_cache_free - freeing a vnode cache */
171 chfs_vnode_cache_free(struct chfs_vnode_cache
*vc
)
173 pool_cache_put(chfs_vnode_cache
, vc
);
177 * chfs_alloc_refblock - allocating a refblock
179 * Returns a pointer of the first element in the block.
181 * We are not allocating just one node ref, instead we allocating REFS_BLOCK_LEN
182 * number of node refs, the last element will be a pointer to the next block.
183 * We do this, because we need a chain of nodes which have been ordered by the
184 * physical address of them.
187 struct chfs_node_ref
*
188 chfs_alloc_refblock(void)
191 struct chfs_node_ref
*nref
;
192 nref
= pool_cache_get(chfs_nrefs_cache
, PR_WAITOK
);
194 for (i
= 0; i
< REFS_BLOCK_LEN
; i
++) {
195 nref
[i
].nref_lnr
= REF_EMPTY_NODE
;
196 nref
[i
].nref_next
= NULL
;
199 nref
[i
].nref_lnr
= REF_LINK_TO_NEXT
;
200 nref
[i
].nref_next
= NULL
;
205 /* chfs_free_refblock - freeing a refblock */
207 chfs_free_refblock(struct chfs_node_ref
*nref
)
209 pool_cache_put(chfs_nrefs_cache
, nref
);
213 * chfs_alloc_node_ref - allocating a node ref from a refblock
215 * Allocating a node ref from a refblock, it there isn't any free element in the
216 * block, a new block will be allocated and be linked to the current block.
218 struct chfs_node_ref
*
219 chfs_alloc_node_ref(struct chfs_eraseblock
*cheb
)
221 struct chfs_node_ref
*nref
, *new, *old
;
222 old
= cheb
->last_node
;
223 nref
= cheb
->last_node
;
226 /* There haven't been any nref allocated for this block yet */
227 nref
= chfs_alloc_refblock();
229 cheb
->first_node
= nref
;
230 cheb
->last_node
= nref
;
231 nref
->nref_lnr
= cheb
->lnr
;
232 KASSERT(cheb
->lnr
== nref
->nref_lnr
);
238 if (nref
->nref_lnr
== REF_LINK_TO_NEXT
) {
239 /* this was the last element, allocate a new block */
240 new = chfs_alloc_refblock();
241 nref
->nref_next
= new;
245 cheb
->last_node
= nref
;
246 nref
->nref_lnr
= cheb
->lnr
;
248 KASSERT(old
->nref_lnr
== nref
->nref_lnr
&&
249 nref
->nref_lnr
== cheb
->lnr
);
254 /* chfs_free_node_refs - freeing an eraseblock's node refs */
256 chfs_free_node_refs(struct chfs_eraseblock
*cheb
)
258 struct chfs_node_ref
*nref
, *block
;
260 block
= nref
= cheb
->first_node
;
263 if (nref
->nref_lnr
== REF_LINK_TO_NEXT
) {
264 nref
= nref
->nref_next
;
265 chfs_free_refblock(block
);
273 /* chfs_alloc_dirent - allocating a directory entry */
275 chfs_alloc_dirent(int namesize
)
277 struct chfs_dirent
*ret
;
278 size_t size
= sizeof(struct chfs_dirent
) + namesize
;
280 ret
= kmem_alloc(size
, KM_SLEEP
);
285 /* chfs_free_dirent - freeing a directory entry */
287 chfs_free_dirent(struct chfs_dirent
*dirent
)
289 size_t size
= sizeof(struct chfs_dirent
) + dirent
->nsize
+ 1;
291 kmem_free(dirent
, size
);
294 /* chfs_alloc_full_dnode - allocating a full data node */
295 struct chfs_full_dnode
*
296 chfs_alloc_full_dnode(void)
298 struct chfs_full_dnode
*ret
;
299 ret
= kmem_alloc(sizeof(struct chfs_full_dnode
), KM_SLEEP
);
305 /* chfs_free_full_dnode - freeing a full data node */
307 chfs_free_full_dnode(struct chfs_full_dnode
*fd
)
309 kmem_free(fd
,(sizeof(struct chfs_full_dnode
)));
312 /* chfs_alloc_flash_vnode - allocating vnode info (used on flash) */
313 struct chfs_flash_vnode
*
314 chfs_alloc_flash_vnode(void)
316 struct chfs_flash_vnode
*ret
;
317 ret
= pool_cache_get(chfs_flash_vnode_cache
, 0);
321 /* chfs_free_flash_vnode - freeing vnode info */
323 chfs_free_flash_vnode(struct chfs_flash_vnode
*fvnode
)
325 pool_cache_put(chfs_flash_vnode_cache
, fvnode
);
328 /* chfs_alloc_flash_dirent - allocating a directory entry (used on flash) */
329 struct chfs_flash_dirent_node
*
330 chfs_alloc_flash_dirent(void)
332 struct chfs_flash_dirent_node
*ret
;
333 ret
= pool_cache_get(chfs_flash_dirent_cache
, 0);
337 /* chfs_free_flash_dirent - freeing a (flash) directory entry */
339 chfs_free_flash_dirent(struct chfs_flash_dirent_node
*fdnode
)
341 pool_cache_put(chfs_flash_dirent_cache
, fdnode
);
344 /* chfs_alloc_flash_dnode - allocating a data node (used on flash) */
345 struct chfs_flash_data_node
*
346 chfs_alloc_flash_dnode(void)
348 struct chfs_flash_data_node
*ret
;
349 ret
= pool_cache_get(chfs_flash_dnode_cache
, 0);
353 /* chfs_free_flash_dnode - freeing a (flash) data node */
355 chfs_free_flash_dnode(struct chfs_flash_data_node
*fdnode
)
357 pool_cache_put(chfs_flash_dnode_cache
, fdnode
);
360 /* chfs_alloc_node_frag - allocating a fragment of a node */
361 struct chfs_node_frag
*
362 chfs_alloc_node_frag(void)
364 struct chfs_node_frag
*ret
;
365 ret
= pool_cache_get(chfs_node_frag_cache
, 0);
369 /* chfs_free_node_frag - freeing a fragment of a node */
371 chfs_free_node_frag(struct chfs_node_frag
*frag
)
373 pool_cache_put(chfs_node_frag_cache
, frag
);
376 /* chfs_alloc_tmp_dnode - allocating a temporarly used dnode */
377 struct chfs_tmp_dnode
*
378 chfs_alloc_tmp_dnode(void)
380 struct chfs_tmp_dnode
*ret
;
381 ret
= pool_cache_get(chfs_tmp_dnode_cache
, 0);
386 /* chfs_free_tmp_dnode - freeing a temporarly used dnode */
388 chfs_free_tmp_dnode(struct chfs_tmp_dnode
*td
)
390 pool_cache_put(chfs_tmp_dnode_cache
, td
);
393 /* chfs_alloc_tmp_dnode_info - allocating a temporarly used dnode descriptor */
394 struct chfs_tmp_dnode_info
*
395 chfs_alloc_tmp_dnode_info(void)
397 struct chfs_tmp_dnode_info
*ret
;
398 ret
= pool_cache_get(chfs_tmp_dnode_info_cache
, 0);
403 /* chfs_free_tmp_dnode_info - freeing a temporarly used dnode descriptor */
405 chfs_free_tmp_dnode_info(struct chfs_tmp_dnode_info
*di
)
407 pool_cache_put(chfs_tmp_dnode_info_cache
, di
);