Copyright 1999-2001, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
directory vnode id list
We only add to this list as we encounter directories; there is no need to
scan through the directories ourselves since we aren't worried about preserving
vnid's across reboots.
We don't worry about aliases for directories since their cluster values will
always be the same -- searches are performed only on the starting cluster
number of the directories.
TODO:
XXX: make this more efficient
*/
#define DPRINTF(a,b) if (debug_dlist > (a)) dprintf b
#include "system_dependencies.h"
#include "dosfs.h"
#include "dlist.h"
#include "util.h"
#include "vcache.h"
#if DEBUG
#define DLIST_ENTRY_QUANTUM 1
#else
#define DLIST_ENTRY_QUANTUM 0x20
#endif
status_t
dlist_init(nspace *vol)
{
DPRINTF(0, ("dlist_init called\n"));
vol->dlist.entries = 0;
vol->dlist.allocated = DLIST_ENTRY_QUANTUM;
vol->dlist.vnid_list = (ino_t *)malloc(sizeof(ino_t) * vol->dlist.allocated);
if (vol->dlist.vnid_list == NULL) {
vol->dlist.allocated = 0;
dprintf("dlist_init: out of core\n");
return ENOMEM;
}
return B_OK;
}
status_t
dlist_uninit(nspace *vol)
{
DPRINTF(0, ("dlist_uninit called\n"));
if (vol->dlist.vnid_list)
free(vol->dlist.vnid_list);
vol->dlist.entries = vol->dlist.allocated = 0;
vol->dlist.vnid_list = NULL;
return B_OK;
}
static status_t
dlist_realloc(nspace *vol, uint32 allocate)
{
ino_t *vnid_list;
DPRINTF(0, ("dlist_realloc %" B_PRIu32 " -> %" B_PRIu32 "\n",
vol->dlist.allocated, allocate));
ASSERT(allocate != vol->dlist.allocated);
ASSERT(allocate > vol->dlist.entries);
vnid_list = (ino_t *)malloc(sizeof(ino_t) * allocate);
if (vnid_list == NULL) {
dprintf("dlist_realloc: out of core\n");
return ENOMEM;
}
memcpy(vnid_list, vol->dlist.vnid_list, sizeof(ino_t) * vol->dlist.entries);
free(vol->dlist.vnid_list);
vol->dlist.vnid_list = vnid_list;
vol->dlist.allocated = allocate;
return B_OK;
}
status_t
dlist_add(nspace *vol, ino_t vnid)
{
DPRINTF(0, ("dlist_add vnid %" B_PRIdINO "\n", vnid));
ASSERT(IS_DIR_CLUSTER_VNID(vnid) || IS_ARTIFICIAL_VNID(vnid));
ASSERT(vnid != 0);
if (vol->dlist.entries == vol->dlist.allocated) {
if (dlist_realloc(vol, vol->dlist.allocated + DLIST_ENTRY_QUANTUM) < 0)
return B_ERROR;
}
vol->dlist.vnid_list[vol->dlist.entries++] = vnid;
return B_OK;
}
status_t
dlist_remove(nspace *vol, ino_t vnid)
{
uint32 i;
DPRINTF(0, ("dlist_remove vnid %" B_PRIdINO "\n", vnid));
for (i=0;i<vol->dlist.entries;i++)
if (vol->dlist.vnid_list[i] == vnid)
break;
ASSERT(i < vol->dlist.entries);
if (i == vol->dlist.entries)
return ENOENT;
for (;i<vol->dlist.entries-1;i++)
vol->dlist.vnid_list[i] = vol->dlist.vnid_list[i+1];
vol->dlist.entries--;
if (vol->dlist.allocated - vol->dlist.entries > 2*DLIST_ENTRY_QUANTUM)
return dlist_realloc(vol, vol->dlist.allocated - DLIST_ENTRY_QUANTUM);
return B_OK;
}
ino_t
dlist_find(nspace *vol, uint32 cluster)
{
uint32 i;
DPRINTF(1, ("dlist_find cluster %" B_PRIu32 "\n", cluster));
ASSERT(((cluster >= 2) && (cluster < vol->total_clusters + 2)) || (cluster == 1));
for (i = 0; i < vol->dlist.entries; i++) {
ino_t loc;
if (vcache_vnid_to_loc(vol, vol->dlist.vnid_list[i], &loc) < B_OK)
loc = vol->dlist.vnid_list[i];
ASSERT(IS_DIR_CLUSTER_VNID(loc));
if (CLUSTER_OF_DIR_CLUSTER_VNID(loc) == cluster)
return vol->dlist.vnid_list[i];
}
DPRINTF(1, ("dlist_find cluster %" B_PRIu32 " not found\n", cluster));
return -1LL;
}
void
dlist_dump(nspace *vol)
{
uint32 i;
dprintf("%" B_PRIu32 "/%" B_PRIu32 " dlist entries filled, QUANTUM = %u\n",
vol->dlist.entries, vol->dlist.allocated, DLIST_ENTRY_QUANTUM);
for (i = 0; i < vol->dlist.entries; i++) {
dprintf("%s %" B_PRIdINO, i == 0 ? "entries:" : ",",
vol->dlist.vnid_list[i]);
}
dprintf("\n");
}