Changeset 9b9d37bb in mainline for uspace/srv/fs/ext4fs/ext4fs_ops.c
- Timestamp:
- 2011-10-06T09:48:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1114173
- Parents:
- 3712434
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/ext4fs/ext4fs_ops.c
r3712434 r9b9d37bb 40 40 #include <libext4.h> 41 41 #include <libfs.h> 42 #include <macros.h> 42 43 #include <malloc.h> 43 #include <stdio.h>44 44 #include <adt/hash_table.h> 45 45 #include <ipc/loc.h> … … 48 48 49 49 #define EXT4FS_NODE(node) ((node) ? (ext4fs_node_t *) (node)->data : NULL) 50 #define EXT4FS_DBG(format, ...) {if (true) printf("ext4fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}51 50 52 51 #define OPEN_NODES_KEYS 2 … … 73 72 * Forward declarations of auxiliary functions 74 73 */ 74 75 static int ext4fs_read_directory(ipc_callid_t, aoff64_t, size_t, 76 ext4fs_instance_t *, ext4_inode_ref_t *, size_t *); 77 static int ext4fs_read_file(ipc_callid_t, aoff64_t, size_t, ext4fs_instance_t *, 78 ext4_inode_ref_t *, size_t *); 79 static bool ext4fs_is_dots(const uint8_t *, size_t); 75 80 static int ext4fs_instance_get(service_id_t, ext4fs_instance_t **); 76 81 static int ext4fs_node_get_core(fs_node_t **, ext4fs_instance_t *, fs_index_t); … … 142 147 int ext4fs_global_init(void) 143 148 { 149 EXT4FS_DBG(""); 150 144 151 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 145 152 OPEN_NODES_KEYS, &open_nodes_ops)) { … … 152 159 int ext4fs_global_fini(void) 153 160 { 161 EXT4FS_DBG(""); 162 154 163 hash_table_destroy(&open_nodes); 155 164 return EOK; … … 169 178 fibril_mutex_lock(&instance_list_mutex); 170 179 171 EXT4FS_DBG("Checking lists");172 173 180 if (list_empty(&instance_list)) { 174 181 fibril_mutex_unlock(&instance_list_mutex); 175 182 return EINVAL; 176 183 } 177 178 EXT4FS_DBG("checked");179 184 180 185 list_foreach(instance_list, link) { … … 188 193 } 189 194 190 EXT4FS_DBG("Not found");191 192 195 fibril_mutex_unlock(&instance_list_mutex); 193 196 return EINVAL; … … 197 200 int ext4fs_root_get(fs_node_t **rfn, service_id_t service_id) 198 201 { 202 EXT4FS_DBG(""); 203 199 204 return ext4fs_node_get(rfn, service_id, EXT4_INODE_ROOT_INDEX); 200 205 } … … 203 208 int ext4fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 204 209 { 205 // TODO 210 EXT4FS_DBG(""); 211 212 ext4fs_node_t *eparent = EXT4FS_NODE(pfn); 213 ext4_filesystem_t *fs; 214 ext4_directory_iterator_t it; 215 int rc; 216 size_t name_size; 217 size_t component_size; 218 bool found = false; 219 uint32_t inode; 220 221 fs = eparent->instance->filesystem; 222 223 if (!ext4_inode_is_type(fs->superblock, eparent->inode_ref->inode, 224 EXT4_INODE_MODE_DIRECTORY)) { 225 return ENOTDIR; 226 } 227 228 rc = ext4_directory_iterator_init(&it, fs, eparent->inode_ref, 0); 229 if (rc != EOK) { 230 return rc; 231 } 232 233 /* Find length of component in bytes 234 * TODO: check for library function call that does this 235 */ 236 component_size = 0; 237 while (*(component+component_size) != 0) { 238 component_size++; 239 } 240 241 while (it.current != NULL) { 242 inode = ext4_directory_entry_ll_get_inode(it.current); 243 244 /* ignore empty directory entries */ 245 if (inode != 0) { 246 name_size = ext4_directory_entry_ll_get_name_length(fs->superblock, 247 it.current); 248 249 if (name_size == component_size && bcmp(component, &it.current->name, 250 name_size) == 0) { 251 rc = ext4fs_node_get_core(rfn, eparent->instance, 252 inode); 253 if (rc != EOK) { 254 ext4_directory_iterator_fini(&it); 255 return rc; 256 } 257 found = true; 258 break; 259 } 260 } 261 262 rc = ext4_directory_iterator_next(&it); 263 if (rc != EOK) { 264 ext4_directory_iterator_fini(&it); 265 return rc; 266 } 267 } 268 269 ext4_directory_iterator_fini(&it); 270 271 if (!found) { 272 return ENOENT; 273 } 274 206 275 return EOK; 207 276 } … … 225 294 fs_index_t index) 226 295 { 227 228 296 int rc; 229 297 fs_node_t *node = NULL; … … 290 358 291 359 292 int ext4fs_node_put_core(ext4fs_node_t *enode) { 293 // TODO 360 int ext4fs_node_put_core(ext4fs_node_t *enode) 361 { 362 int rc; 363 unsigned long key[] = { 364 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id, 365 [OPEN_NODES_INODE_KEY] = enode->inode_ref->index, 366 }; 367 368 hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS); 369 assert(enode->instance->open_nodes_count > 0); 370 enode->instance->open_nodes_count--; 371 372 rc = ext4_filesystem_put_inode_ref(enode->inode_ref); 373 if (rc != EOK) { 374 return rc; 375 } 376 377 free(enode->fs_node); 378 free(enode); 379 294 380 return EOK; 295 381 } … … 304 390 int ext4fs_node_put(fs_node_t *fn) 305 391 { 306 EXT4FS_DBG("");307 392 int rc; 308 393 ext4fs_node_t *enode = EXT4FS_NODE(fn); … … 328 413 int ext4fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 329 414 { 415 EXT4FS_DBG(""); 416 330 417 // TODO 331 418 return ENOTSUP; … … 335 422 int ext4fs_destroy_node(fs_node_t *fn) 336 423 { 424 EXT4FS_DBG(""); 425 337 426 // TODO 338 427 return ENOTSUP; … … 342 431 int ext4fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 343 432 { 433 EXT4FS_DBG(""); 434 344 435 // TODO 345 436 return ENOTSUP; … … 349 440 int ext4fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 350 441 { 442 EXT4FS_DBG(""); 443 351 444 // TODO 352 445 return ENOTSUP; … … 356 449 int ext4fs_has_children(bool *has_children, fs_node_t *fn) 357 450 { 451 EXT4FS_DBG(""); 452 358 453 // TODO 359 454 return EOK; … … 363 458 fs_index_t ext4fs_index_get(fs_node_t *fn) 364 459 { 365 // TODO366 return 0;460 ext4fs_node_t *enode = EXT4FS_NODE(fn); 461 return enode->inode_ref->index; 367 462 } 368 463 … … 370 465 aoff64_t ext4fs_size_get(fs_node_t *fn) 371 466 { 372 // TODO 373 return 0; 467 ext4fs_node_t *enode = EXT4FS_NODE(fn); 468 aoff64_t size = ext4_inode_get_size(enode->instance->filesystem->superblock, 469 enode->inode_ref->inode); 470 return size; 374 471 } 375 472 … … 377 474 unsigned ext4fs_lnkcnt_get(fs_node_t *fn) 378 475 { 379 // TODO 380 return 0; 476 ext4fs_node_t *enode = EXT4FS_NODE(fn); 477 unsigned count = ext4_inode_get_links_count(enode->inode_ref->inode); 478 return count; 381 479 } 382 480 … … 384 482 bool ext4fs_is_directory(fs_node_t *fn) 385 483 { 484 EXT4FS_DBG(""); 485 386 486 // TODO 387 487 return false; … … 391 491 bool ext4fs_is_file(fs_node_t *fn) 392 492 { 393 // TODO 394 return false; 493 ext4fs_node_t *enode = EXT4FS_NODE(fn); 494 bool is_file = ext4_inode_is_type(enode->instance->filesystem->superblock, 495 enode->inode_ref->inode, EXT4_INODE_MODE_FILE); 496 return is_file; 395 497 } 396 498 … … 398 500 service_id_t ext4fs_service_get(fs_node_t *fn) 399 501 { 502 EXT4FS_DBG(""); 503 400 504 // TODO 401 505 return 0; … … 432 536 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt) 433 537 { 538 EXT4FS_DBG(""); 434 539 435 540 int rc; … … 511 616 static int ext4fs_unmounted(service_id_t service_id) 512 617 { 618 EXT4FS_DBG(""); 513 619 514 620 int rc; … … 545 651 size_t *rbytes) 546 652 { 547 // TODO 548 return 0; 549 } 550 653 EXT4FS_DBG(""); 654 655 ext4fs_instance_t *inst; 656 ext4_inode_ref_t *inode_ref; 657 int rc; 658 659 /* 660 * Receive the read request. 661 */ 662 ipc_callid_t callid; 663 size_t size; 664 if (!async_data_read_receive(&callid, &size)) { 665 async_answer_0(callid, EINVAL); 666 return EINVAL; 667 } 668 669 rc = ext4fs_instance_get(service_id, &inst); 670 if (rc != EOK) { 671 async_answer_0(callid, rc); 672 return rc; 673 } 674 675 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); 676 if (rc != EOK) { 677 async_answer_0(callid, rc); 678 return rc; 679 } 680 681 if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode, 682 EXT4_INODE_MODE_FILE)) { 683 rc = ext4fs_read_file(callid, pos, size, inst, inode_ref, 684 rbytes); 685 } else if (ext4_inode_is_type(inst->filesystem->superblock, 686 inode_ref->inode, EXT4_INODE_MODE_DIRECTORY)) { 687 rc = ext4fs_read_directory(callid, pos, size, inst, inode_ref, 688 rbytes); 689 } else { 690 /* Other inode types not supported */ 691 async_answer_0(callid, ENOTSUP); 692 rc = ENOTSUP; 693 } 694 695 ext4_filesystem_put_inode_ref(inode_ref); 696 return rc; 697 } 698 699 bool ext4fs_is_dots(const uint8_t *name, size_t name_size) { 700 if (name_size == 1 && name[0] == '.') { 701 return true; 702 } 703 704 if (name_size == 2 && name[0] == '.' && name[1] == '.') { 705 return true; 706 } 707 708 return false; 709 } 710 711 int ext4fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size, 712 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) 713 { 714 EXT4FS_DBG(""); 715 716 ext4_directory_iterator_t it; 717 aoff64_t next; 718 uint8_t *buf; 719 size_t name_size; 720 int rc; 721 bool found = false; 722 723 rc = ext4_directory_iterator_init(&it, inst->filesystem, inode_ref, pos); 724 if (rc != EOK) { 725 async_answer_0(callid, rc); 726 return rc; 727 } 728 729 /* Find next interesting directory entry. 730 * We want to skip . and .. entries 731 * as these are not used in HelenOS 732 */ 733 while (it.current != NULL) { 734 if (it.current->inode == 0) { 735 goto skip; 736 } 737 738 name_size = ext4_directory_entry_ll_get_name_length( 739 inst->filesystem->superblock, it.current); 740 741 /* skip . and .. */ 742 if (ext4fs_is_dots(&it.current->name, name_size)) { 743 goto skip; 744 } 745 746 /* The on-disk entry does not contain \0 at the end 747 * end of entry name, so we copy it to new buffer 748 * and add the \0 at the end 749 */ 750 buf = malloc(name_size+1); 751 if (buf == NULL) { 752 ext4_directory_iterator_fini(&it); 753 async_answer_0(callid, ENOMEM); 754 return ENOMEM; 755 } 756 memcpy(buf, &it.current->name, name_size); 757 *(buf + name_size) = 0; 758 found = true; 759 (void) async_data_read_finalize(callid, buf, name_size + 1); 760 free(buf); 761 break; 762 763 skip: 764 rc = ext4_directory_iterator_next(&it); 765 if (rc != EOK) { 766 ext4_directory_iterator_fini(&it); 767 async_answer_0(callid, rc); 768 return rc; 769 } 770 } 771 772 if (found) { 773 rc = ext4_directory_iterator_next(&it); 774 if (rc != EOK) 775 return rc; 776 next = it.current_offset; 777 } 778 779 rc = ext4_directory_iterator_fini(&it); 780 if (rc != EOK) 781 return rc; 782 783 if (found) { 784 *rbytes = next - pos; 785 return EOK; 786 } else { 787 async_answer_0(callid, ENOENT); 788 return ENOENT; 789 } 790 } 791 792 int ext4fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size, 793 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) 794 { 795 EXT4FS_DBG(""); 796 797 int rc; 798 uint32_t block_size; 799 aoff64_t file_block; 800 uint64_t file_size; 801 uint32_t fs_block; 802 size_t offset_in_block; 803 size_t bytes; 804 block_t *block; 805 uint8_t *buffer; 806 807 file_size = ext4_inode_get_size(inst->filesystem->superblock, 808 inode_ref->inode); 809 810 if (pos >= file_size) { 811 /* Read 0 bytes successfully */ 812 async_data_read_finalize(callid, NULL, 0); 813 *rbytes = 0; 814 return EOK; 815 } 816 817 /* For now, we only read data from one block at a time */ 818 block_size = ext4_superblock_get_block_size(inst->filesystem->superblock); 819 file_block = pos / block_size; 820 offset_in_block = pos % block_size; 821 bytes = min(block_size - offset_in_block, size); 822 823 /* Handle end of file */ 824 if (pos + bytes > file_size) { 825 bytes = file_size - pos; 826 } 827 828 /* Get the real block number */ 829 rc = ext4_filesystem_get_inode_data_block_index(inst->filesystem, 830 inode_ref->inode, file_block, &fs_block); 831 if (rc != EOK) { 832 async_answer_0(callid, rc); 833 return rc; 834 } 835 836 /* Check for sparse file 837 * If ext2_filesystem_get_inode_data_block_index returned 838 * fs_block == 0, it means that the given block is not allocated for the 839 * file and we need to return a buffer of zeros 840 */ 841 if (fs_block == 0) { 842 buffer = malloc(bytes); 843 if (buffer == NULL) { 844 async_answer_0(callid, ENOMEM); 845 return ENOMEM; 846 } 847 848 memset(buffer, 0, bytes); 849 850 async_data_read_finalize(callid, buffer, bytes); 851 *rbytes = bytes; 852 853 free(buffer); 854 855 return EOK; 856 } 857 858 /* Usual case - we need to read a block from device */ 859 rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE); 860 if (rc != EOK) { 861 async_answer_0(callid, rc); 862 return rc; 863 } 864 865 assert(offset_in_block + bytes <= block_size); 866 async_data_read_finalize(callid, block->data + offset_in_block, bytes); 867 868 rc = block_put(block); 869 if (rc != EOK) 870 return rc; 871 872 *rbytes = bytes; 873 return EOK; 874 } 551 875 552 876 static int
Note:
See TracChangeset
for help on using the changeset viewer.