Changes in uspace/srv/fs/cdfs/cdfs_ops.c [44ecf89:b33870b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/cdfs/cdfs_ops.c
r44ecf89 rb33870b 37 37 */ 38 38 39 #include "cdfs_ops.h" 40 #include <stdbool.h> 39 #include <bool.h> 41 40 #include <adt/hash_table.h> 42 #include <adt/hash.h>43 41 #include <malloc.h> 44 42 #include <mem.h> … … 46 44 #include <libfs.h> 47 45 #include <errno.h> 48 #include < block.h>46 #include <libblock.h> 49 47 #include <str.h> 50 48 #include <byteorder.h> … … 52 50 #include "cdfs.h" 53 51 #include "cdfs_endian.h" 52 #include "cdfs_ops.h" 54 53 55 54 /** Standard CD-ROM block size */ 56 55 #define BLOCK_SIZE 2048 57 56 58 #define NODE_CACHE_SIZE 200 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 59 69 60 70 /** All root nodes have index 0 */ … … 195 205 service_id_t service_id; /**< Service ID of block device */ 196 206 197 ht_link_t nh_link;/**< Nodes hash table link */207 link_t nh_link; /**< Nodes hash table link */ 198 208 cdfs_dentry_type_t type; /**< Dentry type */ 199 209 … … 216 226 static hash_table_t nodes; 217 227 218 /* 219 * Hash table support functions. 220 */ 221 222 typedef struct { 223 service_id_t service_id; 224 fs_index_t index; 225 } ht_key_t; 226 227 static 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 233 static 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 239 static 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 247 static void nodes_remove_callback(ht_link_t *item) 248 { 249 cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link); 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); 250 255 251 256 assert(node->type == CDFS_DIRECTORY); … … 263 268 264 269 /** Nodes hash table operations */ 265 static hash_table_op s_t nodes_ops = {270 static hash_table_operations_t nodes_ops = { 266 271 .hash = nodes_hash, 267 .key_hash = nodes_key_hash, 268 .key_equal = nodes_key_equal, 269 .equal = NULL, 272 .compare = nodes_compare, 270 273 .remove_callback = nodes_remove_callback 271 274 }; … … 274 277 fs_index_t index) 275 278 { 276 ht_key_t key= {277 .index = index,278 .service_id = service_id279 unsigned long key[] = { 280 [NODES_KEY_SRVC] = service_id, 281 [NODES_KEY_INDEX] = index 279 282 }; 280 283 281 ht_link_t *link = hash_table_find(&nodes, &key);284 link_t *link = hash_table_find(&nodes, key); 282 285 if (link) { 283 286 cdfs_node_t *node = 284 hash_table_get_inst (link, cdfs_node_t, nh_link);287 hash_table_get_instance(link, cdfs_node_t, nh_link); 285 288 286 289 *rfn = FS_NODE(node); … … 308 311 node->opened = 0; 309 312 313 link_initialize(&node->nh_link); 310 314 list_initialize(&node->cs_list); 311 315 } … … 349 353 350 354 /* Insert the new node into the nodes hash table. */ 351 hash_table_insert(&nodes, &node->nh_link); 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); 352 361 353 362 *rfn = FS_NODE(node); … … 499 508 static fs_node_t *get_cached_node(service_id_t service_id, fs_index_t index) 500 509 { 501 ht_key_t key= {502 .index = index,503 .service_id = service_id510 unsigned long key[] = { 511 [NODES_KEY_SRVC] = service_id, 512 [NODES_KEY_INDEX] = index 504 513 }; 505 514 506 ht_link_t *link = hash_table_find(&nodes, &key);515 link_t *link = hash_table_find(&nodes, key); 507 516 if (link) { 508 517 cdfs_node_t *node = 509 hash_table_get_inst (link, cdfs_node_t, nh_link);518 hash_table_get_instance(link, cdfs_node_t, nh_link); 510 519 return FS_NODE(node); 511 520 } … … 660 669 */ 661 670 if ((vol_desc->type != VOL_DESC_PRIMARY) || 662 ( memcmp(vol_desc->standard_ident, CDFS_STANDARD_IDENT, 5) != 0) ||671 (bcmp(vol_desc->standard_ident, CDFS_STANDARD_IDENT, 5) != 0) || 663 672 (vol_desc->version != 1)) { 664 673 block_put(block); … … 793 802 } 794 803 795 static 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 807 804 static void cdfs_instance_done(service_id_t service_id) 808 805 { 809 hash_table_apply(&nodes, rm_service_id_nodes, &service_id); 806 unsigned long key[] = { 807 [NODES_KEY_SRVC] = service_id 808 }; 809 810 hash_table_remove(&nodes, key, 1); 810 811 block_cache_fini(service_id); 811 812 block_fini(service_id); … … 821 822 size_t *rbytes) 822 823 { 823 ht_key_t key= {824 .index = index,825 .service_id = service_id824 unsigned long key[] = { 825 [NODES_KEY_SRVC] = service_id, 826 [NODES_KEY_INDEX] = index 826 827 }; 827 828 828 ht_link_t *link = hash_table_find(&nodes, &key);829 link_t *link = hash_table_find(&nodes, key); 829 830 if (link == NULL) 830 831 return ENOENT; 831 832 832 833 cdfs_node_t *node = 833 hash_table_get_inst (link, cdfs_node_t, nh_link);834 hash_table_get_instance(link, cdfs_node_t, nh_link); 834 835 835 836 if (!node->processed) { … … 911 912 } 912 913 913 static 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; 914 static void cleanup_cache(service_id_t service_id) 915 { 916 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 } 926 943 } 927 }928 929 /* Only continue if more nodes were requested to be removed. */930 return 0 < *premove_cnt;931 }932 933 static void cleanup_cache(service_id_t service_id)934 {935 if (nodes_cached > NODE_CACHE_SIZE) {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);940 944 } 941 945 } … … 947 951 return EOK; 948 952 949 ht_key_t key= {950 .index = index,951 .service_id = service_id953 unsigned long key[] = { 954 [NODES_KEY_SRVC] = service_id, 955 [NODES_KEY_INDEX] = index 952 956 }; 953 957 954 ht_link_t *link = hash_table_find(&nodes, &key);958 link_t *link = hash_table_find(&nodes, key); 955 959 if (link == 0) 956 960 return ENOENT; 957 961 958 962 cdfs_node_t *node = 959 hash_table_get_inst (link, cdfs_node_t, nh_link);963 hash_table_get_instance(link, cdfs_node_t, nh_link); 960 964 961 965 assert(node->opened > 0); … … 1003 1007 bool cdfs_init(void) 1004 1008 { 1005 if (!hash_table_create(&nodes, 0, 0, &nodes_ops))1009 if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops)) 1006 1010 return false; 1007 1011
Note:
See TracChangeset
for help on using the changeset viewer.