Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    r4e00f87 rb33870b  
    5050#include <sys/types.h>
    5151#include <adt/hash_table.h>
    52 #include <adt/hash.h>
    5352#include <as.h>
    5453#include <libfs.h>
     
    5655#define min(a, b)               ((a) < (b) ? (a) : (b))
    5756#define max(a, b)               ((a) > (b) ? (a) : (b))
     57
     58#define NODES_BUCKETS   256
    5859
    5960/** All root nodes have index 0. */
     
    141142hash_table_t nodes;
    142143
    143 /*
    144  * Implementation of hash table interface for the nodes hash table.
    145  */
    146 
    147 typedef struct {
    148         service_id_t service_id;
    149         fs_index_t index;
    150 } node_key_t;
    151 
    152 static size_t nodes_key_hash(void *k)
    153 {
    154         node_key_t *key = (node_key_t *)k;
    155         return hash_combine(key->service_id, key->index);
    156 }
    157 
    158 static size_t nodes_hash(const ht_link_t *item)
    159 {
    160         tmpfs_node_t *nodep = hash_table_get_inst(item, tmpfs_node_t, nh_link);
    161         return hash_combine(nodep->service_id, nodep->index);
    162 }
    163 
    164 static bool nodes_key_equal(void *key_arg, const ht_link_t *item)
    165 {
    166         tmpfs_node_t *node = hash_table_get_inst(item, tmpfs_node_t, nh_link);
    167         node_key_t *key = (node_key_t *)key_arg;
    168        
    169         return key->service_id == node->service_id && key->index == node->index;
    170 }
    171 
    172 static void nodes_remove_callback(ht_link_t *item)
    173 {
    174         tmpfs_node_t *nodep = hash_table_get_inst(item, tmpfs_node_t, nh_link);
     144#define NODES_KEY_DEV   0       
     145#define NODES_KEY_INDEX 1
     146
     147/* Implementation of hash table interface for the nodes hash table. */
     148static hash_index_t nodes_hash(unsigned long key[])
     149{
     150        return key[NODES_KEY_INDEX] % NODES_BUCKETS;
     151}
     152
     153static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
     154{
     155        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
     156            nh_link);
     157       
     158        switch (keys) {
     159        case 1:
     160                return (nodep->service_id == key[NODES_KEY_DEV]);
     161        case 2:
     162                return ((nodep->service_id == key[NODES_KEY_DEV]) &&
     163                    (nodep->index == key[NODES_KEY_INDEX]));
     164        default:
     165                assert((keys == 1) || (keys == 2));
     166        }
     167
     168        return 0;
     169}
     170
     171static void nodes_remove_callback(link_t *item)
     172{
     173        tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
     174            nh_link);
    175175
    176176        while (!list_empty(&nodep->cs_list)) {
     
    192192
    193193/** TMPFS nodes hash table operations. */
    194 hash_table_ops_t nodes_ops = {
     194hash_table_operations_t nodes_ops = {
    195195        .hash = nodes_hash,
    196         .key_hash = nodes_key_hash,
    197         .key_equal = nodes_key_equal,
    198         .equal = NULL,
     196        .compare = nodes_compare,
    199197        .remove_callback = nodes_remove_callback
    200198};
     
    209207        nodep->size = 0;
    210208        nodep->data = NULL;
     209        link_initialize(&nodep->nh_link);
    211210        list_initialize(&nodep->cs_list);
    212211}
     
    221220bool tmpfs_init(void)
    222221{
    223         if (!hash_table_create(&nodes, 0, 0, &nodes_ops))
     222        if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
    224223                return false;
    225224       
     
    239238}
    240239
    241 static bool rm_service_id_nodes(ht_link_t *item, void *arg)
    242 {
    243         service_id_t sid = *(service_id_t*)arg;
    244         tmpfs_node_t *node = hash_table_get_inst(item, tmpfs_node_t, nh_link);
    245        
    246         if (node->service_id == sid) {
    247                 hash_table_remove_item(&nodes, &node->nh_link);
    248         }
    249         return true;
    250 }
    251 
    252240static void tmpfs_instance_done(service_id_t service_id)
    253 {       
    254         hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
     241{
     242        unsigned long key[] = {
     243                [NODES_KEY_DEV] = service_id
     244        };
     245        /*
     246         * Here we are making use of one special feature of our hash table
     247         * implementation, which allows to remove more items based on a partial
     248         * key match. In the following, we are going to remove all nodes
     249         * matching our device handle. The nodes_remove_callback() function will
     250         * take care of resource deallocation.
     251         */
     252        hash_table_remove(&nodes, key, 1);
    255253}
    256254
     
    274272int tmpfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
    275273{
    276         node_key_t key = {
    277                 .service_id = service_id,
    278                 .index = index
    279         };
    280        
    281         ht_link_t *lnk = hash_table_find(&nodes, &key);
    282        
     274        unsigned long key[] = {
     275                [NODES_KEY_DEV] = service_id,
     276                [NODES_KEY_INDEX] = index
     277        };
     278        link_t *lnk = hash_table_find(&nodes, key);
    283279        if (lnk) {
    284280                tmpfs_node_t *nodep;
    285                 nodep = hash_table_get_inst(lnk, tmpfs_node_t, nh_link);
     281                nodep = hash_table_get_instance(lnk, tmpfs_node_t, nh_link);
    286282                *rfn = FS_NODE(nodep);
    287283        } else {
     
    335331
    336332        /* Insert the new node into the nodes hash table. */
    337         hash_table_insert(&nodes, &nodep->nh_link);
     333        unsigned long key[] = {
     334                [NODES_KEY_DEV] = nodep->service_id,
     335                [NODES_KEY_INDEX] = nodep->index
     336        };
     337        hash_table_insert(&nodes, key, &nodep->nh_link);
    338338        *rfn = FS_NODE(nodep);
    339339        return EOK;
     
    346346        assert(!nodep->lnkcnt);
    347347        assert(list_empty(&nodep->cs_list));
    348        
    349         hash_table_remove_item(&nodes, &nodep->nh_link);
     348
     349        unsigned long key[] = {
     350                [NODES_KEY_DEV] = nodep->service_id,
     351                [NODES_KEY_INDEX] = nodep->index
     352        };
     353        hash_table_remove(&nodes, key, 2);
    350354
    351355        /*
     
    472476         * Lookup the respective TMPFS node.
    473477         */
    474         node_key_t key = {
    475                 .service_id = service_id,
    476                 .index = index
    477         };
    478        
    479         ht_link_t *hlp = hash_table_find(&nodes, &key);
     478        link_t *hlp;
     479        unsigned long key[] = {
     480                [NODES_KEY_DEV] = service_id,
     481                [NODES_KEY_INDEX] = index
     482        };
     483        hlp = hash_table_find(&nodes, key);
    480484        if (!hlp)
    481485                return ENOENT;
    482        
    483         tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
     486        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
     487            nh_link);
    484488       
    485489        /*
     
    534538         * Lookup the respective TMPFS node.
    535539         */
    536         node_key_t key = {
    537                 .service_id = service_id,
    538                 .index = index
    539         };
    540        
    541         ht_link_t *hlp = hash_table_find(&nodes, &key);
    542        
     540        link_t *hlp;
     541        unsigned long key[] = {
     542                [NODES_KEY_DEV] = service_id,
     543                [NODES_KEY_INDEX] = index
     544        };
     545        hlp = hash_table_find(&nodes, key);
    543546        if (!hlp)
    544547                return ENOENT;
    545        
    546         tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
     548        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
     549            nh_link);
    547550
    548551        /*
     
    597600         * Lookup the respective TMPFS node.
    598601         */
    599         node_key_t key = {
    600                 .service_id = service_id,
    601                 .index = index
    602         };
    603        
    604         ht_link_t *hlp = hash_table_find(&nodes, &key);
    605        
     602        unsigned long key[] = {
     603                [NODES_KEY_DEV] = service_id,
     604                [NODES_KEY_INDEX] = index
     605        };
     606        link_t *hlp = hash_table_find(&nodes, key);
    606607        if (!hlp)
    607608                return ENOENT;
    608         tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
     609        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
    609610       
    610611        if (size == nodep->size)
     
    635636static int tmpfs_destroy(service_id_t service_id, fs_index_t index)
    636637{
    637         node_key_t key = {
    638                 .service_id = service_id,
    639                 .index = index
    640         };
    641        
    642         ht_link_t *hlp = hash_table_find(&nodes, &key);
     638        link_t *hlp;
     639        unsigned long key[] = {
     640                [NODES_KEY_DEV] = service_id,
     641                [NODES_KEY_INDEX] = index
     642        };
     643        hlp = hash_table_find(&nodes, key);
    643644        if (!hlp)
    644645                return ENOENT;
    645         tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t,
     646        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    646647            nh_link);
    647648        return tmpfs_destroy_node(FS_NODE(nodep));
Note: See TracChangeset for help on using the changeset viewer.