Changeset efdfebc in mainline for uspace/srv/fs/cdfs/cdfs_ops.c


Ignore:
Timestamp:
2012-11-06T21:03:44Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
338810f
Parents:
de73242 (diff), 94795812 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/cdfs/cdfs_ops.c

    rde73242 refdfebc  
    3737 */
    3838
     39#include "cdfs_ops.h"
    3940#include <bool.h>
    4041#include <adt/hash_table.h>
     42#include <adt/hash.h>
    4143#include <malloc.h>
    4244#include <mem.h>
     
    4446#include <libfs.h>
    4547#include <errno.h>
    46 #include <libblock.h>
     48#include <block.h>
    4749#include <str.h>
    4850#include <byteorder.h>
     
    5052#include "cdfs.h"
    5153#include "cdfs_endian.h"
    52 #include "cdfs_ops.h"
    5354
    5455/** Standard CD-ROM block size */
    5556#define BLOCK_SIZE  2048
    5657
    57 /** Implicit node cache size
    58  *
    59  * More nodes can be actually cached if the files remain
    60  * opended.
    61  *
    62  */
    63 #define NODE_CACHE_SIZE  200
    64 
    65 #define NODES_BUCKETS  256
    66 
    67 #define NODES_KEY_SRVC   0
    68 #define NODES_KEY_INDEX  1
     58#define NODE_CACHE_SIZE 200
    6959
    7060/** All root nodes have index 0 */
     
    205195        service_id_t service_id;  /**< Service ID of block device */
    206196       
    207         link_t nh_link;           /**< Nodes hash table link */
     197        ht_link_t nh_link;        /**< Nodes hash table link */
    208198        cdfs_dentry_type_t type;  /**< Dentry type */
    209199       
     
    226216static hash_table_t nodes;
    227217
    228 static hash_index_t nodes_hash(unsigned long key[])
    229 {
    230         return key[NODES_KEY_INDEX] % NODES_BUCKETS;
    231 }
    232 
    233 static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
    234 {
    235         cdfs_node_t *node =
    236             hash_table_get_instance(item, cdfs_node_t, nh_link);
    237        
    238         switch (keys) {
    239         case 1:
    240                 return (node->service_id == key[NODES_KEY_SRVC]);
    241         case 2:
    242                 return ((node->service_id == key[NODES_KEY_SRVC]) &&
    243                     (node->index == key[NODES_KEY_INDEX]));
    244         default:
    245                 assert((keys == 1) || (keys == 2));
    246         }
    247        
    248         return 0;
    249 }
    250 
    251 static void nodes_remove_callback(link_t *item)
    252 {
    253         cdfs_node_t *node =
    254             hash_table_get_instance(item, cdfs_node_t, nh_link);
     218/*
     219 * Hash table support functions.
     220 */
     221
     222typedef struct {
     223        service_id_t service_id;
     224    fs_index_t index;
     225} ht_key_t;
     226
     227static size_t nodes_key_hash(void *k)
     228{
     229        ht_key_t *key = (ht_key_t*)k;
     230        return hash_combine(key->service_id, key->index);
     231}
     232
     233static size_t nodes_hash(const ht_link_t *item)
     234{
     235        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
     236        return hash_combine(node->service_id, node->index);
     237}
     238
     239static bool nodes_key_equal(void *k, const ht_link_t *item)
     240{
     241        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
     242        ht_key_t *key = (ht_key_t*)k;
     243       
     244        return key->service_id == node->service_id && key->index == node->index;
     245}
     246
     247static void nodes_remove_callback(ht_link_t *item)
     248{
     249        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
    255250       
    256251        assert(node->type == CDFS_DIRECTORY);
     
    268263
    269264/** Nodes hash table operations */
    270 static hash_table_operations_t nodes_ops = {
     265static hash_table_ops_t nodes_ops = {
    271266        .hash = nodes_hash,
    272         .compare = nodes_compare,
     267        .key_hash = nodes_key_hash,
     268        .key_equal = nodes_key_equal,
     269        .equal = NULL,
    273270        .remove_callback = nodes_remove_callback
    274271};
     
    277274    fs_index_t index)
    278275{
    279         unsigned long key[] = {
    280                 [NODES_KEY_SRVC] = service_id,
    281                 [NODES_KEY_INDEX] = index
     276        ht_key_t key = {
     277                .index = index,
     278                .service_id = service_id
    282279        };
    283280       
    284         link_t *link = hash_table_find(&nodes, key);
     281        ht_link_t *link = hash_table_find(&nodes, &key);
    285282        if (link) {
    286283                cdfs_node_t *node =
    287                     hash_table_get_instance(link, cdfs_node_t, nh_link);
     284                    hash_table_get_inst(link, cdfs_node_t, nh_link);
    288285               
    289286                *rfn = FS_NODE(node);
     
    311308        node->opened = 0;
    312309       
    313         link_initialize(&node->nh_link);
    314310        list_initialize(&node->cs_list);
    315311}
     
    353349       
    354350        /* Insert the new node into the nodes hash table. */
    355         unsigned long key[] = {
    356                 [NODES_KEY_SRVC] = node->service_id,
    357                 [NODES_KEY_INDEX] = node->index
    358         };
    359        
    360         hash_table_insert(&nodes, key, &node->nh_link);
     351        hash_table_insert(&nodes, &node->nh_link);
    361352       
    362353        *rfn = FS_NODE(node);
     
    508499static fs_node_t *get_cached_node(service_id_t service_id, fs_index_t index)
    509500{
    510         unsigned long key[] = {
    511                 [NODES_KEY_SRVC] = service_id,
    512                 [NODES_KEY_INDEX] = index
     501        ht_key_t key = {
     502                .index = index,
     503                .service_id = service_id
    513504        };
    514505       
    515         link_t *link = hash_table_find(&nodes, key);
     506        ht_link_t *link = hash_table_find(&nodes, &key);
    516507        if (link) {
    517508                cdfs_node_t *node =
    518                     hash_table_get_instance(link, cdfs_node_t, nh_link);
     509                    hash_table_get_inst(link, cdfs_node_t, nh_link);
    519510                return FS_NODE(node);
    520511        }
     
    802793}
    803794
     795static bool rm_service_id_nodes(ht_link_t *item, void *arg)
     796{
     797        service_id_t service_id = *(service_id_t*)arg;
     798        cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
     799       
     800        if (node->service_id == service_id) {
     801                hash_table_remove_item(&nodes, &node->nh_link);
     802        }
     803       
     804        return true;
     805}
     806
    804807static void cdfs_instance_done(service_id_t service_id)
    805808{
    806         unsigned long key[] = {
    807                 [NODES_KEY_SRVC] = service_id
    808         };
    809        
    810         hash_table_remove(&nodes, key, 1);
     809        hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
    811810        block_cache_fini(service_id);
    812811        block_fini(service_id);
     
    822821    size_t *rbytes)
    823822{
    824         unsigned long key[] = {
    825                 [NODES_KEY_SRVC] = service_id,
    826                 [NODES_KEY_INDEX] = index
     823        ht_key_t key = {
     824                .index = index,
     825                .service_id = service_id
    827826        };
    828827       
    829         link_t *link = hash_table_find(&nodes, key);
     828        ht_link_t *link = hash_table_find(&nodes, &key);
    830829        if (link == NULL)
    831830                return ENOENT;
    832831       
    833832        cdfs_node_t *node =
    834             hash_table_get_instance(link, cdfs_node_t, nh_link);
     833            hash_table_get_inst(link, cdfs_node_t, nh_link);
    835834       
    836835        if (!node->processed) {
     
    912911}
    913912
     913static bool cache_remove_closed(ht_link_t *item, void *arg)
     914{
     915        size_t *premove_cnt = (size_t*)arg;
     916       
     917        /* Some nodes were requested to be removed from the cache. */
     918        if (0 < *premove_cnt) {
     919                cdfs_node_t *node =     hash_table_get_inst(item, cdfs_node_t, nh_link);
     920
     921                if (!node->opened) {
     922                        hash_table_remove_item(&nodes, item);
     923                       
     924                        --nodes_cached;
     925                        --*premove_cnt;
     926                }
     927        }
     928       
     929        /* Only continue if more nodes were requested to be removed. */
     930        return 0 < *premove_cnt;
     931}
     932
    914933static void cleanup_cache(service_id_t service_id)
    915934{
    916935        if (nodes_cached > NODE_CACHE_SIZE) {
    917                 size_t remove = nodes_cached - NODE_CACHE_SIZE;
    918                
    919                 // FIXME: this accesses the internals of the hash table
    920                 //        and should be rewritten in a clean way
    921                
    922                 for (hash_index_t chain = 0; chain < nodes.entries; chain++) {
    923                         for (link_t *link = nodes.entry[chain].head.next;
    924                             link != &nodes.entry[chain].head;
    925                             link = link->next) {
    926                                 if (remove == 0)
    927                                         return;
    928                                
    929                                 cdfs_node_t *node =
    930                                     hash_table_get_instance(link, cdfs_node_t, nh_link);
    931                                 if (node->opened == 0) {
    932                                         link_t *tmp = link;
    933                                         link = link->prev;
    934                                        
    935                                         list_remove(tmp);
    936                                         nodes.op->remove_callback(tmp);
    937                                         nodes_cached--;
    938                                         remove--;
    939                                        
    940                                         continue;
    941                                 }
    942                         }
    943                 }
     936                size_t remove_cnt = nodes_cached - NODE_CACHE_SIZE;
     937               
     938                if (0 < remove_cnt)
     939                        hash_table_apply(&nodes, cache_remove_closed, &remove_cnt);
    944940        }
    945941}
     
    951947                return EOK;
    952948       
    953         unsigned long key[] = {
    954                 [NODES_KEY_SRVC] = service_id,
    955                 [NODES_KEY_INDEX] = index
     949        ht_key_t key = {
     950                .index = index,
     951                .service_id = service_id
    956952        };
    957953       
    958         link_t *link = hash_table_find(&nodes, key);
     954        ht_link_t *link = hash_table_find(&nodes, &key);
    959955        if (link == 0)
    960956                return ENOENT;
    961957       
    962958        cdfs_node_t *node =
    963             hash_table_get_instance(link, cdfs_node_t, nh_link);
     959            hash_table_get_inst(link, cdfs_node_t, nh_link);
    964960       
    965961        assert(node->opened > 0);
     
    10071003bool cdfs_init(void)
    10081004{
    1009         if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
     1005        if (!hash_table_create(&nodes, 0, 0, &nodes_ops))
    10101006                return false;
    10111007       
Note: See TracChangeset for help on using the changeset viewer.