Changes in uspace/srv/fs/mfs/mfs_ops.c [c2e50d7:5bf76c1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/mfs/mfs_ops.c
rc2e50d7 r5bf76c1 43 43 44 44 static bool check_magic_number(uint16_t magic, bool *native, 45 mfs_version_t *version, bool *longfilenames);45 mfs_version_t *version, bool *longfilenames); 46 46 static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst, 47 fs_index_t index); 47 fs_index_t index); 48 48 49 static int mfs_node_put(fs_node_t *fsnode); 49 50 static int mfs_node_open(fs_node_t *fsnode); … … 63 64 static hash_index_t open_nodes_hash(unsigned long key[]); 64 65 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 65 66 link_t *item); 66 67 static void open_nodes_remove_cb(link_t *link); 68 67 69 static int mfs_node_get(fs_node_t **rfn, service_id_t service_id, 68 fs_index_t index); 69 static int mfs_instance_get(service_id_t service_id, 70 struct mfs_instance **instance); 71 static int mfs_check_sanity(struct mfs_sb_info *sbi); 72 static bool is_power_of_two(uint32_t n); 70 fs_index_t index); 71 static int 72 mfs_instance_get(service_id_t service_id, struct mfs_instance **instance); 73 73 74 74 75 static hash_table_t open_nodes; … … 95 96 96 97 /* Hash table interface for open nodes hash table */ 97 static hash_index_t 98 open_nodes_hash(unsigned long key[]) 98 static hash_index_t open_nodes_hash(unsigned long key[]) 99 99 { 100 100 /* TODO: This is very simple and probably can be improved */ … … 102 102 } 103 103 104 static int 105 open_nodes_compare(unsigned long key[], hash_count_t keys, 106 link_t *item) 104 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 105 link_t *item) 107 106 { 108 107 struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link); … … 119 118 } 120 119 121 static void 122 open_nodes_remove_cb(link_t *link) 120 static void open_nodes_remove_cb(link_t *link) 123 121 { 124 122 /* We don't use remove callback for this hash table */ … … 131 129 }; 132 130 133 int 134 mfs_global_init(void) 131 int mfs_global_init(void) 135 132 { 136 133 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 137 134 OPEN_NODES_KEYS, &open_nodes_ops)) { 138 135 return ENOMEM; 139 136 } … … 143 140 static int 144 141 mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index, 145 142 aoff64_t *size, unsigned *linkcnt) 146 143 { 147 144 enum cache_mode cmode; 148 struct mfs_superblock *sb = NULL;149 struct mfs3_superblock *sb3 = NULL;150 struct mfs_sb_info *sbi = NULL;151 struct mfs_instance *instance = NULL;145 struct mfs_superblock *sb; 146 struct mfs3_superblock *sb3; 147 struct mfs_sb_info *sbi; 148 struct mfs_instance *instance; 152 149 bool native, longnames; 153 150 mfs_version_t version; … … 166 163 return rc; 167 164 168 /* Allocate space for generic MFS superblock*/165 /*Allocate space for generic MFS superblock*/ 169 166 sbi = malloc(sizeof(*sbi)); 170 167 if (!sbi) { 171 rc = ENOMEM;172 goto out_error;173 } 174 175 /* Allocate space for filesystem instance*/168 block_fini(service_id); 169 return ENOMEM; 170 } 171 172 /*Allocate space for filesystem instance*/ 176 173 instance = malloc(sizeof(*instance)); 177 174 if (!instance) { 178 rc = ENOMEM; 179 goto out_error; 175 free(sbi); 176 block_fini(service_id); 177 return ENOMEM; 180 178 } 181 179 182 180 sb = malloc(MFS_SUPERBLOCK_SIZE); 183 181 if (!sb) { 184 rc = ENOMEM; 185 goto out_error; 182 free(instance); 183 free(sbi); 184 block_fini(service_id); 185 return ENOMEM; 186 186 } 187 187 188 188 /* Read the superblock */ 189 189 rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb); 190 if (rc != EOK) 191 goto out_error; 190 if (rc != EOK) { 191 free(instance); 192 free(sbi); 193 free(sb); 194 block_fini(service_id); 195 return rc; 196 } 192 197 193 198 sb3 = (struct mfs3_superblock *) sb; 194 199 195 200 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) { 196 /* This is a V1 or V2 Minix filesystem*/201 /*This is a V1 or V2 Minix filesystem*/ 197 202 magic = sb->s_magic; 198 203 } else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) { 199 /* This is a V3 Minix filesystem*/204 /*This is a V3 Minix filesystem*/ 200 205 magic = sb3->s_magic; 201 206 } else { 202 /* Not recognized*/207 /*Not recognized*/ 203 208 mfsdebug("magic number not recognized\n"); 204 rc = ENOTSUP; 205 goto out_error; 209 free(instance); 210 free(sbi); 211 free(sb); 212 block_fini(service_id); 213 return ENOTSUP; 206 214 } 207 215 208 216 mfsdebug("magic number recognized = %04x\n", magic); 209 217 210 /* Fill superblock info structure*/218 /*Fill superblock info structure*/ 211 219 212 220 sbi->fs_version = version; … … 246 254 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE; 247 255 sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN : 248 MFS_MAX_NAME_LEN; 249 } 250 251 if (sbi->log2_zone_size != 0) { 252 /* In MFS, file space is allocated per zones. 253 * Zones are a collection of consecutive blocks on disk. 254 * 255 * The current MFS implementation supports only filesystems 256 * where the size of a zone is equal to the 257 * size of a block. 258 */ 259 rc = ENOTSUP; 260 goto out_error; 261 } 262 256 MFS_MAX_NAME_LEN; 257 } 263 258 sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks; 264 if ((rc = mfs_check_sanity(sbi)) != EOK) { 265 fprintf(stderr, "Filesystem corrupted, invalid superblock"); 266 goto out_error; 267 } 259 260 free(sb); 268 261 269 262 rc = block_cache_init(service_id, sbi->block_size, 0, cmode); 270 263 if (rc != EOK) { 264 free(instance); 265 free(sbi); 266 block_cache_fini(service_id); 267 block_fini(service_id); 271 268 mfsdebug("block cache initialization failed\n"); 272 rc = EINVAL; 273 goto out_error; 274 } 275 276 /* Initialize the instance structure and remember it */ 269 return EINVAL; 270 } 271 272 /*Initialize the instance structure and remember it*/ 277 273 instance->service_id = service_id; 278 274 instance->sbi = sbi; … … 280 276 rc = fs_instance_create(service_id, instance); 281 277 if (rc != EOK) { 278 free(instance); 279 free(sbi); 282 280 block_cache_fini(service_id); 281 block_fini(service_id); 283 282 mfsdebug("fs instance creation failed\n"); 284 goto out_error;283 return rc; 285 284 } 286 285 … … 296 295 *linkcnt = 1; 297 296 298 free(sb);299 300 297 return mfs_node_put(fn); 301 302 out_error:303 block_fini(service_id);304 if (sb)305 free(sb);306 if (sbi)307 free(sbi);308 if(instance)309 free(instance);310 return rc;311 298 } 312 299 … … 335 322 } 336 323 337 service_id_t 338 mfs_service_get(fs_node_t *fsnode) 324 service_id_t mfs_service_get(fs_node_t *fsnode) 339 325 { 340 326 struct mfs_node *node = fsnode->data; … … 342 328 } 343 329 344 static int 345 mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 330 static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 346 331 { 347 332 int r; … … 357 342 return r; 358 343 359 /* Alloc a new inode*/344 /*Alloc a new inode*/ 360 345 r = mfs_alloc_inode(inst, &inum); 361 346 if (r != EOK) … … 384 369 if (flags & L_DIRECTORY) { 385 370 ino_i->i_mode = S_IFDIR; 386 ino_i->i_nlinks = 1; /* This accounts for the '.' dentry*/387 } else 371 ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/ 372 } else { 388 373 ino_i->i_mode = S_IFREG; 374 ino_i->i_nlinks = 1; 375 } 389 376 390 377 ino_i->i_uid = 0; … … 435 422 } 436 423 437 static int 438 mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 424 static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 439 425 { 440 426 struct mfs_node *mnode = pfn->data; … … 458 444 459 445 if (!d_info.d_inum) { 460 /* This entry is not used*/446 /*This entry is not used*/ 461 447 continue; 462 448 } … … 465 451 466 452 if (comp_size == dentry_name_size && 467 468 /* Hit!*/453 !bcmp(component, d_info.d_name, dentry_name_size)) { 454 /*Hit!*/ 469 455 mfs_node_core_get(rfn, mnode->instance, 470 456 d_info.d_inum); 471 457 goto found; 472 458 } … … 477 463 } 478 464 479 static aoff64_t 480 mfs_size_get(fs_node_t *node) 465 static aoff64_t mfs_size_get(fs_node_t *node) 481 466 { 482 467 const struct mfs_node *mnode = node->data; … … 486 471 static int 487 472 mfs_node_get(fs_node_t **rfn, service_id_t service_id, 488 473 fs_index_t index) 489 474 { 490 475 int rc; … … 530 515 } 531 516 532 static int 533 mfs_node_open(fs_node_t *fsnode) 517 static int mfs_node_open(fs_node_t *fsnode) 534 518 { 535 519 /* … … 540 524 } 541 525 542 static fs_index_t 543 mfs_index_get(fs_node_t *fsnode) 526 static fs_index_t mfs_index_get(fs_node_t *fsnode) 544 527 { 545 528 struct mfs_node *mnode = fsnode->data; … … 547 530 } 548 531 549 static unsigned 550 mfs_lnkcnt_get(fs_node_t *fsnode) 532 static unsigned mfs_lnkcnt_get(fs_node_t *fsnode) 551 533 { 552 534 struct mfs_node *mnode = fsnode->data; … … 563 545 } 564 546 565 static int 566 mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst, 567 fs_index_t index) 547 static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst, 548 fs_index_t index) 568 549 { 569 550 fs_node_t *node = NULL; … … 637 618 } 638 619 639 static bool 640 mfs_is_directory(fs_node_t *fsnode) 620 static bool mfs_is_directory(fs_node_t *fsnode) 641 621 { 642 622 const struct mfs_node *node = fsnode->data; … … 644 624 } 645 625 646 static bool 647 mfs_is_file(fs_node_t *fsnode) 626 static bool mfs_is_file(fs_node_t *fsnode) 648 627 { 649 628 struct mfs_node *node = fsnode->data; … … 651 630 } 652 631 653 static int 654 mfs_root_get(fs_node_t **rfn, service_id_t service_id) 632 static int mfs_root_get(fs_node_t **rfn, service_id_t service_id) 655 633 { 656 634 int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO); … … 658 636 } 659 637 660 static int 661 mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 638 static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 662 639 { 663 640 struct mfs_node *parent = pfn->data; 664 641 struct mfs_node *child = cfn->data; 665 642 struct mfs_sb_info *sbi = parent->instance->sbi; 666 bool destroy_dentry = false;667 643 668 644 mfsdebug("%s()\n", __FUNCTION__); … … 673 649 int r = mfs_insert_dentry(parent, name, child->ino_i->index); 674 650 if (r != EOK) 675 returnr;651 goto exit_error; 676 652 677 653 if (S_ISDIR(child->ino_i->i_mode)) { 678 if (child->ino_i->i_nlinks != 1) {679 /* It's not possible to hardlink directories in MFS */680 destroy_dentry = true;681 r = EMLINK;682 goto exit;683 }684 654 r = mfs_insert_dentry(child, ".", child->ino_i->index); 685 if (r != EOK) { 686 destroy_dentry = true; 687 goto exit; 688 } 655 if (r != EOK) 656 goto exit_error; 689 657 690 658 r = mfs_insert_dentry(child, "..", parent->ino_i->index); 691 if (r != EOK) { 692 destroy_dentry = true; 693 goto exit; 694 } 659 if (r != EOK) 660 goto exit_error; 695 661 696 662 parent->ino_i->i_nlinks++; … … 698 664 } 699 665 700 exit: 701 if (destroy_dentry) { 702 int r2 = mfs_remove_dentry(parent, name); 703 if (r2 != EOK) 704 r = r2; 705 } else { 706 child->ino_i->i_nlinks++; 707 child->ino_i->dirty = true; 708 } 666 exit_error: 709 667 return r; 710 668 } … … 753 711 } 754 712 755 static int 756 mfs_has_children(bool *has_children, fs_node_t *fsnode) 713 static int mfs_has_children(bool *has_children, fs_node_t *fsnode) 757 714 { 758 715 struct mfs_node *mnode = fsnode->data; … … 775 732 776 733 if (d_info.d_inum) { 777 /* A valid entry has been found*/734 /*A valid entry has been found*/ 778 735 *has_children = true; 779 736 break; … … 787 744 static int 788 745 mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 789 746 size_t *rbytes) 790 747 { 791 748 int rc; … … 817 774 818 775 if (pos < 2) { 819 /* Skip the first two dentries ('.' and '..')*/776 /*Skip the first two dentries ('.' and '..')*/ 820 777 pos = 2; 821 778 } … … 827 784 828 785 if (d_info.d_inum) { 829 /* Dentry found!*/786 /*Dentry found!*/ 830 787 goto found; 831 788 } … … 837 794 found: 838 795 async_data_read_finalize(callid, d_info.d_name, 839 796 str_size(d_info.d_name) + 1); 840 797 bytes = ((pos - spos) + 1); 841 798 } else { … … 843 800 844 801 if (pos >= (size_t) ino_i->i_size) { 845 /* Trying to read beyond the end of file*/802 /*Trying to read beyond the end of file*/ 846 803 bytes = 0; 847 804 (void) async_data_read_finalize(callid, NULL, 0); … … 860 817 861 818 if (zone == 0) { 862 /* sparse file*/819 /*sparse file*/ 863 820 uint8_t *buf = malloc(sbi->block_size); 864 821 if (!buf) { … … 868 825 memset(buf, 0, sizeof(sbi->block_size)); 869 826 async_data_read_finalize(callid, 870 827 buf + pos % sbi->block_size, bytes); 871 828 free(buf); 872 829 goto out_success; … … 878 835 879 836 async_data_read_finalize(callid, b->data + 880 837 pos % sbi->block_size, bytes); 881 838 882 839 rc = block_put(b); … … 899 856 static int 900 857 mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 901 858 size_t *wbytes, aoff64_t *nsize) 902 859 { 903 860 fs_node_t *fn; … … 923 880 struct mfs_ino_info *ino_i = mnode->ino_i; 924 881 const size_t bs = sbi->block_size; 925 size_t bytes = min(len, bs - (pos % bs)); 882 size_t bytes = min(len, bs - pos % bs); 883 size_t boundary = ROUND_UP(ino_i->i_size, bs); 926 884 uint32_t block; 927 885 … … 929 887 flags = BLOCK_FLAGS_NOREAD; 930 888 931 r = mfs_read_map(&block, mnode, pos); 932 if (r != EOK) 933 goto out_err; 934 935 if (block == 0) { 889 if (pos < boundary) { 890 r = mfs_read_map(&block, mnode, pos); 891 if (r != EOK) 892 goto out_err; 893 894 if (block == 0) { 895 /*Writing in a sparse block*/ 896 r = mfs_alloc_zone(mnode->instance, &block); 897 if (r != EOK) 898 goto out_err; 899 flags = BLOCK_FLAGS_NOREAD; 900 } 901 } else { 936 902 uint32_t dummy; 937 903 … … 939 905 if (r != EOK) 940 906 goto out_err; 941 907 942 908 r = mfs_write_map(mnode, pos, block, &dummy); 943 909 if (r != EOK) 944 910 goto out_err; 945 946 flags = BLOCK_FLAGS_NOREAD;947 911 } 948 912 … … 952 916 goto out_err; 953 917 954 if (flags == BLOCK_FLAGS_NOREAD) 955 memset(b->data, 0, sbi->block_size); 956 957 async_data_write_finalize(callid, b->data + (pos % bs), bytes); 918 async_data_write_finalize(callid, b->data + pos % bs, bytes); 958 919 b->dirty = true; 959 920 … … 964 925 } 965 926 966 if (pos + bytes > ino_i->i_size) { 967 ino_i->i_size = pos + bytes; 968 ino_i->dirty = true; 969 } 927 ino_i->i_size = pos + bytes; 928 ino_i->dirty = true; 970 929 r = mfs_node_put(fn); 971 *nsize = ino_i->i_size;930 *nsize = pos + bytes; 972 931 *wbytes = bytes; 973 932 return r; … … 991 950 return ENOENT; 992 951 993 /* Destroy the inode*/952 /*Destroy the inode*/ 994 953 return mfs_destroy_node(fn); 995 954 } … … 1010 969 assert(!has_children); 1011 970 1012 /* Free the entire inode content*/971 /*Free the entire inode content*/ 1013 972 r = mfs_inode_shrink(mnode, mnode->ino_i->i_size); 1014 973 if (r != EOK) 1015 974 goto out; 1016 975 1017 /* Mark the inode as free in the bitmap*/976 /*Mark the inode as free in the bitmap*/ 1018 977 r = mfs_free_inode(mnode->instance, mnode->ino_i->index); 1019 978 … … 1054 1013 1055 1014 rc = fs_instance_get(service_id, &data); 1056 if (rc == EOK) 1015 if (rc == EOK) { 1057 1016 *instance = (struct mfs_instance *) data; 1058 else {1017 } else { 1059 1018 mfsdebug("instance not found\n"); 1060 1019 } … … 1063 1022 } 1064 1023 1065 static bool 1066 check_magic_number(uint16_t magic, bool *native, 1067 mfs_version_t *version, bool *longfilenames) 1024 static bool check_magic_number(uint16_t magic, bool *native, 1025 mfs_version_t *version, bool *longfilenames) 1068 1026 { 1069 1027 bool rc = true; … … 1093 1051 } 1094 1052 1095 /** Filesystem sanity check1096 *1097 * @param Pointer to the MFS superblock.1098 *1099 * @return EOK on success, ENOTSUP otherwise.1100 */1101 static int1102 mfs_check_sanity(struct mfs_sb_info *sbi)1103 {1104 if (!is_power_of_two(sbi->block_size) ||1105 sbi->block_size < MFS_MIN_BLOCKSIZE ||1106 sbi->block_size > MFS_MAX_BLOCKSIZE)1107 return ENOTSUP;1108 else if (sbi->ibmap_blocks == 0 || sbi->zbmap_blocks == 0)1109 return ENOTSUP;1110 else if (sbi->ninodes == 0 || sbi->nzones == 0)1111 return ENOTSUP;1112 else if (sbi->firstdatazone == 0)1113 return ENOTSUP;1114 1115 return EOK;1116 }1117 1118 1053 static int 1119 1054 mfs_close(service_id_t service_id, fs_index_t index) … … 1136 1071 1137 1072 return mfs_node_put(fn); 1138 }1139 1140 /** Check if a given number is a power of two.1141 *1142 * @param n The number to check.1143 *1144 * @return true if it is a power of two, false otherwise.1145 */1146 static bool1147 is_power_of_two(uint32_t n)1148 {1149 if (n == 0)1150 return false;1151 1152 return (n & (n - 1)) == 0;1153 1073 } 1154 1074
Note:
See TracChangeset
for help on using the changeset viewer.