From f9defd45266aef2138460ad8d719b452b3a158bc Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Mon, 12 Jan 2015 17:47:02 +0100 Subject: [PATCH] VFS: migrate to BOpenHashTable. --- src/system/kernel/fs/vfs.cpp | 197 ++++++++++++++++------------------- 1 file changed, 92 insertions(+), 105 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 845912c603..5acca18d24 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -252,12 +251,73 @@ static rw_lock sVnodeLock = RW_LOCK_INITIALIZER("vfs_vnode_lock"); static mutex sIOContextRootLock = MUTEX_INITIALIZER("io_context::root lock"); +struct VnodeHash { + typedef vnode_hash_key KeyType; + typedef struct vnode ValueType; + +#define VHASH(mountid, vnodeid) \ + (((uint32)((vnodeid) >> 32) + (uint32)(vnodeid)) ^ (uint32)(mountid)) + + size_t HashKey(KeyType key) const + { + return VHASH(key.device, key.vnode); + } + + size_t Hash(ValueType* vnode) const + { + return VHASH(vnode->device, vnode->id); + } + +#undef VHASH + + bool Compare(KeyType key, ValueType* vnode) const + { + return vnode->device == key.device && vnode->id == key.vnode; + } + + ValueType*& GetLink(ValueType* value) const + { + return value->next; + } +}; + +typedef BOpenHashTable VnodeTable; + + +struct MountHash { + typedef dev_t KeyType; + typedef struct fs_mount ValueType; + + size_t HashKey(KeyType key) const + { + return key; + } + + size_t Hash(ValueType* mount) const + { + return mount->id; + } + + bool Compare(KeyType key, ValueType* mount) const + { + return mount->id == key; + } + + ValueType*& GetLink(ValueType* value) const + { + return value->next; + } +}; + +typedef BOpenHashTable MountTable; + + #define VNODE_HASH_TABLE_SIZE 1024 -static hash_table* sVnodeTable; +static VnodeTable* sVnodeTable; static struct vnode* sRoot; #define MOUNTS_HASH_TABLE_SIZE 16 -static hash_table* sMountsTable; +static MountTable* sMountsTable; static dev_t sNextMountID = 1; #define MAX_TEMP_IO_VECS 8 @@ -647,32 +707,6 @@ public: #endif // VFS_PAGES_IO_TRACING -static int -mount_compare(void* _m, const void* _key) -{ - struct fs_mount* mount = (fs_mount*)_m; - const dev_t* id = (dev_t*)_key; - - if (mount->id == *id) - return 0; - - return -1; -} - - -static uint32 -mount_hash(void* _m, const void* _key, uint32 range) -{ - struct fs_mount* mount = (fs_mount*)_m; - const dev_t* id = (dev_t*)_key; - - if (mount) - return mount->id % range; - - return (uint32)*id % range; -} - - /*! Finds the mounted device (the fs_mount structure) with the given ID. Note, you must hold the gMountMutex lock when you call this function. */ @@ -681,7 +715,7 @@ find_mount(dev_t id) { ASSERT_LOCKED_MUTEX(&sMountMutex); - return (fs_mount*)hash_lookup(sMountsTable, (void*)&id); + return sMountsTable->Lookup(id); } @@ -809,37 +843,6 @@ get_file_system_name_for_layer(const char* fsNames, int32 layer) } -static int -vnode_compare(void* _vnode, const void* _key) -{ - struct vnode* vnode = (struct vnode*)_vnode; - const struct vnode_hash_key* key = (vnode_hash_key*)_key; - - if (vnode->device == key->device && vnode->id == key->vnode) - return 0; - - return -1; -} - - -static uint32 -vnode_hash(void* _vnode, const void* _key, uint32 range) -{ - struct vnode* vnode = (struct vnode*)_vnode; - const struct vnode_hash_key* key = (vnode_hash_key*)_key; - -#define VHASH(mountid, vnodeid) \ - (((uint32)((vnodeid) >> 32) + (uint32)(vnodeid)) ^ (uint32)(mountid)) - - if (vnode != NULL) - return VHASH(vnode->device, vnode->id) % range; - - return VHASH(key->device, key->vnode) % range; - -#undef VHASH -} - - static void add_vnode_to_mount_list(struct vnode* vnode, struct fs_mount* mount) { @@ -874,7 +877,7 @@ lookup_vnode(dev_t mountID, ino_t vnodeID) key.device = mountID; key.vnode = vnodeID; - return (vnode*)hash_lookup(sVnodeTable, &key); + return sVnodeTable->Lookup(key); } @@ -933,7 +936,7 @@ create_new_vnode_and_lock(dev_t mountID, ino_t vnodeID, struct vnode*& _vnode, } // add the vnode to the mount's node list and the hash table - hash_insert(sVnodeTable, vnode); + sVnodeTable->Insert(vnode); add_vnode_to_mount_list(vnode, vnode->mount); mutex_unlock(&sMountMutex); @@ -993,7 +996,7 @@ free_vnode(struct vnode* vnode, bool reenter) // The file system has removed the resources of the vnode now, so we can // make it available again (by removing the busy vnode from the hash). rw_lock_write_lock(&sVnodeLock); - hash_remove(sVnodeTable, vnode); + sVnodeTable->Remove(vnode); rw_lock_write_unlock(&sVnodeLock); // if we have a VMCache attached, remove it @@ -1205,7 +1208,7 @@ restart: FS_CALL(vnode, put_vnode, reenter); rw_lock_write_lock(&sVnodeLock); - hash_remove(sVnodeTable, vnode); + sVnodeTable->Remove(vnode); remove_vnode_from_mount_list(vnode, vnode->mount); rw_lock_write_unlock(&sVnodeLock); @@ -3149,7 +3152,7 @@ dump_mount(int argc, char** argv) ulong val = parse_expression(argv[1]); uint32 id = val; - struct fs_mount* mount = (fs_mount*)hash_lookup(sMountsTable, (void*)&id); + struct fs_mount* mount = sMountsTable->Lookup(id); if (mount == NULL) { if (IS_USER_ADDRESS(id)) { kprintf("fs_mount not found\n"); @@ -3175,12 +3178,11 @@ dump_mounts(int argc, char** argv) B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "root", B_PRINTF_POINTER_WIDTH, "covers", B_PRINTF_POINTER_WIDTH, "cookie"); - struct hash_iterator iterator; struct fs_mount* mount; - hash_open(sMountsTable, &iterator); - while ((mount = (struct fs_mount*)hash_next(sMountsTable, &iterator)) - != NULL) { + MountTable::Iterator iterator(sMountsTable); + while (iterator.HasNext()) { + mount = iterator.Next(); kprintf("%p%4" B_PRIdDEV " %p %p %p %s\n", mount, mount->id, mount->root_vnode, mount->root_vnode->covers, mount->volume->private_volume, mount->volume->file_system_name); @@ -3193,7 +3195,6 @@ dump_mounts(int argc, char** argv) } } - hash_close(sMountsTable, &iterator, false); return 0; } @@ -3225,19 +3226,18 @@ dump_vnode(int argc, char** argv) return 0; } - struct hash_iterator iterator; dev_t device = parse_expression(argv[argi]); ino_t id = parse_expression(argv[argi + 1]); - hash_open(sVnodeTable, &iterator); - while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { + VnodeTable::Iterator iterator(sVnodeTable); + while (iterator.HasNext()) { + vnode = iterator.Next(); if (vnode->id != id || vnode->device != device) continue; _dump_vnode(vnode, printPath); } - hash_close(sVnodeTable, &iterator, false); return 0; } @@ -3253,15 +3253,15 @@ dump_vnodes(int argc, char** argv) // restrict dumped nodes to a certain device if requested dev_t device = parse_expression(argv[1]); - struct hash_iterator iterator; struct vnode* vnode; kprintf("%-*s dev inode ref %-*s %-*s %-*s flags\n", B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "cache", B_PRINTF_POINTER_WIDTH, "fs-node", B_PRINTF_POINTER_WIDTH, "locking"); - hash_open(sVnodeTable, &iterator); - while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { + VnodeTable::Iterator iterator(sVnodeTable); + while (iterator.HasNext()) { + vnode = iterator.Next(); if (vnode->device != device) continue; @@ -3272,7 +3272,6 @@ dump_vnodes(int argc, char** argv) vnode->IsUnpublished() ? "u" : "-"); } - hash_close(sVnodeTable, &iterator, false); return 0; } @@ -3280,7 +3279,6 @@ dump_vnodes(int argc, char** argv) static int dump_vnode_caches(int argc, char** argv) { - struct hash_iterator iterator; struct vnode* vnode; if (argc > 2 || !strcmp(argv[1], "--help")) { @@ -3296,8 +3294,9 @@ dump_vnode_caches(int argc, char** argv) kprintf("%-*s dev inode %-*s size pages\n", B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "cache"); - hash_open(sVnodeTable, &iterator); - while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { + VnodeTable::Iterator iterator(sVnodeTable); + while (iterator.HasNext()) { + vnode = iterator.Next(); if (vnode->cache == NULL) continue; if (device != -1 && vnode->device != device) @@ -3309,7 +3308,6 @@ dump_vnode_caches(int argc, char** argv) vnode->cache->page_count); } - hash_close(sVnodeTable, &iterator, false); return 0; } @@ -3384,16 +3382,7 @@ dump_vnode_usage(int argc, char** argv) kprintf("Unused vnodes: %" B_PRIu32 " (max unused %" B_PRIu32 ")\n", sUnusedVnodes, kMaxUnusedVnodes); - struct hash_iterator iterator; - hash_open(sVnodeTable, &iterator); - - uint32 count = 0; - struct vnode* vnode; - while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { - count++; - } - - hash_close(sVnodeTable, &iterator, false); + uint32 count = sVnodeTable->CountElements(); kprintf("%" B_PRIu32 " vnodes total (%" B_PRIu32 " in use).\n", count, count - sUnusedVnodes); @@ -3727,7 +3716,7 @@ publish_vnode(fs_volume* volume, ino_t vnodeID, void* privateNode, vnode->SetUnpublished(false); } else { locker.Lock(); - hash_remove(sVnodeTable, vnode); + sVnodeTable->Remove(vnode); remove_vnode_from_mount_list(vnode, vnode->mount); free(vnode); } @@ -5155,18 +5144,16 @@ vfs_init(kernel_args* args) { vnode::StaticInit(); - struct vnode dummyVnode; - sVnodeTable = hash_init(VNODE_HASH_TABLE_SIZE, - offset_of_member(dummyVnode, next), &vnode_compare, &vnode_hash); - if (sVnodeTable == NULL) + sVnodeTable = new(std::nothrow) VnodeTable(); + if (sVnodeTable == NULL | sVnodeTable->Init(VNODE_HASH_TABLE_SIZE) != B_OK) panic("vfs_init: error creating vnode hash table\n"); - list_init_etc(&sUnusedVnodeList, offset_of_member(dummyVnode, unused_link)); + list_init_etc(&sUnusedVnodeList, offsetof(struct vnode, unused_link)); struct fs_mount dummyMount; - sMountsTable = hash_init(MOUNTS_HASH_TABLE_SIZE, - offset_of_member(dummyMount, next), &mount_compare, &mount_hash); - if (sMountsTable == NULL) + sMountsTable = new(std::nothrow) MountTable(); + if (sMountsTable == NULL + || sMountsTable->Init(MOUNTS_HASH_TABLE_SIZE) != B_OK) panic("vfs_init: error creating mounts hash table\n"); node_monitor_init(); @@ -7375,7 +7362,7 @@ fs_mount(char* path, const char* device, const char* fsName, uint32 flags, // insert mount struct into list before we call FS's mount() function // so that vnodes can be created for this mount mutex_lock(&sMountMutex); - hash_insert(sMountsTable, mount); + sMountsTable->Insert(mount); mutex_unlock(&sMountMutex); ino_t rootID; @@ -7492,7 +7479,7 @@ err3: put_vnode(coveredNode); err2: mutex_lock(&sMountMutex); - hash_remove(sMountsTable, mount); + sMountsTable->Remove(mount); mutex_unlock(&sMountMutex); err1: delete mount; @@ -7700,7 +7687,7 @@ fs_unmount(char* path, dev_t mountID, uint32 flags, bool kernel) // remove the mount structure from the hash table mutex_lock(&sMountMutex); - hash_remove(sMountsTable, mount); + sMountsTable->Remove(mount); mutex_unlock(&sMountMutex); mountOpLocker.Unlock();