1 /* $NetBSD: chfs_malloc.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $ */ 2 3 /*- 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> 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by the Department of Software Engineering, University of Szeged, Hungary 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 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. 21 * 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 32 * SUCH DAMAGE. 33 */ 34 35 #include "chfs.h" 36 #include <sys/pool.h> 37 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; 46 47 int 48 chfs_alloc_pool_caches(void) 49 { 50 chfs_vnode_cache = pool_cache_init( 51 sizeof(struct chfs_vnode_cache), 52 0, 0, 0, "chfs_vnode_cache", NULL, IPL_NONE, NULL, NULL, 53 NULL); 54 if (!chfs_vnode_cache) 55 goto err_vnode; 56 57 chfs_nrefs_cache = pool_cache_init( 58 (REFS_BLOCK_LEN + 1) * sizeof(struct chfs_node_ref), 0, 0, 59 0, "chfs_nrefs_pool", NULL, IPL_NONE, NULL, NULL, NULL); 60 if (!chfs_nrefs_cache) 61 goto err_nrefs; 62 63 chfs_flash_vnode_cache = pool_cache_init( 64 sizeof(struct chfs_flash_vnode), 0, 0, 0, 65 "chfs_flash_vnode_pool", NULL, IPL_NONE, NULL, NULL, NULL); 66 if (!chfs_flash_vnode_cache) 67 goto err_flash_vnode; 68 69 chfs_flash_dirent_cache = pool_cache_init( 70 sizeof(struct chfs_flash_dirent_node), 0, 0, 0, 71 "chfs_flash_dirent_pool", NULL, IPL_NONE, NULL, NULL, NULL); 72 if (!chfs_flash_dirent_cache) 73 goto err_flash_dirent; 74 75 chfs_flash_dnode_cache = pool_cache_init( 76 sizeof(struct chfs_flash_data_node), 0, 0, 0, 77 "chfs_flash_dnode_pool", NULL, IPL_NONE, NULL, NULL, NULL); 78 if (!chfs_flash_dnode_cache) 79 goto err_flash_dnode; 80 81 chfs_node_frag_cache = pool_cache_init( 82 sizeof(struct chfs_node_frag), 0, 0, 0, 83 "chfs_node_frag_pool", NULL, IPL_NONE, NULL, NULL, NULL); 84 if (!chfs_node_frag_cache) 85 goto err_node_frag; 86 87 chfs_tmp_dnode_cache = pool_cache_init( 88 sizeof(struct chfs_tmp_dnode), 0, 0, 0, 89 "chfs_tmp_dnode_pool", NULL, IPL_NONE, NULL, NULL, NULL); 90 if (!chfs_tmp_dnode_cache) 91 goto err_tmp_dnode; 92 93 chfs_tmp_dnode_info_cache = pool_cache_init( 94 sizeof(struct chfs_tmp_dnode_info), 0, 0, 0, 95 "chfs_tmp_dnode_info_pool", NULL, IPL_NONE, NULL, NULL, NULL); 96 if (!chfs_tmp_dnode_info_cache) 97 goto err_tmp_dnode_info; 98 99 return 0; 100 101 err_tmp_dnode_info: 102 pool_cache_destroy(chfs_tmp_dnode_cache); 103 err_tmp_dnode: 104 pool_cache_destroy(chfs_node_frag_cache); 105 err_node_frag: 106 pool_cache_destroy(chfs_flash_dnode_cache); 107 err_flash_dnode: 108 pool_cache_destroy(chfs_flash_dirent_cache); 109 err_flash_dirent: 110 pool_cache_destroy(chfs_flash_vnode_cache); 111 err_flash_vnode: 112 pool_cache_destroy(chfs_nrefs_cache); 113 err_nrefs: 114 pool_cache_destroy(chfs_vnode_cache); 115 err_vnode: 116 117 return ENOMEM; 118 } 119 120 void 121 chfs_destroy_pool_caches(void) 122 { 123 if (chfs_vnode_cache) 124 pool_cache_destroy(chfs_vnode_cache); 125 126 if (chfs_nrefs_cache) 127 pool_cache_destroy(chfs_nrefs_cache); 128 129 if (chfs_flash_vnode_cache) 130 pool_cache_destroy(chfs_flash_vnode_cache); 131 132 if (chfs_flash_dirent_cache) 133 pool_cache_destroy(chfs_flash_dirent_cache); 134 135 if (chfs_flash_dnode_cache) 136 pool_cache_destroy(chfs_flash_dnode_cache); 137 138 if (chfs_node_frag_cache) 139 pool_cache_destroy(chfs_node_frag_cache); 140 141 if (chfs_tmp_dnode_cache) 142 pool_cache_destroy(chfs_tmp_dnode_cache); 143 144 if (chfs_tmp_dnode_info_cache) 145 pool_cache_destroy(chfs_tmp_dnode_info_cache); 146 } 147 148 struct chfs_vnode_cache * 149 chfs_vnode_cache_alloc(ino_t vno) 150 { 151 struct chfs_vnode_cache* vc; 152 vc = pool_cache_get(chfs_vnode_cache, PR_WAITOK); 153 154 memset(vc, 0, sizeof(*vc)); 155 vc->vno = vno; 156 vc->v = (void *)vc; 157 vc->dirents = (void *)vc; 158 vc->dnode = (void *)vc; 159 TAILQ_INIT(&vc->scan_dirents); 160 vc->highest_version = 0; 161 162 return vc; 163 } 164 165 void 166 chfs_vnode_cache_free(struct chfs_vnode_cache *vc) 167 { 168 //kmem_free(vc->vno_version, sizeof(uint64_t)); 169 pool_cache_put(chfs_vnode_cache, vc); 170 } 171 172 /** 173 * chfs_alloc_refblock - allocating a refblock 174 * 175 * Returns a pointer of the first element in the block. 176 * 177 * We are not allocating just one node ref, instead we allocating REFS_BLOCK_LEN 178 * number of node refs, the last element will be a pointer to the next block. 179 * We do this, because we need a chain of nodes which have been ordered by the 180 * physical address of them. 181 * 182 */ 183 struct chfs_node_ref* 184 chfs_alloc_refblock(void) 185 { 186 int i; 187 struct chfs_node_ref *nref; 188 nref = pool_cache_get(chfs_nrefs_cache, PR_WAITOK); 189 190 for (i = 0; i < REFS_BLOCK_LEN; i++) { 191 nref[i].nref_lnr = REF_EMPTY_NODE; 192 nref[i].nref_next = NULL; 193 } 194 i = REFS_BLOCK_LEN; 195 nref[i].nref_lnr = REF_LINK_TO_NEXT; 196 nref[i].nref_next = NULL; 197 198 return nref; 199 } 200 201 /** 202 * chfs_free_refblock - freeing a refblock 203 */ 204 void 205 chfs_free_refblock(struct chfs_node_ref *nref) 206 { 207 pool_cache_put(chfs_nrefs_cache, nref); 208 } 209 210 /** 211 * chfs_alloc_node_ref - allocating a node ref from a refblock 212 * @cheb: eraseblock information structure 213 * 214 * Allocating a node ref from a refblock, it there isn't any free element in the 215 * block, a new block will be allocated and be linked to the current block. 216 */ 217 struct chfs_node_ref* 218 chfs_alloc_node_ref(struct chfs_eraseblock *cheb) 219 { 220 struct chfs_node_ref *nref, *new, *old; 221 old = cheb->last_node; 222 nref = cheb->last_node; 223 224 if (!nref) { 225 //There haven't been any nref allocated for this block yet 226 nref = chfs_alloc_refblock(); 227 228 cheb->first_node = nref; 229 cheb->last_node = nref; 230 nref->nref_lnr = cheb->lnr; 231 KASSERT(cheb->lnr == nref->nref_lnr); 232 233 return nref; 234 } 235 236 nref++; 237 if (nref->nref_lnr == REF_LINK_TO_NEXT) { 238 new = chfs_alloc_refblock(); 239 nref->nref_next = new; 240 nref = new; 241 } 242 243 cheb->last_node = nref; 244 nref->nref_lnr = cheb->lnr; 245 246 KASSERT(old->nref_lnr == nref->nref_lnr && 247 nref->nref_lnr == cheb->lnr); 248 249 return nref; 250 } 251 252 /** 253 * chfs_free_node_refs - freeing an eraseblock's node refs 254 * @cheb: eraseblock information structure 255 */ 256 void 257 chfs_free_node_refs(struct chfs_eraseblock *cheb) 258 { 259 struct chfs_node_ref *nref, *block; 260 261 block = nref = cheb->first_node; 262 263 while (nref) { 264 if (nref->nref_lnr == REF_LINK_TO_NEXT) { 265 nref = nref->nref_next; 266 chfs_free_refblock(block); 267 block = nref; 268 continue; 269 } 270 nref++; 271 } 272 } 273 274 struct chfs_dirent* 275 chfs_alloc_dirent(int namesize) 276 { 277 struct chfs_dirent *ret; 278 size_t size = sizeof(struct chfs_dirent) + namesize; 279 280 ret = kmem_alloc(size, KM_SLEEP); 281 //ret->alloc_size = size; 282 283 return ret; 284 } 285 286 void 287 chfs_free_dirent(struct chfs_dirent *dirent) 288 { 289 //size_t size = dirent->alloc_size; 290 size_t size = sizeof(struct chfs_dirent) + dirent->nsize + 1; 291 292 kmem_free(dirent, size); 293 } 294 295 struct chfs_full_dnode* 296 chfs_alloc_full_dnode(void) 297 { 298 struct chfs_full_dnode *ret; 299 ret = kmem_alloc(sizeof(struct chfs_full_dnode), KM_SLEEP); 300 ret->nref = NULL; 301 ret->frags = 0; 302 return ret; 303 } 304 305 void 306 chfs_free_full_dnode(struct chfs_full_dnode *fd) 307 { 308 kmem_free(fd,(sizeof(struct chfs_full_dnode))); 309 } 310 311 struct chfs_flash_vnode* 312 chfs_alloc_flash_vnode(void) 313 { 314 struct chfs_flash_vnode *ret; 315 ret = pool_cache_get(chfs_flash_vnode_cache, 0); 316 return ret; 317 } 318 319 void 320 chfs_free_flash_vnode(struct chfs_flash_vnode *fvnode) 321 { 322 pool_cache_put(chfs_flash_vnode_cache, fvnode); 323 } 324 325 struct chfs_flash_dirent_node* 326 chfs_alloc_flash_dirent(void) 327 { 328 struct chfs_flash_dirent_node *ret; 329 ret = pool_cache_get(chfs_flash_dirent_cache, 0); 330 return ret; 331 } 332 333 void 334 chfs_free_flash_dirent(struct chfs_flash_dirent_node *fdnode) 335 { 336 pool_cache_put(chfs_flash_dirent_cache, fdnode); 337 } 338 339 struct chfs_flash_data_node* 340 chfs_alloc_flash_dnode(void) 341 { 342 struct chfs_flash_data_node *ret; 343 ret = pool_cache_get(chfs_flash_dnode_cache, 0); 344 return ret; 345 } 346 347 void 348 chfs_free_flash_dnode(struct chfs_flash_data_node *fdnode) 349 { 350 pool_cache_put(chfs_flash_dnode_cache, fdnode); 351 } 352 353 354 struct chfs_node_frag* 355 chfs_alloc_node_frag(void) 356 { 357 struct chfs_node_frag *ret; 358 ret = pool_cache_get(chfs_node_frag_cache, 0); 359 return ret; 360 361 } 362 363 void 364 chfs_free_node_frag(struct chfs_node_frag *frag) 365 { 366 pool_cache_put(chfs_node_frag_cache, frag); 367 } 368 369 struct chfs_tmp_dnode * 370 chfs_alloc_tmp_dnode(void) 371 { 372 struct chfs_tmp_dnode *ret; 373 ret = pool_cache_get(chfs_tmp_dnode_cache, 0); 374 ret->next = NULL; 375 return ret; 376 } 377 378 void 379 chfs_free_tmp_dnode(struct chfs_tmp_dnode *td) 380 { 381 pool_cache_put(chfs_tmp_dnode_cache, td); 382 } 383 384 struct chfs_tmp_dnode_info * 385 chfs_alloc_tmp_dnode_info(void) 386 { 387 struct chfs_tmp_dnode_info *ret; 388 ret = pool_cache_get(chfs_tmp_dnode_info_cache, 0); 389 ret->tmpnode = NULL; 390 return ret; 391 } 392 393 void 394 chfs_free_tmp_dnode_info(struct chfs_tmp_dnode_info *di) 395 { 396 pool_cache_put(chfs_tmp_dnode_info_cache, di); 397 } 398 399