Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/ext4fs/ext4fs_ops.c

    r062d900 r38542dc  
    4242#include <malloc.h>
    4343#include <adt/hash_table.h>
    44 #include <adt/hash.h>
    4544#include <ipc/loc.h>
    4645#include "ext4fs.h"
     
    4948#define EXT4FS_NODE(node) \
    5049        ((node) ? (ext4fs_node_t *) (node)->data : NULL)
     50
     51#define OPEN_NODES_KEYS  2
     52
     53#define OPEN_NODES_DEV_HANDLE_KEY  0
     54#define OPEN_NODES_INODE_KEY       1
     55
     56#define OPEN_NODES_BUCKETS  256
    5157
    5258/**
     
    6773        ext4_inode_ref_t *inode_ref;
    6874        fs_node_t *fs_node;
    69         ht_link_t link;
     75        link_t link;
    7076        unsigned int references;
    7177} ext4fs_node_t;
     
    109115
    110116/* Hash table interface for open nodes hash table */
    111 
    112 typedef struct {
    113         service_id_t service_id;
    114         fs_index_t index;
    115 } node_key_t;
    116 
    117 static size_t open_nodes_key_hash(void *key_arg)
    118 {
    119         node_key_t *key = (node_key_t *)key_arg;
    120         return hash_combine(key->service_id, key->index);
    121 }
    122 
    123 static size_t open_nodes_hash(const ht_link_t *item)
    124 {
    125         ext4fs_node_t *enode = hash_table_get_inst(item, ext4fs_node_t, link);
    126         return hash_combine(enode->instance->service_id, enode->inode_ref->index);     
    127 }
    128 
    129 static bool open_nodes_key_equal(void *key_arg, const ht_link_t *item)
    130 {
    131         node_key_t *key = (node_key_t *)key_arg;
    132         ext4fs_node_t *enode = hash_table_get_inst(item, ext4fs_node_t, link);
    133        
    134         return key->service_id == enode->instance->service_id
    135                 && key->index == enode->inode_ref->index;
    136 }
    137 
    138 static hash_table_ops_t open_nodes_ops = {
     117static hash_index_t open_nodes_hash(unsigned long key[])
     118{
     119        /* TODO: This is very simple and probably can be improved */
     120        return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
     121}
     122
     123/** Compare given item with values in hash table.
     124 *
     125 */
     126static int open_nodes_compare(unsigned long key[], hash_count_t keys,
     127    link_t *item)
     128{
     129        assert(keys > 0);
     130       
     131        ext4fs_node_t *enode =
     132            hash_table_get_instance(item, ext4fs_node_t, link);
     133       
     134        if (enode->instance->service_id !=
     135            ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY]))
     136                return false;
     137       
     138        if (keys == 1)
     139                return true;
     140       
     141        assert(keys == 2);
     142       
     143        return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
     144}
     145
     146/** Empty callback to correct hash table initialization.
     147 *
     148 */
     149static void open_nodes_remove_cb(link_t *link)
     150{
     151        /* We don't use remove callback for this hash table */
     152}
     153
     154static hash_table_operations_t open_nodes_ops = {
    139155        .hash = open_nodes_hash,
    140         .key_hash = open_nodes_key_hash,
    141         .key_equal = open_nodes_key_equal,
    142         .equal = NULL,
    143         .remove_callback = NULL,
     156        .compare = open_nodes_compare,
     157        .remove_callback = open_nodes_remove_cb,
    144158};
    145159
     
    154168int ext4fs_global_init(void)
    155169{
    156         if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops))
     170        if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
     171            OPEN_NODES_KEYS, &open_nodes_ops))
    157172                return ENOMEM;
    158173       
     
    300315       
    301316        /* Check if the node is not already open */
    302         node_key_t key = {
    303                 .service_id = inst->service_id,
    304                 .index = index
     317        unsigned long key[] = {
     318                [OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
     319                [OPEN_NODES_INODE_KEY] = index
    305320        };
    306321       
    307         ht_link_t *already_open = hash_table_find(&open_nodes, &key);
     322        link_t *already_open = hash_table_find(&open_nodes, key);
    308323        ext4fs_node_t *enode = NULL;
    309324        if (already_open) {
    310                 enode = hash_table_get_inst(already_open, ext4fs_node_t, link);
     325                enode = hash_table_get_instance(already_open, ext4fs_node_t, link);
    311326                *rfn = enode->fs_node;
    312327                enode->references++;
     
    349364        enode->references = 1;
    350365        enode->fs_node = fs_node;
     366        link_initialize(&enode->link);
    351367       
    352368        fs_node->data = enode;
    353369        *rfn = fs_node;
    354370       
    355         hash_table_insert(&open_nodes, &enode->link);
     371        hash_table_insert(&open_nodes, key, &enode->link);
    356372        inst->open_nodes_count++;
    357373       
     
    370386int ext4fs_node_put_core(ext4fs_node_t *enode)
    371387{
    372         hash_table_remove_item(&open_nodes, &enode->link);
     388        unsigned long key[] = {
     389                [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
     390                [OPEN_NODES_INODE_KEY] = enode->inode_ref->index
     391        };
     392       
     393        hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
    373394        assert(enode->instance->open_nodes_count > 0);
    374395        enode->instance->open_nodes_count--;
     
    477498        enode->references = 1;
    478499       
     500        link_initialize(&enode->link);
     501       
     502        unsigned long key[] = {
     503                [OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
     504                [OPEN_NODES_INODE_KEY] = inode_ref->index
     505        };
     506       
    479507        fibril_mutex_lock(&open_nodes_lock);
    480         hash_table_insert(&open_nodes, &enode->link);
     508        hash_table_insert(&open_nodes, key, &enode->link);
    481509        fibril_mutex_unlock(&open_nodes_lock);
    482510        inst->open_nodes_count++;
Note: See TracChangeset for help on using the changeset viewer.