Changeset 1fff583 in mainline
- Timestamp:
- 2012-04-12T12:16:32Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 831507b
- Parents:
- 7eb033ce
- Location:
- uspace/srv/fs/ext4fs
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/ext4fs/ext4fs.c
r7eb033ce r1fff583 53 53 }; 54 54 55 /** 56 * Entry point of ext4fs server. 57 * Initialize data structures and IPC, then accepts connections in server mode. 58 */ 55 59 int main(int argc, char **argv) 56 60 { -
uspace/srv/fs/ext4fs/ext4fs_ops.c
r7eb033ce r1fff583 55 55 #define OPEN_NODES_BUCKETS 256 56 56 57 /** 58 * Type for holding an instance of mounted partition. 59 */ 57 60 typedef struct ext4fs_instance { 58 61 link_t link; … … 62 65 } ext4fs_instance_t; 63 66 67 /** 68 * Type for wrapping common fs_node and add some useful pointers. 69 */ 64 70 typedef struct ext4fs_node { 65 71 ext4fs_instance_t *instance; … … 70 76 } ext4fs_node_t; 71 77 72 /* 73 * Forward declarations of auxiliary functions 74 */ 78 // Forward declarations of auxiliary functions 75 79 76 80 static int ext4fs_read_directory(ipc_callid_t, aoff64_t, size_t, … … 83 87 static int ext4fs_node_put_core(ext4fs_node_t *); 84 88 85 /* 86 * Forward declarations of EXT4 libfs operations. 87 */ 89 // Forward declarations of EXT4 libfs operations. 90 88 91 static int ext4fs_root_get(fs_node_t **, service_id_t); 89 92 static int ext4fs_match(fs_node_t **, fs_node_t *, const char *); … … 103 106 static service_id_t ext4fs_service_get(fs_node_t *node); 104 107 105 /* 106 * Static variables 107 */ 108 // Static variables 109 108 110 static LIST_INITIALIZE(instance_list); 109 111 static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex); … … 118 120 } 119 121 122 /** Compare given item with values in hash table. 123 * 124 * @return bool result of compare operation 125 */ 120 126 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 121 127 link_t *item) … … 134 140 } 135 141 142 /** Empty callback to correct hash table initialization. 143 * 144 */ 136 145 static void open_nodes_remove_cb(link_t *link) 137 146 { … … 146 155 147 156 157 /** Basic initialization of the driver. 158 * 159 * There is only needed to create hash table for storing open nodes. 160 * 161 * @return error code 162 */ 148 163 int ext4fs_global_init(void) 149 164 { … … 155 170 } 156 171 157 172 /* Finalization of the driver. 173 * 174 * There is only needed to destroy hash table. 175 * 176 * @return error code 177 */ 158 178 int ext4fs_global_fini(void) 159 179 { … … 167 187 */ 168 188 189 /** Get instance from internal table by service_id. 190 * 191 * @param service_id device identifier 192 * @param inst output instance if successful operation 193 * @return error code 194 */ 169 195 int ext4fs_instance_get(service_id_t service_id, ext4fs_instance_t **inst) 170 196 { … … 192 218 193 219 220 /** Get root node of filesystem specified by service_id. 221 * 222 * @param rfn output pointer to loaded node 223 * @param service_id device to load root node from 224 * @return error code 225 */ 194 226 int ext4fs_root_get(fs_node_t **rfn, service_id_t service_id) 195 227 { … … 197 229 } 198 230 199 231 /** Check if specified name (component) matches with any directory entry. 232 * 233 * If match is found, load and return matching node. 234 * 235 * @param rfn output pointer to node if operation successful 236 * @param pfn parent directory node 237 * @param component name to check directory for 238 * @return error code 239 */ 200 240 int ext4fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 201 241 { … … 235 275 } 236 276 237 277 /** Get node specified by index 278 * 279 * It's wrapper for node_put_core operation 280 * 281 * @param rfn output pointer to loaded node if operation successful 282 * @param service_id device identifier 283 * @param index node index (here i-node number) 284 * @return error code 285 */ 238 286 int ext4fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) 239 287 { … … 249 297 } 250 298 251 299 /** Main function for getting node from the filesystem. 300 * 301 * @param rfn output point to loaded node if operation successful 302 * @param inst instance of filesystem 303 * @param index index of node (i-node number) 304 * @return error code 305 */ 252 306 int ext4fs_node_get_core(fs_node_t **rfn, ext4fs_instance_t *inst, 253 307 fs_index_t index) … … 274 328 } 275 329 330 // Prepare new enode 276 331 enode = malloc(sizeof(ext4fs_node_t)); 277 332 if (enode == NULL) { … … 288 343 fs_node_initialize(fs_node); 289 344 345 // Load inode from filesystem 290 346 ext4_inode_ref_t *inode_ref; 291 347 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); … … 297 353 } 298 354 355 // Initialize enode 299 356 enode->inode_ref = inode_ref; 300 357 enode->instance = inst; … … 314 371 } 315 372 316 373 /** Put previously loaded node. 374 * 375 * @param enode node to put back 376 * @return error code 377 */ 317 378 int ext4fs_node_put_core(ext4fs_node_t *enode) 318 379 { … … 327 388 enode->instance->open_nodes_count--; 328 389 390 // Put inode back in filesystem 329 391 rc = ext4_filesystem_put_inode_ref(enode->inode_ref); 330 392 if (rc != EOK) { … … 332 394 } 333 395 396 // Destroy data structure 334 397 free(enode->fs_node); 335 398 free(enode); … … 339 402 340 403 404 /** Open node. 405 * 406 * This operation is stateless in this driver. 407 * 408 * @param fn node to open 409 * @return error code (EOK) 410 */ 341 411 int ext4fs_node_open(fs_node_t *fn) 342 412 { … … 345 415 } 346 416 417 418 /** Put previously loaded node. 419 * 420 * It's wrapper for node_put_core operation 421 * 422 * @param fn node to put back 423 * @return error code 424 */ 347 425 int ext4fs_node_put(fs_node_t *fn) 348 426 { … … 368 446 369 447 448 /** Create new node in filesystem. 449 * 450 * @param rfn output pointer to newly created node if successful 451 * @param service_id device identifier, where the filesystem is 452 * @param flags flags for specification of new node parameters 453 * @return error code 454 */ 370 455 int ext4fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 371 456 { 372 457 int rc; 373 458 459 // Allocate node structures 374 460 ext4fs_node_t *enode; 375 461 enode = malloc(sizeof(ext4fs_node_t)); … … 385 471 } 386 472 473 // Load instance 387 474 ext4fs_instance_t *inst; 388 475 rc = ext4fs_instance_get(service_id, &inst); … … 393 480 } 394 481 482 // Allocate new i-node in filesystem 395 483 ext4_inode_ref_t *inode_ref; 396 484 rc = ext4_filesystem_alloc_inode(inst->filesystem, &inode_ref, flags); … … 401 489 } 402 490 491 // Do some interconnections in references 403 492 enode->inode_ref = inode_ref; 404 493 enode->instance = inst; … … 428 517 429 518 519 /** Destroy existing node. 520 * 521 * @param fs node to destroy 522 * @return error code 523 */ 430 524 int ext4fs_destroy_node(fs_node_t *fn) 431 525 { 432 526 int rc; 433 527 528 // If directory, check for children 434 529 bool has_children; 435 530 rc = ext4fs_has_children(&has_children, fn); … … 448 543 ext4_inode_ref_t *inode_ref = enode->inode_ref; 449 544 545 // Release data blocks 450 546 rc = ext4_filesystem_truncate_inode(inode_ref, 0); 451 547 if (rc != EOK) { … … 454 550 } 455 551 552 // Handle orphans 456 553 uint32_t rev_level = ext4_superblock_get_rev_level(fs->superblock); 457 554 if (rev_level > 0) { … … 459 556 } 460 557 461 // TODO set real deletion time 558 // TODO set real deletion time when it will be supported 462 559 // time_t now = time(NULL); 463 560 time_t now = ext4_inode_get_change_inode_time(inode_ref->inode); … … 465 562 inode_ref->dirty = true; 466 563 564 // Free inode 467 565 rc = ext4_filesystem_free_inode(inode_ref); 468 566 if (rc != EOK) { … … 476 574 477 575 576 /** Link the specfied node to directory. 577 * 578 * @param pfn parent node to link in 579 * @param cfn node to be linked 580 * @param name name which will be assigned to directory entry 581 * @return error code 582 */ 478 583 int ext4fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 479 584 { … … 510 615 } 511 616 617 // Initialize directory index if necessary 512 618 // if (ext4_superblock_has_feature_compatible( 513 619 // fs->superblock, EXT4_FEATURE_COMPAT_DIR_INDEX)) { … … 540 646 541 647 648 /** Unlink node from specified directory. 649 * 650 * @param pfn parent node to delete node from 651 * @param cfn child node to be unlinked from directory 652 * @param name name of entry that will be removed 653 * @return error code 654 */ 542 655 int ext4fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *name) 543 656 { … … 606 719 607 720 721 /** Check if specified node has children. 722 * 723 * For files is response allways false and check is executed only for directories. 724 * 725 * @param has_children output value for response 726 * @param fn node to check 727 * @return error code 728 */ 608 729 int ext4fs_has_children(bool *has_children, fs_node_t *fn) 609 730 { … … 613 734 ext4_filesystem_t *fs = enode->instance->filesystem; 614 735 736 // Check if node is directory 615 737 if (!ext4_inode_is_type(fs->superblock, enode->inode_ref->inode, 616 738 EXT4_INODE_MODE_DIRECTORY)) { … … 655 777 656 778 779 /** Unpack index number from node. 780 * 781 * @param fn node to load index from 782 * @return index number of i-node 783 */ 657 784 fs_index_t ext4fs_index_get(fs_node_t *fn) 658 785 { … … 662 789 663 790 791 /** Get real size of file / directory. 792 * 793 * @param fn node to get size of 794 * @return real size of node 795 */ 664 796 aoff64_t ext4fs_size_get(fs_node_t *fn) 665 797 { … … 670 802 671 803 804 /** Get number of links to specified node. 805 * 806 * @param fn node to get links to 807 * @return number of links 808 */ 672 809 unsigned ext4fs_lnkcnt_get(fs_node_t *fn) 673 810 { … … 688 825 689 826 827 /** Check if node is directory. 828 * 829 * @param fn node to check 830 * @return result of check 831 */ 690 832 bool ext4fs_is_directory(fs_node_t *fn) 691 833 { … … 697 839 698 840 841 /** Check if node is regular file. 842 * 843 * @param fn node to check 844 * @return result of check 845 */ 699 846 bool ext4fs_is_file(fs_node_t *fn) 700 847 { … … 705 852 } 706 853 707 854 /** Extract device identifier from node. 855 * 856 * @param node node to extract id from 857 * @return id of device, where is the filesystem 858 */ 708 859 service_id_t ext4fs_service_get(fs_node_t *fn) 709 860 { … … 739 890 */ 740 891 892 /** Mount operation. 893 * 894 * Try to mount specified filesystem from device. 895 * 896 * @param service_id identifier of device 897 * @param opts mount options 898 * @param index TODO 899 * @param size TODO 900 * @param lnkcnt TODO 901 * @return error code 902 */ 741 903 static int ext4fs_mounted(service_id_t service_id, const char *opts, 742 904 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt) … … 816 978 } 817 979 818 980 /** Unmount operation. 981 * 982 * Correctly release the filesystem. 983 * 984 * @param service_id device to be unmounted 985 * @return error code 986 */ 819 987 static int ext4fs_unmounted(service_id_t service_id) 820 988 { … … 845 1013 846 1014 1015 /** Read bytes from node. 1016 * 1017 * @param service_id device to read data from 1018 * @param index number of node to read from 1019 * @param pos position where the read should be started 1020 * @param rbytes output value, where the real size was returned 1021 * @return error code 1022 */ 847 1023 static int ext4fs_read(service_id_t service_id, fs_index_t index, 848 1024 aoff64_t pos, size_t *rbytes) … … 867 1043 } 868 1044 1045 // Load i-node 869 1046 ext4_inode_ref_t *inode_ref; 870 1047 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); … … 874 1051 } 875 1052 1053 // Read from i-node by type 876 1054 if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode, 877 1055 EXT4_INODE_MODE_FILE)) { … … 893 1071 } 894 1072 1073 /** Check if filename is dot or dotdot (reserved names). 1074 * 1075 * @param name name to check 1076 * @param name_size length of string name 1077 * @return result of the check 1078 */ 895 1079 bool ext4fs_is_dots(const uint8_t *name, size_t name_size) 896 1080 { … … 906 1090 } 907 1091 1092 /** Read data from directory. 1093 * 1094 * @param callid IPC id of call (for communication) 1095 * @param pos position to start reading from 1096 * @param size how many bytes to read 1097 * @param inst filesystem instance 1098 * @param inode_ref node to read data from 1099 * @param rbytes output value to return real number of bytes was read 1100 * @return error code 1101 */ 908 1102 int ext4fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size, 909 1103 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) … … 977 1171 } 978 1172 1173 // Prepare return values 979 1174 if (found) { 980 1175 *rbytes = next - pos; … … 986 1181 } 987 1182 1183 1184 /** Read data from file. 1185 * 1186 * @param callid IPC id of call (for communication) 1187 * @param pos position to start reading from 1188 * @param size how many bytes to read 1189 * @param inst filesystem instance 1190 * @param inode_ref node to read data from 1191 * @param rbytes output value to return real number of bytes was read 1192 * @return error code 1193 */ 988 1194 int ext4fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size, 989 1195 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) … … 1063 1269 } 1064 1270 1271 1272 /** Write bytes to file 1273 * 1274 * @param service_id device identifier 1275 * @param index i-node number of file 1276 * @param pos position in file to start reading from 1277 * @param wbytes TODO 1278 * @param nsize TODO 1279 * @return error code 1280 */ 1065 1281 static int ext4fs_write(service_id_t service_id, fs_index_t index, 1066 1282 aoff64_t pos, size_t *wbytes, aoff64_t *nsize) … … 1100 1316 uint32_t fblock; 1101 1317 1318 // Load inode 1102 1319 ext4_inode_ref_t *inode_ref = enode->inode_ref; 1103 1320 rc = ext4_filesystem_get_inode_data_block_index(inode_ref, iblock, &fblock); … … 1108 1325 } 1109 1326 1327 // Check for sparse file 1110 1328 if (fblock == 0) { 1111 1329 … … 1145 1363 } 1146 1364 1365 // Load target block 1147 1366 block_t *write_block; 1148 1367 rc = block_get(&write_block, service_id, fblock, flags); … … 1171 1390 } 1172 1391 1392 // Do some counting 1173 1393 uint32_t old_inode_size = ext4_inode_get_size(fs->superblock, inode_ref->inode); 1174 1394 if (pos + bytes > old_inode_size) { … … 1184 1404 1185 1405 1406 /** Truncate file. 1407 * 1408 * Only the direction to shorter file is supported. 1409 * 1410 * @param service_id device identifier 1411 * @param index index if node to truncated 1412 * @param new_size new size of file 1413 * @return error code 1414 */ 1186 1415 static int ext4fs_truncate(service_id_t service_id, fs_index_t index, 1187 1416 aoff64_t new_size) … … 1205 1434 1206 1435 1436 /** Close file. 1437 *' 1438 * @param service_id device identifier 1439 * @param index i-node number 1440 * @return error code 1441 */ 1207 1442 static int ext4fs_close(service_id_t service_id, fs_index_t index) 1208 1443 { … … 1211 1446 1212 1447 1448 /** Destroy node specified by index. 1449 * 1450 * @param service_id device identifier 1451 * @param index number of i-node to destroy 1452 * @return error code 1453 */ 1213 1454 static int ext4fs_destroy(service_id_t service_id, fs_index_t index) 1214 1455 { … … 1225 1466 } 1226 1467 1227 1468 /** Enforce inode synchronization (write) to device. 1469 * 1470 * @param service_id device identifier 1471 * @param index i-node number. 1472 */ 1228 1473 static int ext4fs_sync(service_id_t service_id, fs_index_t index) 1229 1474 { … … 1242 1487 } 1243 1488 1489 /** VFS operations 1490 * 1491 */ 1244 1492 vfs_out_ops_t ext4fs_ops = { 1245 1493 .mounted = ext4fs_mounted,
Note:
See TracChangeset
for help on using the changeset viewer.