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