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