xref: /haiku/src/add-ons/kernel/file_systems/websearchfs/vnidpool.c (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1) !
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