Changes in uspace/srv/fs/mfs/mfs_ops.c [c2e50d7:7a46bfe] in mainline
- File:
-
- 1 edited
-
uspace/srv/fs/mfs/mfs_ops.c (modified) (53 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/mfs/mfs_ops.c
rc2e50d7 r7a46bfe 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); … … 54 55 static int mfs_has_children(bool *has_children, fs_node_t *fsnode); 55 56 static int mfs_root_get(fs_node_t **rfn, service_id_t service_id); 56 static service_id_t mfs_ service_get(fs_node_t *fsnode);57 static service_id_t mfs_device_get(fs_node_t *fsnode); 57 58 static aoff64_t mfs_size_get(fs_node_t *node); 58 59 static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component); … … 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 link_t *item);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); 73 70 fs_index_t index); 71 static int 72 mfs_instance_get(service_id_t service_id, struct mfs_instance **instance); 73 74 75 static LIST_INITIALIZE(inst_list); 76 static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex); 74 77 static hash_table_t open_nodes; 75 78 static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock); … … 78 81 .size_get = mfs_size_get, 79 82 .root_get = mfs_root_get, 80 . service_get = mfs_service_get,83 .device_get = mfs_device_get, 81 84 .is_directory = mfs_is_directory, 82 85 .is_file = mfs_is_file, … … 95 98 96 99 /* Hash table interface for open nodes hash table */ 97 static hash_index_t 98 open_nodes_hash(unsigned long key[]) 100 static hash_index_t open_nodes_hash(unsigned long key[]) 99 101 { 100 102 /* TODO: This is very simple and probably can be improved */ … … 102 104 } 103 105 104 static int 105 open_nodes_compare(unsigned long key[], hash_count_t keys, 106 link_t *item) 106 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 107 link_t *item) 107 108 { 108 109 struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link); … … 119 120 } 120 121 121 static void 122 open_nodes_remove_cb(link_t *link) 122 static void open_nodes_remove_cb(link_t *link) 123 123 { 124 124 /* We don't use remove callback for this hash table */ … … 131 131 }; 132 132 133 int 134 mfs_global_init(void) 133 int mfs_global_init(void) 135 134 { 136 135 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 137 OPEN_NODES_KEYS, &open_nodes_ops)) {136 OPEN_NODES_KEYS, &open_nodes_ops)) { 138 137 return ENOMEM; 139 138 } … … 143 142 static int 144 143 mfs_mounted(service_id_t service_id, const char *opts, fs_index_t *index, 145 aoff64_t *size, unsigned *linkcnt)144 aoff64_t *size, unsigned *linkcnt) 146 145 { 147 146 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;147 struct mfs_superblock *sb; 148 struct mfs3_superblock *sb3; 149 struct mfs_sb_info *sbi; 150 struct mfs_instance *instance; 152 151 bool native, longnames; 153 152 mfs_version_t version; … … 166 165 return rc; 167 166 168 /* Allocate space for generic MFS superblock*/167 /*Allocate space for generic MFS superblock*/ 169 168 sbi = malloc(sizeof(*sbi)); 170 169 if (!sbi) { 171 rc = ENOMEM;172 goto out_error;173 } 174 175 /* Allocate space for filesystem instance*/170 block_fini(service_id); 171 return ENOMEM; 172 } 173 174 /*Allocate space for filesystem instance*/ 176 175 instance = malloc(sizeof(*instance)); 177 176 if (!instance) { 178 rc = ENOMEM; 179 goto out_error; 180 } 177 free(sbi); 178 block_fini(service_id); 179 return ENOMEM; 180 } 181 182 instance->open_nodes_cnt = 0; 181 183 182 184 sb = malloc(MFS_SUPERBLOCK_SIZE); 183 185 if (!sb) { 184 rc = ENOMEM; 185 goto out_error; 186 free(instance); 187 free(sbi); 188 block_fini(service_id); 189 return ENOMEM; 186 190 } 187 191 188 192 /* Read the superblock */ 189 193 rc = block_read_direct(service_id, MFS_SUPERBLOCK << 1, 2, sb); 190 if (rc != EOK) 191 goto out_error; 194 if (rc != EOK) { 195 free(instance); 196 free(sbi); 197 free(sb); 198 block_fini(service_id); 199 return rc; 200 } 192 201 193 202 sb3 = (struct mfs3_superblock *) sb; 194 203 195 204 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) { 196 /* This is a V1 or V2 Minix filesystem*/205 /*This is a V1 or V2 Minix filesystem*/ 197 206 magic = sb->s_magic; 198 207 } else if (check_magic_number(sb3->s_magic, &native, &version, &longnames)) { 199 /* This is a V3 Minix filesystem*/208 /*This is a V3 Minix filesystem*/ 200 209 magic = sb3->s_magic; 201 210 } else { 202 /* Not recognized*/211 /*Not recognized*/ 203 212 mfsdebug("magic number not recognized\n"); 204 rc = ENOTSUP; 205 goto out_error; 213 free(instance); 214 free(sbi); 215 free(sb); 216 block_fini(service_id); 217 return ENOTSUP; 206 218 } 207 219 208 220 mfsdebug("magic number recognized = %04x\n", magic); 209 221 210 /* Fill superblock info structure*/222 /*Fill superblock info structure*/ 211 223 212 224 sbi->fs_version = version; … … 246 258 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE; 247 259 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 260 MFS_MAX_NAME_LEN; 261 } 263 262 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 } 263 264 free(sb); 268 265 269 266 rc = block_cache_init(service_id, sbi->block_size, 0, cmode); 270 267 if (rc != EOK) { 268 free(instance); 269 free(sbi); 270 free(sb); 271 block_cache_fini(service_id); 272 block_fini(service_id); 271 273 mfsdebug("block cache initialization failed\n"); 272 r c =EINVAL;273 goto out_error;274 } 275 276 /* Initialize the instance structure and remember it */274 return EINVAL; 275 } 276 277 /*Initialize the instance structure and add it to the list*/ 278 link_initialize(&instance->link); 277 279 instance->service_id = service_id; 278 280 instance->sbi = sbi; 279 instance->open_nodes_cnt = 0; 280 rc = fs_instance_create(service_id, instance); 281 if (rc != EOK) { 282 block_cache_fini(service_id); 283 mfsdebug("fs instance creation failed\n"); 284 goto out_error; 285 } 281 282 fibril_mutex_lock(&inst_list_mutex); 283 list_append(&instance->link, &inst_list); 284 fibril_mutex_unlock(&inst_list_mutex); 286 285 287 286 mfsdebug("mount successful\n"); … … 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 … … 328 315 block_fini(service_id); 329 316 330 /* Remove and destroy the instance */ 331 (void) fs_instance_destroy(service_id); 317 /* Remove the instance from the list */ 318 fibril_mutex_lock(&inst_list_mutex); 319 list_remove(&inst->link); 320 fibril_mutex_unlock(&inst_list_mutex); 321 332 322 free(inst->sbi); 333 323 free(inst); … … 335 325 } 336 326 337 service_id_t 338 mfs_service_get(fs_node_t *fsnode) 327 service_id_t mfs_device_get(fs_node_t *fsnode) 339 328 { 340 329 struct mfs_node *node = fsnode->data; … … 342 331 } 343 332 344 static int 345 mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 333 static int mfs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 346 334 { 347 335 int r; … … 357 345 return r; 358 346 359 /* Alloc a new inode*/347 /*Alloc a new inode*/ 360 348 r = mfs_alloc_inode(inst, &inum); 361 349 if (r != EOK) … … 384 372 if (flags & L_DIRECTORY) { 385 373 ino_i->i_mode = S_IFDIR; 386 ino_i->i_nlinks = 1; /* This accounts for the '.' dentry*/387 } else 374 ino_i->i_nlinks = 2; /*This accounts for the '.' dentry*/ 375 } else { 388 376 ino_i->i_mode = S_IFREG; 377 ino_i->i_nlinks = 1; 378 } 389 379 390 380 ino_i->i_uid = 0; … … 435 425 } 436 426 437 static int 438 mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 427 static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 439 428 { 440 429 struct mfs_node *mnode = pfn->data; … … 458 447 459 448 if (!d_info.d_inum) { 460 /* This entry is not used*/449 /*This entry is not used*/ 461 450 continue; 462 451 } … … 465 454 466 455 if (comp_size == dentry_name_size && 467 !bcmp(component, d_info.d_name, dentry_name_size)) {468 /* Hit!*/456 !bcmp(component, d_info.d_name, dentry_name_size)) { 457 /*Hit!*/ 469 458 mfs_node_core_get(rfn, mnode->instance, 470 d_info.d_inum);459 d_info.d_inum); 471 460 goto found; 472 461 } … … 477 466 } 478 467 479 static aoff64_t 480 mfs_size_get(fs_node_t *node) 481 { 468 static aoff64_t mfs_size_get(fs_node_t *node) 469 { 470 assert(node); 471 482 472 const struct mfs_node *mnode = node->data; 473 assert(mnode); 474 assert(mnode->ino_i); 475 483 476 return mnode->ino_i->i_size; 484 477 } … … 486 479 static int 487 480 mfs_node_get(fs_node_t **rfn, service_id_t service_id, 488 fs_index_t index)481 fs_index_t index) 489 482 { 490 483 int rc; … … 520 513 assert(mnode->instance->open_nodes_cnt > 0); 521 514 mnode->instance->open_nodes_cnt--; 522 rc = mfs_put_inode (mnode);515 rc = mfs_put_inode_core(mnode); 523 516 free(mnode->ino_i); 524 517 free(mnode); … … 530 523 } 531 524 532 static int 533 mfs_node_open(fs_node_t *fsnode) 525 static int mfs_node_open(fs_node_t *fsnode) 534 526 { 535 527 /* … … 540 532 } 541 533 542 static fs_index_t 543 mfs_index_get(fs_node_t *fsnode) 534 static fs_index_t mfs_index_get(fs_node_t *fsnode) 544 535 { 545 536 struct mfs_node *mnode = fsnode->data; 537 538 assert(mnode->ino_i); 546 539 return mnode->ino_i->index; 547 540 } 548 541 549 static unsigned 550 mfs_lnkcnt_get(fs_node_t *fsnode) 542 static unsigned mfs_lnkcnt_get(fs_node_t *fsnode) 551 543 { 552 544 struct mfs_node *mnode = fsnode->data; … … 563 555 } 564 556 565 static int 566 mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst, 567 fs_index_t index) 557 static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst, 558 fs_index_t index) 568 559 { 569 560 fs_node_t *node = NULL; … … 637 628 } 638 629 639 static bool 640 mfs_is_directory(fs_node_t *fsnode) 630 static bool mfs_is_directory(fs_node_t *fsnode) 641 631 { 642 632 const struct mfs_node *node = fsnode->data; … … 644 634 } 645 635 646 static bool 647 mfs_is_file(fs_node_t *fsnode) 636 static bool mfs_is_file(fs_node_t *fsnode) 648 637 { 649 638 struct mfs_node *node = fsnode->data; … … 651 640 } 652 641 653 static int 654 mfs_root_get(fs_node_t **rfn, service_id_t service_id) 642 static int mfs_root_get(fs_node_t **rfn, service_id_t service_id) 655 643 { 656 644 int rc = mfs_node_get(rfn, service_id, MFS_ROOT_INO); … … 658 646 } 659 647 660 static int 661 mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 648 static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 662 649 { 663 650 struct mfs_node *parent = pfn->data; 664 651 struct mfs_node *child = cfn->data; 665 652 struct mfs_sb_info *sbi = parent->instance->sbi; 666 bool destroy_dentry = false;667 653 668 654 mfsdebug("%s()\n", __FUNCTION__); … … 673 659 int r = mfs_insert_dentry(parent, name, child->ino_i->index); 674 660 if (r != EOK) 675 returnr;661 goto exit_error; 676 662 677 663 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 664 r = mfs_insert_dentry(child, ".", child->ino_i->index); 685 if (r != EOK) { 686 destroy_dentry = true; 687 goto exit; 688 } 665 if (r != EOK) 666 goto exit_error; 689 667 690 668 r = mfs_insert_dentry(child, "..", parent->ino_i->index); 691 if (r != EOK) { 692 destroy_dentry = true; 693 goto exit; 694 } 669 if (r != EOK) 670 goto exit_error; 695 671 696 672 parent->ino_i->i_nlinks++; … … 698 674 } 699 675 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 } 676 exit_error: 709 677 return r; 710 678 } … … 753 721 } 754 722 755 static int 756 mfs_has_children(bool *has_children, fs_node_t *fsnode) 723 static int mfs_has_children(bool *has_children, fs_node_t *fsnode) 757 724 { 758 725 struct mfs_node *mnode = fsnode->data; … … 775 742 776 743 if (d_info.d_inum) { 777 /* A valid entry has been found*/744 /*A valid entry has been found*/ 778 745 *has_children = true; 779 746 break; … … 787 754 static int 788 755 mfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 789 size_t *rbytes)756 size_t *rbytes) 790 757 { 791 758 int rc; … … 817 784 818 785 if (pos < 2) { 819 /* Skip the first two dentries ('.' and '..')*/786 /*Skip the first two dentries ('.' and '..')*/ 820 787 pos = 2; 821 788 } … … 827 794 828 795 if (d_info.d_inum) { 829 /* Dentry found!*/796 /*Dentry found!*/ 830 797 goto found; 831 798 } … … 837 804 found: 838 805 async_data_read_finalize(callid, d_info.d_name, 839 str_size(d_info.d_name) + 1);806 str_size(d_info.d_name) + 1); 840 807 bytes = ((pos - spos) + 1); 841 808 } else { … … 843 810 844 811 if (pos >= (size_t) ino_i->i_size) { 845 /* Trying to read beyond the end of file*/812 /*Trying to read beyond the end of file*/ 846 813 bytes = 0; 847 814 (void) async_data_read_finalize(callid, NULL, 0); … … 860 827 861 828 if (zone == 0) { 862 /* sparse file*/829 /*sparse file*/ 863 830 uint8_t *buf = malloc(sbi->block_size); 864 831 if (!buf) { … … 868 835 memset(buf, 0, sizeof(sbi->block_size)); 869 836 async_data_read_finalize(callid, 870 buf + pos % sbi->block_size, bytes);837 buf + pos % sbi->block_size, bytes); 871 838 free(buf); 872 839 goto out_success; … … 878 845 879 846 async_data_read_finalize(callid, b->data + 880 pos % sbi->block_size, bytes);847 pos % sbi->block_size, bytes); 881 848 882 849 rc = block_put(b); … … 899 866 static int 900 867 mfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 901 size_t *wbytes, aoff64_t *nsize)868 size_t *wbytes, aoff64_t *nsize) 902 869 { 903 870 fs_node_t *fn; … … 923 890 struct mfs_ino_info *ino_i = mnode->ino_i; 924 891 const size_t bs = sbi->block_size; 925 size_t bytes = min(len, bs - (pos % bs)); 892 size_t bytes = min(len, bs - pos % bs); 893 size_t boundary = ROUND_UP(ino_i->i_size, bs); 926 894 uint32_t block; 927 895 … … 929 897 flags = BLOCK_FLAGS_NOREAD; 930 898 931 r = mfs_read_map(&block, mnode, pos); 932 if (r != EOK) 933 goto out_err; 934 935 if (block == 0) { 899 if (pos < boundary) { 900 r = mfs_read_map(&block, mnode, pos); 901 if (r != EOK) 902 goto out_err; 903 904 if (block == 0) { 905 /*Writing in a sparse block*/ 906 r = mfs_alloc_zone(mnode->instance, &block); 907 if (r != EOK) 908 goto out_err; 909 flags = BLOCK_FLAGS_NOREAD; 910 } 911 } else { 936 912 uint32_t dummy; 937 913 … … 939 915 if (r != EOK) 940 916 goto out_err; 941 917 942 918 r = mfs_write_map(mnode, pos, block, &dummy); 943 919 if (r != EOK) 944 920 goto out_err; 945 946 flags = BLOCK_FLAGS_NOREAD;947 921 } 948 922 … … 952 926 goto out_err; 953 927 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); 928 async_data_write_finalize(callid, b->data + pos % bs, bytes); 958 929 b->dirty = true; 959 930 … … 964 935 } 965 936 966 if (pos + bytes > ino_i->i_size) { 967 ino_i->i_size = pos + bytes; 968 ino_i->dirty = true; 969 } 937 ino_i->i_size = pos + bytes; 938 ino_i->dirty = true; 970 939 r = mfs_node_put(fn); 971 *nsize = ino_i->i_size;940 *nsize = pos + bytes; 972 941 *wbytes = bytes; 973 942 return r; … … 991 960 return ENOENT; 992 961 993 /* Destroy the inode*/962 /*Destroy the inode*/ 994 963 return mfs_destroy_node(fn); 995 964 } … … 1010 979 assert(!has_children); 1011 980 1012 /* Free the entire inode content*/981 /*Free the entire inode content*/ 1013 982 r = mfs_inode_shrink(mnode, mnode->ino_i->i_size); 1014 983 if (r != EOK) 1015 984 goto out; 1016 985 1017 /* Mark the inode as free in the bitmap*/986 /*Mark the inode as free in the bitmap*/ 1018 987 r = mfs_free_inode(mnode->instance, mnode->ino_i->index); 1019 988 … … 1050 1019 mfs_instance_get(service_id_t service_id, struct mfs_instance **instance) 1051 1020 { 1052 void *data; 1053 int rc; 1054 1055 rc = fs_instance_get(service_id, &data); 1056 if (rc == EOK) 1057 *instance = (struct mfs_instance *) data; 1058 else { 1059 mfsdebug("instance not found\n"); 1060 } 1061 1062 return rc; 1063 } 1064 1065 static bool 1066 check_magic_number(uint16_t magic, bool *native, 1067 mfs_version_t *version, bool *longfilenames) 1021 struct mfs_instance *instance_ptr; 1022 1023 fibril_mutex_lock(&inst_list_mutex); 1024 1025 if (list_empty(&inst_list)) { 1026 fibril_mutex_unlock(&inst_list_mutex); 1027 return EINVAL; 1028 } 1029 1030 list_foreach(inst_list, link) { 1031 instance_ptr = list_get_instance(link, struct mfs_instance, 1032 link); 1033 1034 if (instance_ptr->service_id == service_id) { 1035 *instance = instance_ptr; 1036 fibril_mutex_unlock(&inst_list_mutex); 1037 return EOK; 1038 } 1039 } 1040 1041 mfsdebug("Instance not found\n"); 1042 1043 fibril_mutex_unlock(&inst_list_mutex); 1044 return EINVAL; 1045 } 1046 1047 static bool check_magic_number(uint16_t magic, bool *native, 1048 mfs_version_t *version, bool *longfilenames) 1068 1049 { 1069 1050 bool rc = true; … … 1093 1074 } 1094 1075 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 1076 static int 1119 1077 mfs_close(service_id_t service_id, fs_index_t index) … … 1136 1094 1137 1095 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 1096 } 1154 1097
Note:
See TracChangeset
for help on using the changeset viewer.
