Changeset d1ac0d7 in mainline
- Timestamp:
- 2011-05-03T20:37:06Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 423f64f
- Parents:
- daa36d3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/ext2fs/ext2fs_ops.c
rdaa36d3 rd1ac0d7 62 62 #define EXT2FS_NODE(node) ((node) ? (ext2fs_node_t *) (node)->data : NULL) 63 63 #define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);} 64 #define OPEN_NODES_KEYS 2 65 #define OPEN_NODES_DEV_HANDLE_KEY 0 66 #define OPEN_NODES_INODE_KEY 1 67 #define OPEN_NODES_BUCKETS 256 64 68 65 69 typedef struct ext2fs_instance { … … 67 71 devmap_handle_t devmap_handle; 68 72 ext2_filesystem_t *filesystem; 73 unsigned int open_nodes_count; 69 74 } ext2fs_instance_t; 70 75 … … 72 77 ext2fs_instance_t *instance; 73 78 ext2_inode_ref_t *inode_ref; 79 fs_node_t *fs_node; 80 link_t link; 81 unsigned int references; 74 82 } ext2fs_node_t; 75 83 … … 84 92 static bool ext2fs_is_dots(const uint8_t *, size_t); 85 93 static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t); 94 static int ext2fs_node_put_core(ext2fs_node_t *); 86 95 87 96 /* … … 111 120 static LIST_INITIALIZE(instance_list); 112 121 static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex); 122 static hash_table_t open_nodes; 123 static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock); 124 125 /* Hash table interface for open nodes hash table */ 126 static hash_index_t open_nodes_hash(unsigned long key[]) 127 { 128 /* TODO: This is very simple and probably can be improved */ 129 return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS; 130 } 131 132 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 133 link_t *item) 134 { 135 ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link); 136 assert(keys > 0); 137 if (enode->instance->devmap_handle != 138 ((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) { 139 return false; 140 } 141 if (keys == 1) { 142 return true; 143 } 144 assert(keys == 2); 145 return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]); 146 } 147 148 static void open_nodes_remove_cb(link_t *link) 149 { 150 /* We don't use remove callback for this hash table */ 151 } 152 153 static hash_table_operations_t open_nodes_ops = { 154 .hash = open_nodes_hash, 155 .compare = open_nodes_compare, 156 .remove_callback = open_nodes_remove_cb, 157 }; 113 158 114 159 /** … … 117 162 int ext2fs_global_init(void) 118 163 { 164 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 165 OPEN_NODES_KEYS, &open_nodes_ops)) { 166 return ENOMEM; 167 } 119 168 return EOK; 120 169 } … … 122 171 int ext2fs_global_fini(void) 123 172 { 173 hash_table_destroy(&open_nodes); 124 174 return EOK; 125 175 } 126 127 176 128 177 … … 262 311 ext2_inode_ref_t *inode_ref = NULL; 263 312 313 fibril_mutex_lock(&open_nodes_lock); 314 315 /* Check if the node is not already open */ 316 unsigned long key[] = { 317 [OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle, 318 [OPEN_NODES_INODE_KEY] = index, 319 }; 320 link_t *already_open = hash_table_find(&open_nodes, key); 321 322 if (already_open) { 323 enode = hash_table_get_instance(already_open, ext2fs_node_t, link); 324 *rfn = enode->fs_node; 325 enode->references++; 326 327 fibril_mutex_unlock(&open_nodes_lock); 328 return EOK; 329 } 330 264 331 enode = malloc(sizeof(ext2fs_node_t)); 265 332 if (enode == NULL) { 333 fibril_mutex_unlock(&open_nodes_lock); 266 334 return ENOMEM; 267 335 } … … 270 338 if (node == NULL) { 271 339 free(enode); 340 fibril_mutex_unlock(&open_nodes_lock); 272 341 return ENOMEM; 273 342 } … … 278 347 free(enode); 279 348 free(node); 349 fibril_mutex_unlock(&open_nodes_lock); 280 350 return rc; 281 351 } … … 283 353 enode->inode_ref = inode_ref; 284 354 enode->instance = inst; 355 enode->references = 1; 356 enode->fs_node = node; 357 link_initialize(&enode->link); 358 285 359 node->data = enode; 286 360 *rfn = node; 287 361 362 hash_table_insert(&open_nodes, key, &enode->link); 363 inst->open_nodes_count++; 364 288 365 EXT2FS_DBG("inode: %u", inode_ref->index); 289 366 290 367 EXT2FS_DBG("EOK"); 291 368 369 fibril_mutex_unlock(&open_nodes_lock); 292 370 return EOK; 293 371 } … … 308 386 int rc; 309 387 ext2fs_node_t *enode = EXT2FS_NODE(fn); 388 389 fibril_mutex_lock(&open_nodes_lock); 390 391 assert(enode->references > 0); 392 enode->references--; 393 if (enode->references == 0) { 394 rc = ext2fs_node_put_core(enode); 395 if (rc != EOK) { 396 fibril_mutex_unlock(&open_nodes_lock); 397 return rc; 398 } 399 } 400 401 fibril_mutex_unlock(&open_nodes_lock); 402 403 return EOK; 404 } 405 406 int ext2fs_node_put_core(ext2fs_node_t *enode) 407 { 408 int rc; 409 410 unsigned long key[] = { 411 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle, 412 [OPEN_NODES_INODE_KEY] = enode->inode_ref->index, 413 }; 414 hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS); 415 assert(enode->instance->open_nodes_count > 0); 416 enode->instance->open_nodes_count--; 417 310 418 rc = ext2_filesystem_put_inode_ref(enode->inode_ref); 311 419 if (rc != EOK) { 312 420 EXT2FS_DBG("ext2_filesystem_put_inode_ref failed"); 313 } 314 return rc; 421 return rc; 422 } 423 424 free(enode->fs_node); 425 free(enode); 426 return EOK; 315 427 } 316 428 … … 544 656 } 545 657 546 /* Initialize instance and add to the list*/658 /* Initialize instance */ 547 659 link_initialize(&inst->link); 548 660 inst->devmap_handle = devmap_handle; 549 661 inst->filesystem = fs; 550 662 inst->open_nodes_count = 0; 663 664 /* Read root node */ 665 fs_node_t *root_node; 666 rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX); 667 if (rc != EOK) { 668 ext2_filesystem_fini(fs); 669 free(fs); 670 free(inst); 671 async_answer_0(rid, rc); 672 return; 673 } 674 ext2fs_node_t *enode = EXT2FS_NODE(root_node); 675 676 /* Add instance to the list */ 551 677 fibril_mutex_lock(&instance_list_mutex); 552 678 list_append(&inst->link, &instance_list); 553 679 fibril_mutex_unlock(&instance_list_mutex); 554 680 555 async_answer_0(rid, EOK); 681 async_answer_3(rid, EOK, 682 EXT2_INODE_ROOT_INDEX, 683 0, 684 ext2_inode_get_usage_count(enode->inode_ref->inode)); 685 686 ext2fs_node_put(root_node); 556 687 } 557 688 … … 576 707 } 577 708 578 // TODO: check if the fs is busy 709 fibril_mutex_lock(&open_nodes_lock); 710 711 EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count) 712 if (inst->open_nodes_count != 0) { 713 fibril_mutex_unlock(&open_nodes_lock); 714 async_answer_0(rid, EBUSY); 715 return; 716 } 579 717 580 718 // Remove the instance from list … … 582 720 list_remove(&inst->link); 583 721 fibril_mutex_unlock(&instance_list_mutex); 722 723 fibril_mutex_unlock(&open_nodes_lock); 584 724 585 725 ext2_filesystem_fini(inst->filesystem);
Note:
See TracChangeset
for help on using the changeset viewer.