/* * Copyright 2004-2008, François Revol, . * Distributed under the terms of the MIT License. */ #include #include #include #include "vnidpool.h" #include /* primary type for the bitmap */ #define BMT uint32 #define BM_BYTE(p, vnid) (p->bitmap[(vnid % p->bmsize) / sizeof(BMT)]) #define BM_ISSET(p, vnid) (BM_BYTE(p, vnid) & (1 << (p->nextvnid % sizeof(BMT)))) #define BM_SET(p, vnid) (BM_BYTE(p, vnid) |= (1 << (p->nextvnid % sizeof(BMT)))) #define BM_UNSET(p, vnid) (BM_BYTE(p, vnid) &= ~(1 << (p->nextvnid % sizeof(BMT)))) status_t vnidpool_alloc(struct vnidpool **pool, size_t size) { struct vnidpool *p; if (size < 2) return EINVAL; if (!pool) return EINVAL; size = (size + sizeof(BMT) - 1) / sizeof(BMT); size *= sizeof(BMT); p = malloc(sizeof(struct vnidpool) + size / sizeof(BMT)); if (!p) return B_NO_MEMORY; new_lock(&p->lock, "vnidpool lock"); p->nextvnid = 1LL; p->bitmap = (BMT *)(p + 1); p->bmsize = size; memset(p->bitmap, 0, size / sizeof(BMT)); fprintf(stderr, "vnidpool_alloc: pool @ %p, bitmap @ %p, size %ld\n", p, p->bitmap, p->bmsize); *pool = p; return B_OK; } status_t vnidpool_free(struct vnidpool *pool) { unsigned int i; fprintf(stderr, "vnidpool_free: pool @ %p\n", pool); if (!pool) return EINVAL; if (LOCK(&pool->lock) < B_OK) return B_ERROR; /* make sure no vnid is left in use */ for (i = 0; i < (pool->bmsize % sizeof(BMT)); i++) { if (pool->bitmap[i]) fprintf(stderr, "WARNING: vnidpool_free called with vnids still in use!!!\n"); //panic("vnidpool_free: vnids still in use"); } free_lock(&pool->lock); free(pool); return B_OK; } status_t vnidpool_get(struct vnidpool *pool, ino_t *vnid) { status_t err = B_ERROR; uint32 i; if (!pool) return EINVAL; if (LOCK(&pool->lock) < B_OK) return B_ERROR; for (i = 0; BM_ISSET(pool, pool->nextvnid) && i < pool->bmsize; pool->nextvnid++, i++) { /* avoid 0 as vnid */ if (!pool->nextvnid) continue; } if (BM_ISSET(pool, pool->nextvnid)) err = ENOBUFS; else { BM_SET(pool, pool->nextvnid); *vnid = pool->nextvnid++; err = B_OK; } UNLOCK(&pool->lock); return err; } status_t vnidpool_put(struct vnidpool *pool, ino_t vnid) { status_t err = B_ERROR; if (!pool) return EINVAL; if (LOCK(&pool->lock) < B_OK) return B_ERROR; if (!BM_ISSET(pool, vnid)) err = EINVAL; else { BM_UNSET(pool, vnid); err = B_OK; } UNLOCK(&pool->lock); return err; }