Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/ext2fs/ext2fs_ops.c

    r4e00f87 rf73b291  
    4949#include <byteorder.h>
    5050#include <adt/hash_table.h>
    51 #include <adt/hash.h>
    5251#include <adt/list.h>
    5352#include <assert.h>
     
    6362#define EXT2FS_NODE(node)       ((node) ? (ext2fs_node_t *) (node)->data : NULL)
    6463#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
     64#define OPEN_NODES_KEYS 2
     65#define OPEN_NODES_DEV_HANDLE_KEY 0
     66#define OPEN_NODES_INODE_KEY 1
     67#define OPEN_NODES_BUCKETS 256
    6568
    6669typedef struct ext2fs_instance {
     
    7578        ext2_inode_ref_t *inode_ref;
    7679        fs_node_t *fs_node;
    77         ht_link_t link;
     80        link_t link;
    7881        unsigned int references;
    7982} ext2fs_node_t;
     
    119122static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
    120123
    121 /*
    122  * Hash table interface for open nodes hash table
    123  */
    124 
    125 typedef struct {
    126         service_id_t service_id;
    127         fs_index_t index;
    128 } node_key_t;
    129 
    130 static size_t open_nodes_key_hash(void *key)
    131 {
    132         node_key_t *node_key = (node_key_t*)key;
    133         return hash_combine(node_key->service_id, node_key->index);
    134 }
    135 
    136 static size_t open_nodes_hash(const ht_link_t *item)
    137 {
    138         ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
    139 
    140         assert(enode->instance);
    141         assert(enode->inode_ref);
    142        
    143         return hash_combine(enode->instance->service_id, enode->inode_ref->index);
    144 }
    145 
    146 static bool open_nodes_key_equal(void *key, const ht_link_t *item)
    147 {
    148         node_key_t *node_key = (node_key_t*)key;
    149         ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
    150        
    151         return node_key->service_id == enode->instance->service_id
    152                 && node_key->index == enode->inode_ref->index;
    153 }
    154 
    155 static hash_table_ops_t open_nodes_ops = {
     124/* Hash table interface for open nodes hash table */
     125static hash_index_t open_nodes_hash(unsigned long key[])
     126{
     127        /* TODO: This is very simple and probably can be improved */
     128        return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
     129}
     130
     131static int open_nodes_compare(unsigned long key[], hash_count_t keys,
     132    link_t *item)
     133{
     134        ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
     135        assert(keys > 0);
     136        if (enode->instance->service_id !=
     137            ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
     138                return false;
     139        }
     140        if (keys == 1) {
     141                return true;
     142        }
     143        assert(keys == 2);
     144        return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
     145}
     146
     147static void open_nodes_remove_cb(link_t *link)
     148{
     149        /* We don't use remove callback for this hash table */
     150}
     151
     152static hash_table_operations_t open_nodes_ops = {
    156153        .hash = open_nodes_hash,
    157         .key_hash = open_nodes_key_hash,
    158         .key_equal = open_nodes_key_equal,
    159         .equal = NULL,
    160         .remove_callback = NULL,
     154        .compare = open_nodes_compare,
     155        .remove_callback = open_nodes_remove_cb,
    161156};
    162157
     
    166161int ext2fs_global_init(void)
    167162{
    168         if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) {
     163        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
     164            OPEN_NODES_KEYS, &open_nodes_ops)) {
    169165                return ENOMEM;
    170166        }
     
    320316       
    321317        /* Check if the node is not already open */
    322         node_key_t key = {
    323                 .service_id = inst->service_id,
    324                 .index = index
     318        unsigned long key[] = {
     319                [OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
     320                [OPEN_NODES_INODE_KEY] = index,
    325321        };
    326         ht_link_t *already_open = hash_table_find(&open_nodes, &key);
     322        link_t *already_open = hash_table_find(&open_nodes, key);
    327323
    328324        if (already_open) {
    329                 enode = hash_table_get_inst(already_open, ext2fs_node_t, link);
     325                enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
    330326                *rfn = enode->fs_node;
    331327                enode->references++;
     
    361357        enode->references = 1;
    362358        enode->fs_node = node;
     359        link_initialize(&enode->link);
    363360       
    364361        node->data = enode;
    365362        *rfn = node;
    366363       
    367         hash_table_insert(&open_nodes, &enode->link);
     364        hash_table_insert(&open_nodes, key, &enode->link);
    368365        inst->open_nodes_count++;
    369366       
     
    411408int ext2fs_node_put_core(ext2fs_node_t *enode)
    412409{
    413         node_key_t key = {
    414                 .service_id = enode->instance->service_id,
    415                 .index = enode->inode_ref->index
     410        int rc;
     411
     412        unsigned long key[] = {
     413                [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
     414                [OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
    416415        };
    417 
    418         hash_table_remove(&open_nodes, &key);
    419        
     416        hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
    420417        assert(enode->instance->open_nodes_count > 0);
    421418        enode->instance->open_nodes_count--;
    422419
    423         int rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
     420        rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
    424421        if (rc != EOK) {
    425422                EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
Note: See TracChangeset for help on using the changeset viewer.