Changes in uspace/srv/fs/fat/fat_ops.c [efcebe1:5a9a1aaf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
refcebe1 r5a9a1aaf 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 39 40 #include "fat_dentry.h" 40 41 #include "fat_fat.h" 42 #include "fat_directory.h" 41 43 #include "../../vfs/vfs.h" 42 44 #include <libfs.h> … … 56 58 #include <align.h> 57 59 #include <malloc.h> 60 #include <str.h> 58 61 59 62 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 67 70 68 71 /** List of cached free FAT nodes. */ 69 static LIST_INITIALIZE(ffn_ list);72 static LIST_INITIALIZE(ffn_head); 70 73 71 74 /* … … 85 88 static aoff64_t fat_size_get(fs_node_t *); 86 89 static unsigned fat_lnkcnt_get(fs_node_t *); 90 static char fat_plb_get_char(unsigned); 87 91 static bool fat_is_directory(fs_node_t *); 88 92 static bool fat_is_file(fs_node_t *node); … … 104 108 node->dirty = false; 105 109 node->lastc_cached_valid = false; 106 node->lastc_cached_value = FAT_CLST_LAST1;110 node->lastc_cached_value = 0; 107 111 node->currc_cached_valid = false; 108 112 node->currc_cached_bn = 0; 109 node->currc_cached_value = FAT_CLST_LAST1;113 node->currc_cached_value = 0; 110 114 } 111 115 … … 116 120 fat_dentry_t *d; 117 121 int rc; 118 122 119 123 assert(node->dirty); 120 124 121 125 bs = block_bb_get(node->idx->devmap_handle); 122 126 123 127 /* Read the block that contains the dentry of interest. */ 124 128 rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc, … … 136 140 d->attr = FAT_ATTR_SUBDIR; 137 141 } 138 142 139 143 /* TODO: update other fields? (e.g time fields) */ 140 144 141 145 b->dirty = true; /* need to sync block */ 142 146 rc = block_put(b); … … 146 150 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle) 147 151 { 152 link_t *lnk; 148 153 fat_node_t *nodep; 149 154 int rc; … … 157 162 restart: 158 163 fibril_mutex_lock(&ffn_mutex); 159 list_foreach(ffn_list, lnk) {164 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) { 160 165 nodep = list_get_instance(lnk, fat_node_t, ffn_link); 161 166 if (!fibril_mutex_trylock(&nodep->lock)) { … … 194 199 free(nodep); 195 200 196 /* Need to restart because we changed ffn_list. */201 /* Need to restart because we changed the ffn_head list. */ 197 202 goto restart; 198 203 } … … 209 214 210 215 fibril_mutex_lock(&ffn_mutex); 211 if (!list_empty(&ffn_ list)) {216 if (!list_empty(&ffn_head)) { 212 217 /* Try to use a cached free node structure. */ 213 218 fat_idx_t *idxp_tmp; 214 nodep = list_get_instance(list_first(&ffn_list), fat_node_t, 215 ffn_link); 219 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); 216 220 if (!fibril_mutex_trylock(&nodep->lock)) 217 221 goto skip_cache; … … 255 259 fn->data = nodep; 256 260 nodep->bp = fn; 257 261 258 262 *nodepp = nodep; 259 263 return EOK; … … 291 295 * We must instantiate the node from the file system. 292 296 */ 293 297 294 298 assert(idxp->pfc); 295 299 … … 309 313 310 314 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs)); 315 if (FAT_IS_FAT32(bs)) { 316 nodep->firstc = uint16_t_le2host(d->firstc_lo) | 317 (uint16_t_le2host(d->firstc_hi) << 16); 318 } 319 else 320 nodep->firstc = uint16_t_le2host(d->firstc); 321 311 322 if (d->attr & FAT_ATTR_SUBDIR) { 312 /* 323 /* 313 324 * The only directory which does not have this bit set is the 314 325 * root directory itself. The root directory node is handled … … 316 327 */ 317 328 nodep->type = FAT_DIRECTORY; 329 318 330 /* 319 331 * Unfortunately, the 'size' field of the FAT dentry is not … … 321 333 * size of the directory by walking the FAT. 322 334 */ 323 uint16_t clusters; 324 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, 325 uint16_t_le2host(d->firstc)); 335 uint32_t clusters; 336 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, nodep->firstc); 326 337 if (rc != EOK) { 327 338 (void) block_put(b); … … 334 345 nodep->size = uint32_t_le2host(d->size); 335 346 } 336 nodep->firstc = uint16_t_le2host(d->firstc); 347 337 348 nodep->lnkcnt = 1; 338 349 nodep->refcnt = 1; … … 363 374 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 364 375 { 365 fat_bs_t *bs;366 376 fat_node_t *parentp = FAT_NODE(pfn); 367 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 368 unsigned i, j; 369 unsigned blocks; 377 char name[FAT_LFN_NAME_SIZE]; 370 378 fat_dentry_t *d; 371 379 devmap_handle_t devmap_handle; 372 block_t *b;373 380 int rc; 374 381 … … 376 383 devmap_handle = parentp->idx->devmap_handle; 377 384 fibril_mutex_unlock(&parentp->idx->lock); 378 379 bs = block_bb_get(devmap_handle); 380 blocks = parentp->size / BPS(bs); 381 for (i = 0; i < blocks; i++) { 382 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 383 if (rc != EOK) 384 return rc; 385 for (j = 0; j < DPS(bs); j++) { 386 d = ((fat_dentry_t *)b->data) + j; 387 switch (fat_classify_dentry(d)) { 388 case FAT_DENTRY_SKIP: 389 case FAT_DENTRY_FREE: 390 continue; 391 case FAT_DENTRY_LAST: 392 /* miss */ 393 rc = block_put(b); 394 *rfn = NULL; 395 return rc; 396 default: 397 case FAT_DENTRY_VALID: 398 fat_dentry_name_get(d, name); 399 break; 385 386 fat_directory_t di; 387 rc = fat_directory_open(parentp, &di); 388 if (rc != EOK) 389 return rc; 390 391 while (fat_directory_read(&di, name, &d) == EOK) { 392 if (fat_dentry_namecmp(name, component) == 0) { 393 /* hit */ 394 fat_node_t *nodep; 395 aoff64_t o = di.pos % (BPS(di.bs) / sizeof(fat_dentry_t)); 396 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle, 397 parentp->firstc, di.bnum * DPS(di.bs) + o); 398 if (!idx) { 399 /* 400 * Can happen if memory is low or if we 401 * run out of 32-bit indices. 402 */ 403 rc = fat_directory_close(&di); 404 return (rc == EOK) ? ENOMEM : rc; 400 405 } 401 if (fat_dentry_namecmp(name, component) == 0) { 402 /* hit */ 403 fat_node_t *nodep; 404 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle, 405 parentp->firstc, i * DPS(bs) + j); 406 if (!idx) { 407 /* 408 * Can happen if memory is low or if we 409 * run out of 32-bit indices. 410 */ 411 rc = block_put(b); 412 return (rc == EOK) ? ENOMEM : rc; 413 } 414 rc = fat_node_get_core(&nodep, idx); 415 fibril_mutex_unlock(&idx->lock); 416 if (rc != EOK) { 417 (void) block_put(b); 418 return rc; 419 } 420 *rfn = FS_NODE(nodep); 421 rc = block_put(b); 422 if (rc != EOK) 423 (void) fat_node_put(*rfn); 406 rc = fat_node_get_core(&nodep, idx); 407 fibril_mutex_unlock(&idx->lock); 408 if (rc != EOK) { 409 (void) fat_directory_close(&di); 424 410 return rc; 425 411 } 426 } 427 rc = block_put(b); 428 if (rc != EOK) 412 *rfn = FS_NODE(nodep); 413 rc = fat_directory_close(&di); 414 if (rc != EOK) 415 (void) fat_node_put(*rfn); 429 416 return rc; 430 } 431 417 } else { 418 rc = fat_directory_next(&di); 419 if (rc != EOK) 420 break; 421 } 422 } 423 (void) fat_directory_close(&di); 432 424 *rfn = NULL; 433 425 return EOK; … … 472 464 if (nodep->idx) { 473 465 fibril_mutex_lock(&ffn_mutex); 474 list_append(&nodep->ffn_link, &ffn_ list);466 list_append(&nodep->ffn_link, &ffn_head); 475 467 fibril_mutex_unlock(&ffn_mutex); 476 468 } else { … … 521 513 rc = fat_idx_get_new(&idxp, devmap_handle); 522 514 if (rc != EOK) { 523 (void) fat_free_clusters(bs, devmap_handle, mcl); 515 (void) fat_free_clusters(bs, devmap_handle, mcl); 524 516 (void) fat_node_put(FS_NODE(nodep)); 525 517 return rc; … … 591 583 fat_bs_t *bs; 592 584 block_t *b; 593 unsigned i, j; 594 unsigned blocks; 595 fat_cluster_t mcl, lcl; 585 fat_directory_t di; 586 fat_dentry_t de; 596 587 int rc; 597 588 … … 607 598 fibril_mutex_unlock(&childp->lock); 608 599 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 600 if (!fat_valid_name(name)) 613 601 return ENOTSUP; 614 } 615 616 /* 617 * Get us an unused parent node's dentry or grow the parent and allocate 618 * a new one. 619 */ 620 602 621 603 fibril_mutex_lock(&parentp->idx->lock); 622 604 bs = block_bb_get(parentp->idx->devmap_handle); 623 624 blocks = parentp->size / BPS(bs); 625 626 for (i = 0; i < blocks; i++) { 627 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 628 if (rc != EOK) { 629 fibril_mutex_unlock(&parentp->idx->lock); 630 return rc; 631 } 632 for (j = 0; j < DPS(bs); j++) { 633 d = ((fat_dentry_t *)b->data) + j; 634 switch (fat_classify_dentry(d)) { 635 case FAT_DENTRY_SKIP: 636 case FAT_DENTRY_VALID: 637 /* skipping used and meta entries */ 638 continue; 639 case FAT_DENTRY_FREE: 640 case FAT_DENTRY_LAST: 641 /* found an empty slot */ 642 goto hit; 643 } 644 } 645 rc = block_put(b); 646 if (rc != EOK) { 647 fibril_mutex_unlock(&parentp->idx->lock); 648 return rc; 649 } 650 } 651 j = 0; 652 653 /* 654 * We need to grow the parent in order to create a new unused dentry. 655 */ 656 if (parentp->firstc == FAT_CLST_ROOT) { 657 /* Can't grow the root directory. */ 658 fibril_mutex_unlock(&parentp->idx->lock); 659 return ENOSPC; 660 } 661 rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl); 662 if (rc != EOK) { 663 fibril_mutex_unlock(&parentp->idx->lock); 605 rc = fat_directory_open(parentp, &di); 606 if (rc != EOK) 664 607 return rc; 665 } 666 rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl); 667 if (rc != EOK) { 668 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 669 fibril_mutex_unlock(&parentp->idx->lock); 670 return rc; 671 } 672 rc = fat_append_clusters(bs, parentp, mcl, lcl); 673 if (rc != EOK) { 674 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 675 fibril_mutex_unlock(&parentp->idx->lock); 676 return rc; 677 } 678 parentp->size += BPS(bs) * SPC(bs); 679 parentp->dirty = true; /* need to sync node */ 680 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 681 if (rc != EOK) { 682 fibril_mutex_unlock(&parentp->idx->lock); 683 return rc; 684 } 685 d = (fat_dentry_t *)b->data; 686 687 hit: 608 688 609 /* 689 610 * At this point we only establish the link between the parent and the … … 692 613 * dentry data is kept in the child node structure. 693 614 */ 694 memset(d, 0, sizeof(fat_dentry_t)); 695 fat_dentry_name_set(d, name); 696 b->dirty = true; /* need to sync block */ 697 rc = block_put(b); 615 memset(&de, 0, sizeof(fat_dentry_t)); 616 617 rc = fat_directory_write(&di, name, &de); 618 if (rc!=EOK) 619 return rc; 620 rc = fat_directory_close(&di); 621 if (rc!=EOK) 622 return rc; 623 698 624 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK) 625 if (rc != EOK) 700 626 return rc; 701 627 702 628 fibril_mutex_lock(&childp->idx->lock); 703 629 704 630 if (childp->type == FAT_DIRECTORY) { 705 631 /* … … 720 646 d = (fat_dentry_t *) b->data; 721 647 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 722 ( str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {648 (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) { 723 649 memset(d, 0, sizeof(fat_dentry_t)); 724 650 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 730 656 d++; 731 657 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 732 ( str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {658 (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) { 733 659 memset(d, 0, sizeof(fat_dentry_t)); 734 660 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 735 661 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 736 662 d->attr = FAT_ATTR_SUBDIR; 737 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?738 host2uint16_t_le(FAT_CLST_R ES0) :663 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 664 host2uint16_t_le(FAT_CLST_ROOTPAR) : 739 665 host2uint16_t_le(parentp->firstc); 740 666 /* TODO: initialize also the date/time members. */ … … 750 676 751 677 childp->idx->pfc = parentp->firstc; 752 childp->idx->pdi = i * DPS(bs) + j;678 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */ 753 679 fibril_mutex_unlock(&childp->idx->lock); 754 680 … … 770 696 fat_node_t *parentp = FAT_NODE(pfn); 771 697 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs;773 fat_dentry_t *d;774 block_t *b;775 698 bool has_children; 776 699 int rc; … … 778 701 if (!parentp) 779 702 return EBUSY; 780 703 781 704 rc = fat_has_children(&has_children, cfn); 782 705 if (rc != EOK) … … 789 712 assert(childp->lnkcnt == 1); 790 713 fibril_mutex_lock(&childp->idx->lock); 791 bs = block_bb_get(childp->idx->devmap_handle); 792 793 rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc, 794 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 795 BLOCK_FLAGS_NONE); 796 if (rc != EOK) 714 715 fat_directory_t di; 716 rc = fat_directory_open(parentp,&di); 717 if (rc != EOK) 797 718 goto error; 798 d = (fat_dentry_t *)b->data + 799 (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t))); 800 /* mark the dentry as not-currently-used */ 801 d->name[0] = FAT_DENTRY_ERASED; 802 b->dirty = true; /* need to sync block */ 803 rc = block_put(b); 719 rc = fat_directory_seek(&di, childp->idx->pdi); 720 if (rc != EOK) 721 goto error; 722 rc = fat_directory_erase(&di); 723 if (rc != EOK) 724 goto error; 725 rc = fat_directory_close(&di); 804 726 if (rc != EOK) 805 727 goto error; … … 820 742 821 743 error: 822 fibril_mutex_unlock(&parentp->idx->lock); 744 (void) fat_directory_close(&di); 745 fibril_mutex_unlock(&childp->idx->lock); 823 746 fibril_mutex_unlock(&childp->lock); 824 fibril_mutex_unlock(& childp->idx->lock);747 fibril_mutex_unlock(&parentp->lock); 825 748 return rc; 826 749 } … … 839 762 return EOK; 840 763 } 841 764 842 765 fibril_mutex_lock(&nodep->idx->lock); 843 766 bs = block_bb_get(nodep->idx->devmap_handle); … … 847 770 for (i = 0; i < blocks; i++) { 848 771 fat_dentry_t *d; 849 772 850 773 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 851 774 if (rc != EOK) { … … 875 798 if (rc != EOK) { 876 799 fibril_mutex_unlock(&nodep->idx->lock); 877 return rc; 800 return rc; 878 801 } 879 802 } … … 898 821 { 899 822 return FAT_NODE(fn)->lnkcnt; 823 } 824 825 char fat_plb_get_char(unsigned pos) 826 { 827 return fat_reg.plb_ro[pos % PLB_SIZE]; 900 828 } 901 829 … … 930 858 .size_get = fat_size_get, 931 859 .lnkcnt_get = fat_lnkcnt_get, 860 .plb_get_char = fat_plb_get_char, 932 861 .is_directory = fat_is_directory, 933 862 .is_file = fat_is_file, … … 936 865 937 866 /* 938 * FAT VFS_OUToperations.867 * VFS operations. 939 868 */ 940 869 941 static int 942 fat_mounted(devmap_handle_t devmap_handle, const char *opts, fs_index_t *index, 943 aoff64_t *size, unsigned *linkcnt) 944 { 870 void fat_mounted(ipc_callid_t rid, ipc_call_t *request) 871 { 872 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 945 873 enum cache_mode cmode; 946 874 fat_bs_t *bs; 947 int rc; 948 875 876 /* Accept the mount options */ 877 char *opts; 878 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 879 880 if (rc != EOK) { 881 async_answer_0(rid, rc); 882 return; 883 } 884 949 885 /* Check for option enabling write through. */ 950 886 if (str_cmp(opts, "wtcache") == 0) … … 953 889 cmode = CACHE_MODE_WB; 954 890 891 free(opts); 892 955 893 /* initialize libblock */ 956 rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE); 957 if (rc != EOK) 958 return rc; 894 rc = block_init(devmap_handle, BS_SIZE); 895 if (rc != EOK) { 896 async_answer_0(rid, rc); 897 return; 898 } 959 899 960 900 /* prepare the boot block */ … … 962 902 if (rc != EOK) { 963 903 block_fini(devmap_handle); 964 return rc; 904 async_answer_0(rid, rc); 905 return; 965 906 } 966 907 967 908 /* get the buffer with the boot sector */ 968 909 bs = block_bb_get(devmap_handle); 969 910 970 911 if (BPS(bs) != BS_SIZE) { 971 912 block_fini(devmap_handle); 972 return ENOTSUP; 913 async_answer_0(rid, ENOTSUP); 914 return; 973 915 } 974 916 … … 977 919 if (rc != EOK) { 978 920 block_fini(devmap_handle); 979 return rc; 921 async_answer_0(rid, rc); 922 return; 980 923 } 981 924 … … 985 928 (void) block_cache_fini(devmap_handle); 986 929 block_fini(devmap_handle); 987 return rc; 930 async_answer_0(rid, rc); 931 return; 988 932 } 989 933 … … 992 936 (void) block_cache_fini(devmap_handle); 993 937 block_fini(devmap_handle); 994 return rc; 938 async_answer_0(rid, rc); 939 return; 995 940 } 996 941 … … 1001 946 block_fini(devmap_handle); 1002 947 fat_idx_fini_by_devmap_handle(devmap_handle); 1003 return ENOMEM; 1004 } 948 async_answer_0(rid, ENOMEM); 949 return; 950 } 951 1005 952 fs_node_initialize(rfn); 1006 953 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); … … 1010 957 block_fini(devmap_handle); 1011 958 fat_idx_fini_by_devmap_handle(devmap_handle); 1012 return ENOMEM; 959 async_answer_0(rid, ENOMEM); 960 return; 1013 961 } 1014 962 fat_node_initialize(rootp); … … 1021 969 block_fini(devmap_handle); 1022 970 fat_idx_fini_by_devmap_handle(devmap_handle); 1023 return ENOMEM; 971 async_answer_0(rid, ENOMEM); 972 return; 1024 973 } 1025 974 assert(ridxp->index == 0); … … 1027 976 1028 977 rootp->type = FAT_DIRECTORY; 1029 rootp->firstc = FAT_ CLST_ROOT;978 rootp->firstc = FAT_ROOT_CLST(bs); 1030 979 rootp->refcnt = 1; 1031 980 rootp->lnkcnt = 0; /* FS root is not linked */ 1032 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 981 982 if (FAT_IS_FAT32(bs)) { 983 uint32_t clusters; 984 rc = fat_clusters_get(&clusters, bs, devmap_handle, rootp->firstc); 985 if (rc != EOK) { 986 free(rfn); 987 free(rootp); 988 free(ridxp); /* TODO: Is it right way to free ridxp? */ 989 (void) block_cache_fini(devmap_handle); 990 block_fini(devmap_handle); 991 fat_idx_fini_by_devmap_handle(devmap_handle); 992 async_answer_0(rid, ENOTSUP); 993 return; 994 } 995 rootp->size = BPS(bs) * SPC(bs) * clusters; 996 } else 997 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 998 1033 999 rootp->idx = ridxp; 1034 1000 ridxp->nodep = rootp; 1035 1001 rootp->bp = rfn; 1036 1002 rfn->data = rootp; 1037 1003 1038 1004 fibril_mutex_unlock(&ridxp->lock); 1039 1005 1040 *index = ridxp->index; 1041 *size = rootp->size; 1042 *linkcnt = rootp->lnkcnt; 1043 1044 return EOK; 1045 } 1046 1047 static int fat_unmounted(devmap_handle_t devmap_handle) 1048 { 1006 async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); 1007 } 1008 1009 void fat_mount(ipc_callid_t rid, ipc_call_t *request) 1010 { 1011 libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1012 } 1013 1014 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request) 1015 { 1016 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1049 1017 fs_node_t *fn; 1050 1018 fat_node_t *nodep; … … 1052 1020 1053 1021 rc = fat_root_get(&fn, devmap_handle); 1054 if (rc != EOK) 1055 return rc; 1022 if (rc != EOK) { 1023 async_answer_0(rid, rc); 1024 return; 1025 } 1056 1026 nodep = FAT_NODE(fn); 1057 1027 … … 1062 1032 if (nodep->refcnt != 2) { 1063 1033 (void) fat_node_put(fn); 1064 return EBUSY; 1065 } 1066 1034 async_answer_0(rid, EBUSY); 1035 return; 1036 } 1037 1067 1038 /* 1068 1039 * Put the root node and force it to the FAT free node list. … … 1081 1052 block_fini(devmap_handle); 1082 1053 1083 return EOK; 1084 } 1085 1086 static int 1087 fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos, 1088 size_t *rbytes) 1089 { 1054 async_answer_0(rid, EOK); 1055 } 1056 1057 void fat_unmount(ipc_callid_t rid, ipc_call_t *request) 1058 { 1059 libfs_unmount(&fat_libfs_ops, rid, request); 1060 } 1061 1062 void fat_lookup(ipc_callid_t rid, ipc_call_t *request) 1063 { 1064 libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1065 } 1066 1067 void fat_read(ipc_callid_t rid, ipc_call_t *request) 1068 { 1069 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1070 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1071 aoff64_t pos = 1072 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1090 1073 fs_node_t *fn; 1091 1074 fat_node_t *nodep; … … 1096 1079 1097 1080 rc = fat_node_get(&fn, devmap_handle, index); 1098 if (rc != EOK) 1099 return rc; 1100 if (!fn) 1101 return ENOENT; 1081 if (rc != EOK) { 1082 async_answer_0(rid, rc); 1083 return; 1084 } 1085 if (!fn) { 1086 async_answer_0(rid, ENOENT); 1087 return; 1088 } 1102 1089 nodep = FAT_NODE(fn); 1103 1090 … … 1107 1094 fat_node_put(fn); 1108 1095 async_answer_0(callid, EINVAL); 1109 return EINVAL; 1096 async_answer_0(rid, EINVAL); 1097 return; 1110 1098 } 1111 1099 … … 1130 1118 fat_node_put(fn); 1131 1119 async_answer_0(callid, rc); 1132 return rc; 1120 async_answer_0(rid, rc); 1121 return; 1133 1122 } 1134 1123 (void) async_data_read_finalize(callid, … … 1137 1126 if (rc != EOK) { 1138 1127 fat_node_put(fn); 1139 return rc; 1128 async_answer_0(rid, rc); 1129 return; 1140 1130 } 1141 1131 } 1142 1132 } else { 1143 unsigned bnum;1144 1133 aoff64_t spos = pos; 1145 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1134 char name[FAT_LFN_NAME_SIZE]; 1146 1135 fat_dentry_t *d; 1147 1136 … … 1150 1139 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1151 1140 1152 /* 1153 * Our strategy for readdir() is to use the position pointer as 1154 * an index into the array of all dentries. On entry, it points 1155 * to the first unread dentry. If we skip any dentries, we bump 1156 * the position pointer accordingly. 1157 */ 1158 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs); 1159 while (bnum < nodep->size / BPS(bs)) { 1160 aoff64_t o; 1161 1162 rc = fat_block_get(&b, bs, nodep, bnum, 1163 BLOCK_FLAGS_NONE); 1164 if (rc != EOK) 1165 goto err; 1166 for (o = pos % (BPS(bs) / sizeof(fat_dentry_t)); 1167 o < BPS(bs) / sizeof(fat_dentry_t); 1168 o++, pos++) { 1169 d = ((fat_dentry_t *)b->data) + o; 1170 switch (fat_classify_dentry(d)) { 1171 case FAT_DENTRY_SKIP: 1172 case FAT_DENTRY_FREE: 1173 continue; 1174 case FAT_DENTRY_LAST: 1175 rc = block_put(b); 1176 if (rc != EOK) 1177 goto err; 1178 goto miss; 1179 default: 1180 case FAT_DENTRY_VALID: 1181 fat_dentry_name_get(d, name); 1182 rc = block_put(b); 1183 if (rc != EOK) 1184 goto err; 1185 goto hit; 1186 } 1187 } 1188 rc = block_put(b); 1189 if (rc != EOK) 1190 goto err; 1191 bnum++; 1192 } 1193 miss: 1194 rc = fat_node_put(fn); 1195 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1196 *rbytes = 0; 1197 return rc != EOK ? rc : ENOENT; 1141 fat_directory_t di; 1142 rc = fat_directory_open(nodep, &di); 1143 if (rc != EOK) goto err; 1144 rc = fat_directory_seek(&di, pos); 1145 if (rc != EOK) { 1146 (void) fat_directory_close(&di); 1147 goto err; 1148 } 1149 1150 rc = fat_directory_read(&di, name, &d); 1151 if (rc == EOK) goto hit; 1152 if (rc == ENOENT) goto miss; 1198 1153 1199 1154 err: 1200 1155 (void) fat_node_put(fn); 1201 1156 async_answer_0(callid, rc); 1202 return rc; 1157 async_answer_0(rid, rc); 1158 return; 1159 1160 miss: 1161 rc = fat_directory_close(&di); 1162 if (rc!=EOK) 1163 goto err; 1164 rc = fat_node_put(fn); 1165 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1166 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1167 return; 1203 1168 1204 1169 hit: 1170 pos = di.pos; 1171 rc = fat_directory_close(&di); 1172 if (rc!=EOK) 1173 goto err; 1205 1174 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1206 bytes = (pos - spos) +1;1175 bytes = (pos - spos)+1; 1207 1176 } 1208 1177 1209 1178 rc = fat_node_put(fn); 1210 *rbytes = bytes; 1211 return rc; 1212 } 1213 1214 static int 1215 fat_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos, 1216 size_t *wbytes, aoff64_t *nsize) 1217 { 1179 async_answer_1(rid, rc, (sysarg_t)bytes); 1180 } 1181 1182 void fat_write(ipc_callid_t rid, ipc_call_t *request) 1183 { 1184 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1185 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1186 aoff64_t pos = 1187 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1218 1188 fs_node_t *fn; 1219 1189 fat_node_t *nodep; 1220 1190 fat_bs_t *bs; 1221 size_t bytes ;1191 size_t bytes, size; 1222 1192 block_t *b; 1223 1193 aoff64_t boundary; 1224 1194 int flags = BLOCK_FLAGS_NONE; 1225 1195 int rc; 1226 1196 1227 1197 rc = fat_node_get(&fn, devmap_handle, index); 1228 if (rc != EOK) 1229 return rc; 1230 if (!fn) 1231 return ENOENT; 1198 if (rc != EOK) { 1199 async_answer_0(rid, rc); 1200 return; 1201 } 1202 if (!fn) { 1203 async_answer_0(rid, ENOENT); 1204 return; 1205 } 1232 1206 nodep = FAT_NODE(fn); 1233 1207 1234 1208 ipc_callid_t callid; 1235 1209 size_t len; … … 1237 1211 (void) fat_node_put(fn); 1238 1212 async_answer_0(callid, EINVAL); 1239 return EINVAL; 1213 async_answer_0(rid, EINVAL); 1214 return; 1240 1215 } 1241 1216 … … 1247 1222 * but this one greatly simplifies fat_write(). Note that we can afford 1248 1223 * to do this because the client must be ready to handle the return 1249 * value signalizing a smaller number of bytes written. 1250 */ 1224 * value signalizing a smaller number of bytes written. 1225 */ 1251 1226 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1252 1227 if (bytes == BPS(bs)) 1253 1228 flags |= BLOCK_FLAGS_NOREAD; 1254 1229 1255 1230 boundary = ROUND_UP(nodep->size, BPC(bs)); 1256 1231 if (pos < boundary) { … … 1265 1240 (void) fat_node_put(fn); 1266 1241 async_answer_0(callid, rc); 1267 return rc; 1242 async_answer_0(rid, rc); 1243 return; 1268 1244 } 1269 1245 rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags); … … 1271 1247 (void) fat_node_put(fn); 1272 1248 async_answer_0(callid, rc); 1273 return rc; 1249 async_answer_0(rid, rc); 1250 return; 1274 1251 } 1275 1252 (void) async_data_write_finalize(callid, … … 1279 1256 if (rc != EOK) { 1280 1257 (void) fat_node_put(fn); 1281 return rc; 1258 async_answer_0(rid, rc); 1259 return; 1282 1260 } 1283 1261 if (pos + bytes > nodep->size) { … … 1285 1263 nodep->dirty = true; /* need to sync node */ 1286 1264 } 1287 *wbytes = bytes; 1288 *nsize = nodep->size; 1265 size = nodep->size; 1289 1266 rc = fat_node_put(fn); 1290 return rc; 1267 async_answer_2(rid, rc, bytes, nodep->size); 1268 return; 1291 1269 } else { 1292 1270 /* … … 1295 1273 */ 1296 1274 unsigned nclsts; 1297 fat_cluster_t mcl, lcl; 1298 1275 fat_cluster_t mcl, lcl; 1276 1299 1277 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1300 1278 /* create an independent chain of nclsts clusters in all FATs */ … … 1304 1282 (void) fat_node_put(fn); 1305 1283 async_answer_0(callid, rc); 1306 return rc; 1284 async_answer_0(rid, rc); 1285 return; 1307 1286 } 1308 1287 /* zero fill any gaps */ … … 1312 1291 (void) fat_node_put(fn); 1313 1292 async_answer_0(callid, rc); 1314 return rc; 1293 async_answer_0(rid, rc); 1294 return; 1315 1295 } 1316 1296 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL, … … 1320 1300 (void) fat_node_put(fn); 1321 1301 async_answer_0(callid, rc); 1322 return rc; 1302 async_answer_0(rid, rc); 1303 return; 1323 1304 } 1324 1305 (void) async_data_write_finalize(callid, … … 1329 1310 (void) fat_free_clusters(bs, devmap_handle, mcl); 1330 1311 (void) fat_node_put(fn); 1331 return rc; 1312 async_answer_0(rid, rc); 1313 return; 1332 1314 } 1333 1315 /* … … 1339 1321 (void) fat_free_clusters(bs, devmap_handle, mcl); 1340 1322 (void) fat_node_put(fn); 1341 return rc; 1342 } 1343 *nsize = nodep->size = pos + bytes; 1323 async_answer_0(rid, rc); 1324 return; 1325 } 1326 nodep->size = size = pos + bytes; 1327 nodep->dirty = true; /* need to sync node */ 1344 1328 rc = fat_node_put(fn); 1345 nodep->dirty = true; /* need to sync node */ 1346 *wbytes = bytes; 1347 return rc; 1348 } 1349 } 1350 1351 static int 1352 fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size) 1353 { 1329 async_answer_2(rid, rc, bytes, size); 1330 return; 1331 } 1332 } 1333 1334 void fat_truncate(ipc_callid_t rid, ipc_call_t *request) 1335 { 1336 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1337 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1338 aoff64_t size = 1339 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1354 1340 fs_node_t *fn; 1355 1341 fat_node_t *nodep; … … 1358 1344 1359 1345 rc = fat_node_get(&fn, devmap_handle, index); 1360 if (rc != EOK) 1361 return rc; 1362 if (!fn) 1363 return ENOENT; 1346 if (rc != EOK) { 1347 async_answer_0(rid, rc); 1348 return; 1349 } 1350 if (!fn) { 1351 async_answer_0(rid, ENOENT); 1352 return; 1353 } 1364 1354 nodep = FAT_NODE(fn); 1365 1355 … … 1380 1370 nodep->size = size; 1381 1371 nodep->dirty = true; /* need to sync node */ 1382 rc = EOK; 1372 rc = EOK; 1383 1373 } else { 1384 1374 /* … … 1401 1391 nodep->size = size; 1402 1392 nodep->dirty = true; /* need to sync node */ 1403 rc = EOK; 1393 rc = EOK; 1404 1394 } 1405 1395 out: 1406 1396 fat_node_put(fn); 1407 return rc; 1408 } 1409 1410 static int fat_close(devmap_handle_t devmap_handle, fs_index_t index) 1411 { 1412 return EOK; 1413 } 1414 1415 static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index) 1416 { 1397 async_answer_0(rid, rc); 1398 return; 1399 } 1400 1401 void fat_close(ipc_callid_t rid, ipc_call_t *request) 1402 { 1403 async_answer_0(rid, EOK); 1404 } 1405 1406 void fat_destroy(ipc_callid_t rid, ipc_call_t *request) 1407 { 1408 devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request); 1409 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1417 1410 fs_node_t *fn; 1418 1411 fat_node_t *nodep; … … 1420 1413 1421 1414 rc = fat_node_get(&fn, devmap_handle, index); 1422 if (rc != EOK) 1423 return rc; 1424 if (!fn) 1425 return ENOENT; 1415 if (rc != EOK) { 1416 async_answer_0(rid, rc); 1417 return; 1418 } 1419 if (!fn) { 1420 async_answer_0(rid, ENOENT); 1421 return; 1422 } 1426 1423 1427 1424 nodep = FAT_NODE(fn); … … 1433 1430 1434 1431 rc = fat_destroy_node(fn); 1435 return rc; 1436 } 1437 1438 static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index) 1439 { 1432 async_answer_0(rid, rc); 1433 } 1434 1435 void fat_open_node(ipc_callid_t rid, ipc_call_t *request) 1436 { 1437 libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1438 } 1439 1440 void fat_stat(ipc_callid_t rid, ipc_call_t *request) 1441 { 1442 libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1443 } 1444 1445 void fat_sync(ipc_callid_t rid, ipc_call_t *request) 1446 { 1447 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1448 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1449 1440 1450 fs_node_t *fn; 1441 1451 int rc = fat_node_get(&fn, devmap_handle, index); 1442 if (rc != EOK) 1443 return rc; 1444 if (!fn) 1445 return ENOENT; 1446 1452 if (rc != EOK) { 1453 async_answer_0(rid, rc); 1454 return; 1455 } 1456 if (!fn) { 1457 async_answer_0(rid, ENOENT); 1458 return; 1459 } 1460 1447 1461 fat_node_t *nodep = FAT_NODE(fn); 1448 1462 1449 1463 nodep->dirty = true; 1450 1464 rc = fat_node_sync(nodep); 1451 1465 1452 1466 fat_node_put(fn); 1453 return rc; 1454 } 1455 1456 vfs_out_ops_t fat_ops = { 1457 .mounted = fat_mounted, 1458 .unmounted = fat_unmounted, 1459 .read = fat_read, 1460 .write = fat_write, 1461 .truncate = fat_truncate, 1462 .close = fat_close, 1463 .destroy = fat_destroy, 1464 .sync = fat_sync, 1465 }; 1467 async_answer_0(rid, rc); 1468 } 1466 1469 1467 1470 /**
Note:
See TracChangeset
for help on using the changeset viewer.