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