1 /* 2 * Copyright 2004-2008, François Revol, <revol@free.fr>. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <malloc.h> 7 #include <string.h> 8 #include <KernelExport.h> 9 #include "vnidpool.h" 10 11 #include <stdio.h> 12 13 /* primary type for the bitmap */ 14 #define BMT uint32 15 16 #define BM_BYTE(p, vnid) (p->bitmap[(vnid % p->bmsize) / sizeof(BMT)]) 17 #define BM_ISSET(p, vnid) (BM_BYTE(p, vnid) & (1 << (p->nextvnid % sizeof(BMT)))) 18 #define BM_SET(p, vnid) (BM_BYTE(p, vnid) |= (1 << (p->nextvnid % sizeof(BMT)))) 19 #define BM_UNSET(p, vnid) (BM_BYTE(p, vnid) &= ~(1 << (p->nextvnid % sizeof(BMT)))) 20 21 status_t vnidpool_alloc(struct vnidpool **pool, size_t size) 22 { 23 struct vnidpool *p; 24 if (size < 2) 25 return EINVAL; 26 if (!pool) 27 return EINVAL; 28 size = (size + sizeof(BMT) - 1) / sizeof(BMT); 29 size *= sizeof(BMT); 30 p = malloc(sizeof(struct vnidpool) + size / sizeof(BMT)); 31 if (!p) 32 return B_NO_MEMORY; 33 new_lock(&p->lock, "vnidpool lock"); 34 p->nextvnid = 1LL; 35 p->bitmap = (BMT *)(p + 1); 36 p->bmsize = size; 37 memset(p->bitmap, 0, size / sizeof(BMT)); 38 fprintf(stderr, "vnidpool_alloc: pool @ %p, bitmap @ %p, size %ld\n", p, p->bitmap, p->bmsize); 39 *pool = p; 40 return B_OK; 41 } 42 43 status_t vnidpool_free(struct vnidpool *pool) { 44 unsigned int i; 45 fprintf(stderr, "vnidpool_free: pool @ %p\n", pool); 46 if (!pool) 47 return EINVAL; 48 if (LOCK(&pool->lock) < B_OK) 49 return B_ERROR; 50 /* make sure no vnid is left in use */ 51 for (i = 0; i < (pool->bmsize % sizeof(BMT)); i++) { 52 if (pool->bitmap[i]) 53 fprintf(stderr, "WARNING: vnidpool_free called with vnids still in use!!!\n"); 54 //panic("vnidpool_free: vnids still in use"); 55 } 56 free_lock(&pool->lock); 57 free(pool); 58 return B_OK; 59 } 60 61 status_t vnidpool_get(struct vnidpool *pool, ino_t *vnid) 62 { 63 status_t err = B_ERROR; 64 uint32 i; 65 if (!pool) 66 return EINVAL; 67 if (LOCK(&pool->lock) < B_OK) 68 return B_ERROR; 69 for (i = 0; BM_ISSET(pool, pool->nextvnid) && i < pool->bmsize; pool->nextvnid++, i++) { 70 /* avoid 0 as vnid */ 71 if (!pool->nextvnid) 72 continue; 73 } 74 if (BM_ISSET(pool, pool->nextvnid)) 75 err = ENOBUFS; 76 else { 77 BM_SET(pool, pool->nextvnid); 78 *vnid = pool->nextvnid++; 79 err = B_OK; 80 } 81 UNLOCK(&pool->lock); 82 return err; 83 } 84 85 status_t vnidpool_put(struct vnidpool *pool, ino_t vnid) 86 { 87 status_t err = B_ERROR; 88 if (!pool) 89 return EINVAL; 90 if (LOCK(&pool->lock) < B_OK) 91 return B_ERROR; 92 if (!BM_ISSET(pool, vnid)) 93 err = EINVAL; 94 else { 95 BM_UNSET(pool, vnid); 96 err = B_OK; 97 } 98 UNLOCK(&pool->lock); 99 return err; 100 } 101 102