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
21status_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
43status_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
61status_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
85status_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