Changes in uspace/srv/fs/fat/fat_ops.c [b72efe8:b33870b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
rb72efe8 rb33870b 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> 43 45 #include <libblock.h> 44 46 #include <ipc/services.h> 45 #include <ipc/ devmap.h>47 #include <ipc/loc.h> 46 48 #include <macros.h> 47 49 #include <async.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) … … 72 75 * Forward declarations of FAT libfs operations. 73 76 */ 74 static int fat_root_get(fs_node_t **, devmap_handle_t);77 static int fat_root_get(fs_node_t **, service_id_t); 75 78 static int fat_match(fs_node_t **, fs_node_t *, const char *); 76 static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);79 static int fat_node_get(fs_node_t **, service_id_t, fs_index_t); 77 80 static int fat_node_open(fs_node_t *); 78 81 static int fat_node_put(fs_node_t *); 79 static int fat_create_node(fs_node_t **, devmap_handle_t, int);82 static int fat_create_node(fs_node_t **, service_id_t, int); 80 83 static int fat_destroy_node(fs_node_t *); 81 84 static int fat_link(fs_node_t *, fs_node_t *, const char *); … … 85 88 static aoff64_t fat_size_get(fs_node_t *); 86 89 static unsigned fat_lnkcnt_get(fs_node_t *); 87 static char fat_plb_get_char(unsigned);88 90 static bool fat_is_directory(fs_node_t *); 89 91 static bool fat_is_file(fs_node_t *node); 90 static devmap_handle_t fat_device_get(fs_node_t *node);92 static service_id_t fat_service_get(fs_node_t *node); 91 93 92 94 /* … … 105 107 node->dirty = false; 106 108 node->lastc_cached_valid = false; 107 node->lastc_cached_value = FAT_CLST_LAST1;109 node->lastc_cached_value = 0; 108 110 node->currc_cached_valid = false; 109 111 node->currc_cached_bn = 0; 110 node->currc_cached_value = FAT_CLST_LAST1;112 node->currc_cached_value = 0; 111 113 } 112 114 … … 117 119 fat_dentry_t *d; 118 120 int rc; 119 121 120 122 assert(node->dirty); 121 123 122 bs = block_bb_get(node->idx-> devmap_handle);123 124 bs = block_bb_get(node->idx->service_id); 125 124 126 /* Read the block that contains the dentry of interest. */ 125 rc = _fat_block_get(&b, bs, node->idx-> devmap_handle, node->idx->pfc,127 rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, 126 128 NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 127 129 BLOCK_FLAGS_NONE); … … 137 139 d->attr = FAT_ATTR_SUBDIR; 138 140 } 139 141 140 142 /* TODO: update other fields? (e.g time fields) */ 141 143 142 144 b->dirty = true; /* need to sync block */ 143 145 rc = block_put(b); … … 145 147 } 146 148 147 static int fat_node_fini_by_ devmap_handle(devmap_handle_t devmap_handle)149 static int fat_node_fini_by_service_id(service_id_t service_id) 148 150 { 149 151 fat_node_t *nodep; … … 169 171 goto restart; 170 172 } 171 if (nodep->idx-> devmap_handle != devmap_handle) {173 if (nodep->idx->service_id != service_id) { 172 174 fibril_mutex_unlock(&nodep->idx->lock); 173 175 fibril_mutex_unlock(&nodep->lock); … … 256 258 fn->data = nodep; 257 259 nodep->bp = fn; 258 260 259 261 *nodepp = nodep; 260 262 return EOK; … … 292 294 * We must instantiate the node from the file system. 293 295 */ 294 296 295 297 assert(idxp->pfc); 296 298 … … 299 301 return rc; 300 302 301 bs = block_bb_get(idxp-> devmap_handle);303 bs = block_bb_get(idxp->service_id); 302 304 303 305 /* Read the block that contains the dentry of interest. */ 304 rc = _fat_block_get(&b, bs, idxp-> devmap_handle, idxp->pfc, NULL,306 rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL, 305 307 (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE); 306 308 if (rc != EOK) { … … 310 312 311 313 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs)); 314 if (FAT_IS_FAT32(bs)) { 315 nodep->firstc = uint16_t_le2host(d->firstc_lo) | 316 (uint16_t_le2host(d->firstc_hi) << 16); 317 } else 318 nodep->firstc = uint16_t_le2host(d->firstc); 319 312 320 if (d->attr & FAT_ATTR_SUBDIR) { 313 /* 321 /* 314 322 * The only directory which does not have this bit set is the 315 323 * root directory itself. The root directory node is handled … … 317 325 */ 318 326 nodep->type = FAT_DIRECTORY; 327 319 328 /* 320 329 * Unfortunately, the 'size' field of the FAT dentry is not … … 322 331 * size of the directory by walking the FAT. 323 332 */ 324 uint 16_t clusters;325 rc = fat_clusters_get(&clusters, bs, idxp-> devmap_handle,326 uint16_t_le2host(d->firstc));333 uint32_t clusters; 334 rc = fat_clusters_get(&clusters, bs, idxp->service_id, 335 nodep->firstc); 327 336 if (rc != EOK) { 328 337 (void) block_put(b); … … 335 344 nodep->size = uint32_t_le2host(d->size); 336 345 } 337 nodep->firstc = uint16_t_le2host(d->firstc); 346 338 347 nodep->lnkcnt = 1; 339 348 nodep->refcnt = 1; … … 357 366 */ 358 367 359 int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)360 { 361 return fat_node_get(rfn, devmap_handle, 0);368 int fat_root_get(fs_node_t **rfn, service_id_t service_id) 369 { 370 return fat_node_get(rfn, service_id, 0); 362 371 } 363 372 364 373 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 365 374 { 366 fat_bs_t *bs;367 375 fat_node_t *parentp = FAT_NODE(pfn); 368 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 369 unsigned i, j; 370 unsigned blocks; 376 char name[FAT_LFN_NAME_SIZE]; 371 377 fat_dentry_t *d; 372 devmap_handle_t devmap_handle; 373 block_t *b; 378 service_id_t service_id; 374 379 int rc; 375 380 376 381 fibril_mutex_lock(&parentp->idx->lock); 377 devmap_handle = parentp->idx->devmap_handle;382 service_id = parentp->idx->service_id; 378 383 fibril_mutex_unlock(&parentp->idx->lock); 379 380 bs = block_bb_get(devmap_handle); 381 blocks = parentp->size / BPS(bs); 382 for (i = 0; i < blocks; i++) { 383 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 384 if (rc != EOK) 385 return rc; 386 for (j = 0; j < DPS(bs); j++) { 387 d = ((fat_dentry_t *)b->data) + j; 388 switch (fat_classify_dentry(d)) { 389 case FAT_DENTRY_SKIP: 390 case FAT_DENTRY_FREE: 391 continue; 392 case FAT_DENTRY_LAST: 393 /* miss */ 394 rc = block_put(b); 395 *rfn = NULL; 396 return rc; 397 default: 398 case FAT_DENTRY_VALID: 399 fat_dentry_name_get(d, name); 400 break; 384 385 fat_directory_t di; 386 rc = fat_directory_open(parentp, &di); 387 if (rc != EOK) 388 return rc; 389 390 while (fat_directory_read(&di, name, &d) == EOK) { 391 if (fat_dentry_namecmp(name, component) == 0) { 392 /* hit */ 393 fat_node_t *nodep; 394 aoff64_t o = di.pos % 395 (BPS(di.bs) / sizeof(fat_dentry_t)); 396 fat_idx_t *idx = fat_idx_get_by_pos(service_id, 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; 401 405 } 402 if (fat_dentry_namecmp(name, component) == 0) { 403 /* hit */ 404 fat_node_t *nodep; 405 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle, 406 parentp->firstc, i * DPS(bs) + j); 407 if (!idx) { 408 /* 409 * Can happen if memory is low or if we 410 * run out of 32-bit indices. 411 */ 412 rc = block_put(b); 413 return (rc == EOK) ? ENOMEM : rc; 414 } 415 rc = fat_node_get_core(&nodep, idx); 416 fibril_mutex_unlock(&idx->lock); 417 if (rc != EOK) { 418 (void) block_put(b); 419 return rc; 420 } 421 *rfn = FS_NODE(nodep); 422 rc = block_put(b); 423 if (rc != EOK) 424 (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); 425 410 return rc; 426 411 } 427 } 428 rc = block_put(b); 429 if (rc != EOK) 412 *rfn = FS_NODE(nodep); 413 rc = fat_directory_close(&di); 414 if (rc != EOK) 415 (void) fat_node_put(*rfn); 430 416 return rc; 431 } 432 417 } else { 418 rc = fat_directory_next(&di); 419 if (rc != EOK) 420 break; 421 } 422 } 423 (void) fat_directory_close(&di); 433 424 *rfn = NULL; 434 425 return EOK; … … 436 427 437 428 /** Instantiate a FAT in-core node. */ 438 int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)429 int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) 439 430 { 440 431 fat_node_t *nodep; … … 442 433 int rc; 443 434 444 idxp = fat_idx_get_by_index( devmap_handle, index);435 idxp = fat_idx_get_by_index(service_id, index); 445 436 if (!idxp) { 446 437 *rfn = NULL; … … 493 484 } 494 485 495 int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)486 int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 496 487 { 497 488 fat_idx_t *idxp; … … 501 492 int rc; 502 493 503 bs = block_bb_get( devmap_handle);494 bs = block_bb_get(service_id); 504 495 if (flags & L_DIRECTORY) { 505 496 /* allocate a cluster */ 506 rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);497 rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl); 507 498 if (rc != EOK) 508 499 return rc; 509 500 /* populate the new cluster with unused dentries */ 510 rc = fat_zero_cluster(bs, devmap_handle, mcl);511 if (rc != EOK) { 512 (void) fat_free_clusters(bs, devmap_handle, mcl);501 rc = fat_zero_cluster(bs, service_id, mcl); 502 if (rc != EOK) { 503 (void) fat_free_clusters(bs, service_id, mcl); 513 504 return rc; 514 505 } … … 517 508 rc = fat_node_get_new(&nodep); 518 509 if (rc != EOK) { 519 (void) fat_free_clusters(bs, devmap_handle, mcl);520 return rc; 521 } 522 rc = fat_idx_get_new(&idxp, devmap_handle);510 (void) fat_free_clusters(bs, service_id, mcl); 511 return rc; 512 } 513 rc = fat_idx_get_new(&idxp, service_id); 523 514 if (rc != EOK) { 524 (void) fat_free_clusters(bs, devmap_handle, mcl);515 (void) fat_free_clusters(bs, service_id, mcl); 525 516 (void) fat_node_put(FS_NODE(nodep)); 526 517 return rc; … … 571 562 assert(!has_children); 572 563 573 bs = block_bb_get(nodep->idx-> devmap_handle);564 bs = block_bb_get(nodep->idx->service_id); 574 565 if (nodep->firstc != FAT_CLST_RES0) { 575 566 assert(nodep->size); 576 567 /* Free all clusters allocated to the node. */ 577 rc = fat_free_clusters(bs, nodep->idx-> devmap_handle,568 rc = fat_free_clusters(bs, nodep->idx->service_id, 578 569 nodep->firstc); 579 570 } … … 592 583 fat_bs_t *bs; 593 584 block_t *b; 594 unsigned i, j; 595 unsigned blocks; 596 fat_cluster_t mcl, lcl; 585 fat_directory_t di; 586 fat_dentry_t de; 597 587 int rc; 598 588 … … 608 598 fibril_mutex_unlock(&childp->lock); 609 599 610 if (!fat_dentry_name_verify(name)) { 611 /* 612 * Attempt to create unsupported name. 613 */ 600 if (!fat_valid_name(name)) 614 601 return ENOTSUP; 615 } 616 617 /* 618 * Get us an unused parent node's dentry or grow the parent and allocate 619 * a new one. 620 */ 621 602 622 603 fibril_mutex_lock(&parentp->idx->lock); 623 bs = block_bb_get(parentp->idx->devmap_handle); 624 625 blocks = parentp->size / BPS(bs); 626 627 for (i = 0; i < blocks; i++) { 628 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 629 if (rc != EOK) { 630 fibril_mutex_unlock(&parentp->idx->lock); 631 return rc; 632 } 633 for (j = 0; j < DPS(bs); j++) { 634 d = ((fat_dentry_t *)b->data) + j; 635 switch (fat_classify_dentry(d)) { 636 case FAT_DENTRY_SKIP: 637 case FAT_DENTRY_VALID: 638 /* skipping used and meta entries */ 639 continue; 640 case FAT_DENTRY_FREE: 641 case FAT_DENTRY_LAST: 642 /* found an empty slot */ 643 goto hit; 644 } 645 } 646 rc = block_put(b); 647 if (rc != EOK) { 648 fibril_mutex_unlock(&parentp->idx->lock); 649 return rc; 650 } 651 } 652 j = 0; 653 654 /* 655 * We need to grow the parent in order to create a new unused dentry. 656 */ 657 if (parentp->firstc == FAT_CLST_ROOT) { 658 /* Can't grow the root directory. */ 659 fibril_mutex_unlock(&parentp->idx->lock); 660 return ENOSPC; 661 } 662 rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl); 604 bs = block_bb_get(parentp->idx->service_id); 605 rc = fat_directory_open(parentp, &di); 663 606 if (rc != EOK) { 664 607 fibril_mutex_unlock(&parentp->idx->lock); 665 608 return rc; 666 609 } 667 rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl); 668 if (rc != EOK) { 669 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 670 fibril_mutex_unlock(&parentp->idx->lock); 671 return rc; 672 } 673 rc = fat_append_clusters(bs, parentp, mcl, lcl); 674 if (rc != EOK) { 675 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl); 676 fibril_mutex_unlock(&parentp->idx->lock); 677 return rc; 678 } 679 parentp->size += BPS(bs) * SPC(bs); 680 parentp->dirty = true; /* need to sync node */ 681 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 682 if (rc != EOK) { 683 fibril_mutex_unlock(&parentp->idx->lock); 684 return rc; 685 } 686 d = (fat_dentry_t *)b->data; 687 688 hit: 610 689 611 /* 690 612 * At this point we only establish the link between the parent and the … … 693 615 * dentry data is kept in the child node structure. 694 616 */ 695 memset(d, 0, sizeof(fat_dentry_t)); 696 fat_dentry_name_set(d, name); 697 b->dirty = true; /* need to sync block */ 698 rc = block_put(b); 617 memset(&de, 0, sizeof(fat_dentry_t)); 618 619 rc = fat_directory_write(&di, name, &de); 620 if (rc != EOK) { 621 (void) fat_directory_close(&di); 622 fibril_mutex_unlock(&parentp->idx->lock); 623 return rc; 624 } 625 rc = fat_directory_close(&di); 626 if (rc != EOK) { 627 fibril_mutex_unlock(&parentp->idx->lock); 628 return rc; 629 } 630 699 631 fibril_mutex_unlock(&parentp->idx->lock); 700 if (rc != EOK)701 return rc;702 632 703 633 fibril_mutex_lock(&childp->idx->lock); 704 634 705 635 if (childp->type == FAT_DIRECTORY) { 706 636 /* … … 721 651 d = (fat_dentry_t *) b->data; 722 652 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 723 ( str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {653 (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) { 724 654 memset(d, 0, sizeof(fat_dentry_t)); 725 655 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 731 661 d++; 732 662 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 733 ( str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {663 (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) { 734 664 memset(d, 0, sizeof(fat_dentry_t)); 735 665 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 736 666 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 737 667 d->attr = FAT_ATTR_SUBDIR; 738 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?739 host2uint16_t_le(FAT_CLST_R ES0) :668 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 669 host2uint16_t_le(FAT_CLST_ROOTPAR) : 740 670 host2uint16_t_le(parentp->firstc); 741 671 /* TODO: initialize also the date/time members. */ … … 751 681 752 682 childp->idx->pfc = parentp->firstc; 753 childp->idx->pdi = i * DPS(bs) + j;683 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */ 754 684 fibril_mutex_unlock(&childp->idx->lock); 755 685 … … 771 701 fat_node_t *parentp = FAT_NODE(pfn); 772 702 fat_node_t *childp = FAT_NODE(cfn); 773 fat_bs_t *bs;774 fat_dentry_t *d;775 block_t *b;776 703 bool has_children; 777 704 int rc; … … 779 706 if (!parentp) 780 707 return EBUSY; 781 708 782 709 rc = fat_has_children(&has_children, cfn); 783 710 if (rc != EOK) … … 790 717 assert(childp->lnkcnt == 1); 791 718 fibril_mutex_lock(&childp->idx->lock); 792 bs = block_bb_get(childp->idx->devmap_handle); 793 794 rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc, 795 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 796 BLOCK_FLAGS_NONE); 797 if (rc != EOK) 719 720 fat_directory_t di; 721 rc = fat_directory_open(parentp, &di); 722 if (rc != EOK) 798 723 goto error; 799 d = (fat_dentry_t *)b->data + 800 (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t))); 801 /* mark the dentry as not-currently-used */ 802 d->name[0] = FAT_DENTRY_ERASED; 803 b->dirty = true; /* need to sync block */ 804 rc = block_put(b); 724 rc = fat_directory_seek(&di, childp->idx->pdi); 725 if (rc != EOK) 726 goto error; 727 rc = fat_directory_erase(&di); 728 if (rc != EOK) 729 goto error; 730 rc = fat_directory_close(&di); 805 731 if (rc != EOK) 806 732 goto error; … … 821 747 822 748 error: 823 fibril_mutex_unlock(&parentp->idx->lock); 749 (void) fat_directory_close(&di); 750 fibril_mutex_unlock(&childp->idx->lock); 824 751 fibril_mutex_unlock(&childp->lock); 825 fibril_mutex_unlock(& childp->idx->lock);752 fibril_mutex_unlock(&parentp->lock); 826 753 return rc; 827 754 } … … 840 767 return EOK; 841 768 } 842 769 843 770 fibril_mutex_lock(&nodep->idx->lock); 844 bs = block_bb_get(nodep->idx-> devmap_handle);771 bs = block_bb_get(nodep->idx->service_id); 845 772 846 773 blocks = nodep->size / BPS(bs); … … 848 775 for (i = 0; i < blocks; i++) { 849 776 fat_dentry_t *d; 850 777 851 778 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 852 779 if (rc != EOK) { … … 876 803 if (rc != EOK) { 877 804 fibril_mutex_unlock(&nodep->idx->lock); 878 return rc; 805 return rc; 879 806 } 880 807 } … … 901 828 } 902 829 903 char fat_plb_get_char(unsigned pos)904 {905 return fat_reg.plb_ro[pos % PLB_SIZE];906 }907 908 830 bool fat_is_directory(fs_node_t *fn) 909 831 { … … 916 838 } 917 839 918 devmap_handle_t fat_device_get(fs_node_t *node)840 service_id_t fat_service_get(fs_node_t *node) 919 841 { 920 842 return 0; … … 936 858 .size_get = fat_size_get, 937 859 .lnkcnt_get = fat_lnkcnt_get, 938 .plb_get_char = fat_plb_get_char,939 860 .is_directory = fat_is_directory, 940 861 .is_file = fat_is_file, 941 . device_get = fat_device_get862 .service_get = fat_service_get 942 863 }; 943 864 944 865 /* 945 * VFSoperations.866 * FAT VFS_OUT operations. 946 867 */ 947 868 948 void fat_mounted(ipc_callid_t rid, ipc_call_t *request) 949 { 950 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 869 static int 870 fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index, 871 aoff64_t *size, unsigned *linkcnt) 872 { 951 873 enum cache_mode cmode; 952 874 fat_bs_t *bs; 953 954 /* Accept the mount options */ 955 char *opts; 956 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL); 957 958 if (rc != EOK) { 959 async_answer_0(rid, rc); 960 return; 961 } 875 int rc; 962 876 963 877 /* Check for option enabling write through. */ … … 967 881 cmode = CACHE_MODE_WB; 968 882 969 free(opts);970 971 883 /* initialize libblock */ 972 rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE); 884 rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE); 885 if (rc != EOK) 886 return rc; 887 888 /* prepare the boot block */ 889 rc = block_bb_read(service_id, BS_BLOCK); 973 890 if (rc != EOK) { 974 async_answer_0(rid, rc); 975 return; 976 } 977 978 /* prepare the boot block */ 979 rc = block_bb_read(devmap_handle, BS_BLOCK); 980 if (rc != EOK) { 981 block_fini(devmap_handle); 982 async_answer_0(rid, rc); 983 return; 891 block_fini(service_id); 892 return rc; 984 893 } 985 894 986 895 /* get the buffer with the boot sector */ 987 bs = block_bb_get( devmap_handle);896 bs = block_bb_get(service_id); 988 897 989 898 if (BPS(bs) != BS_SIZE) { 990 block_fini(devmap_handle); 991 async_answer_0(rid, ENOTSUP); 992 return; 899 block_fini(service_id); 900 return ENOTSUP; 993 901 } 994 902 995 903 /* Initialize the block cache */ 996 rc = block_cache_init( devmap_handle, BPS(bs), 0 /* XXX */, cmode);904 rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode); 997 905 if (rc != EOK) { 998 block_fini(devmap_handle); 999 async_answer_0(rid, rc); 1000 return; 906 block_fini(service_id); 907 return rc; 1001 908 } 1002 909 1003 910 /* Do some simple sanity checks on the file system. */ 1004 rc = fat_sanity_check(bs, devmap_handle);911 rc = fat_sanity_check(bs, service_id); 1005 912 if (rc != EOK) { 1006 (void) block_cache_fini(devmap_handle); 1007 block_fini(devmap_handle); 1008 async_answer_0(rid, rc); 1009 return; 1010 } 1011 1012 rc = fat_idx_init_by_devmap_handle(devmap_handle); 913 (void) block_cache_fini(service_id); 914 block_fini(service_id); 915 return rc; 916 } 917 918 rc = fat_idx_init_by_service_id(service_id); 1013 919 if (rc != EOK) { 1014 (void) block_cache_fini(devmap_handle); 1015 block_fini(devmap_handle); 1016 async_answer_0(rid, rc); 1017 return; 920 (void) block_cache_fini(service_id); 921 block_fini(service_id); 922 return rc; 1018 923 } 1019 924 … … 1021 926 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 1022 927 if (!rfn) { 1023 (void) block_cache_fini( devmap_handle);1024 block_fini( devmap_handle);1025 fat_idx_fini_by_ devmap_handle(devmap_handle);1026 async_answer_0(rid, ENOMEM);1027 return;1028 } 928 (void) block_cache_fini(service_id); 929 block_fini(service_id); 930 fat_idx_fini_by_service_id(service_id); 931 return ENOMEM; 932 } 933 1029 934 fs_node_initialize(rfn); 1030 935 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); 1031 936 if (!rootp) { 1032 937 free(rfn); 1033 (void) block_cache_fini(devmap_handle); 1034 block_fini(devmap_handle); 1035 fat_idx_fini_by_devmap_handle(devmap_handle); 1036 async_answer_0(rid, ENOMEM); 1037 return; 938 (void) block_cache_fini(service_id); 939 block_fini(service_id); 940 fat_idx_fini_by_service_id(service_id); 941 return ENOMEM; 1038 942 } 1039 943 fat_node_initialize(rootp); 1040 944 1041 fat_idx_t *ridxp = fat_idx_get_by_pos( devmap_handle, FAT_CLST_ROOTPAR, 0);945 fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0); 1042 946 if (!ridxp) { 1043 947 free(rfn); 1044 948 free(rootp); 1045 (void) block_cache_fini(devmap_handle); 1046 block_fini(devmap_handle); 1047 fat_idx_fini_by_devmap_handle(devmap_handle); 1048 async_answer_0(rid, ENOMEM); 1049 return; 949 (void) block_cache_fini(service_id); 950 block_fini(service_id); 951 fat_idx_fini_by_service_id(service_id); 952 return ENOMEM; 1050 953 } 1051 954 assert(ridxp->index == 0); … … 1053 956 1054 957 rootp->type = FAT_DIRECTORY; 1055 rootp->firstc = FAT_ CLST_ROOT;958 rootp->firstc = FAT_ROOT_CLST(bs); 1056 959 rootp->refcnt = 1; 1057 960 rootp->lnkcnt = 0; /* FS root is not linked */ 1058 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 961 962 if (FAT_IS_FAT32(bs)) { 963 uint32_t clusters; 964 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc); 965 if (rc != EOK) { 966 free(rfn); 967 free(rootp); 968 (void) block_cache_fini(service_id); 969 block_fini(service_id); 970 fat_idx_fini_by_service_id(service_id); 971 return ENOTSUP; 972 } 973 rootp->size = BPS(bs) * SPC(bs) * clusters; 974 } else 975 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 976 1059 977 rootp->idx = ridxp; 1060 978 ridxp->nodep = rootp; 1061 979 rootp->bp = rfn; 1062 980 rfn->data = rootp; 1063 981 1064 982 fibril_mutex_unlock(&ridxp->lock); 1065 983 1066 async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); 1067 } 1068 1069 void fat_mount(ipc_callid_t rid, ipc_call_t *request) 1070 { 1071 libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1072 } 1073 1074 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request) 1075 { 1076 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 984 *index = ridxp->index; 985 *size = rootp->size; 986 *linkcnt = rootp->lnkcnt; 987 988 return EOK; 989 } 990 991 static int fat_unmounted(service_id_t service_id) 992 { 1077 993 fs_node_t *fn; 1078 994 fat_node_t *nodep; 1079 995 int rc; 1080 996 1081 rc = fat_root_get(&fn, devmap_handle); 1082 if (rc != EOK) { 1083 async_answer_0(rid, rc); 1084 return; 1085 } 997 rc = fat_root_get(&fn, service_id); 998 if (rc != EOK) 999 return rc; 1086 1000 nodep = FAT_NODE(fn); 1087 1001 … … 1092 1006 if (nodep->refcnt != 2) { 1093 1007 (void) fat_node_put(fn); 1094 async_answer_0(rid, EBUSY); 1095 return; 1096 } 1097 1008 return EBUSY; 1009 } 1010 1098 1011 /* 1099 1012 * Put the root node and force it to the FAT free node list. … … 1107 1020 * stop using libblock for this instance. 1108 1021 */ 1109 (void) fat_node_fini_by_devmap_handle(devmap_handle); 1110 fat_idx_fini_by_devmap_handle(devmap_handle); 1111 (void) block_cache_fini(devmap_handle); 1112 block_fini(devmap_handle); 1113 1114 async_answer_0(rid, EOK); 1115 } 1116 1117 void fat_unmount(ipc_callid_t rid, ipc_call_t *request) 1118 { 1119 libfs_unmount(&fat_libfs_ops, rid, request); 1120 } 1121 1122 void fat_lookup(ipc_callid_t rid, ipc_call_t *request) 1123 { 1124 libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1125 } 1126 1127 void fat_read(ipc_callid_t rid, ipc_call_t *request) 1128 { 1129 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1130 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1131 aoff64_t pos = 1132 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1022 (void) fat_node_fini_by_service_id(service_id); 1023 fat_idx_fini_by_service_id(service_id); 1024 (void) block_cache_fini(service_id); 1025 block_fini(service_id); 1026 1027 return EOK; 1028 } 1029 1030 static int 1031 fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 1032 size_t *rbytes) 1033 { 1133 1034 fs_node_t *fn; 1134 1035 fat_node_t *nodep; … … 1138 1039 int rc; 1139 1040 1140 rc = fat_node_get(&fn, devmap_handle, index); 1141 if (rc != EOK) { 1142 async_answer_0(rid, rc); 1143 return; 1144 } 1145 if (!fn) { 1146 async_answer_0(rid, ENOENT); 1147 return; 1148 } 1041 rc = fat_node_get(&fn, service_id, index); 1042 if (rc != EOK) 1043 return rc; 1044 if (!fn) 1045 return ENOENT; 1149 1046 nodep = FAT_NODE(fn); 1150 1047 … … 1154 1051 fat_node_put(fn); 1155 1052 async_answer_0(callid, EINVAL); 1156 async_answer_0(rid, EINVAL); 1157 return; 1158 } 1159 1160 bs = block_bb_get(devmap_handle); 1053 return EINVAL; 1054 } 1055 1056 bs = block_bb_get(service_id); 1161 1057 1162 1058 if (nodep->type == FAT_FILE) { … … 1178 1074 fat_node_put(fn); 1179 1075 async_answer_0(callid, rc); 1180 async_answer_0(rid, rc); 1181 return; 1076 return rc; 1182 1077 } 1183 1078 (void) async_data_read_finalize(callid, … … 1186 1081 if (rc != EOK) { 1187 1082 fat_node_put(fn); 1188 async_answer_0(rid, rc); 1189 return; 1083 return rc; 1190 1084 } 1191 1085 } 1192 1086 } else { 1193 unsigned bnum;1194 1087 aoff64_t spos = pos; 1195 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1088 char name[FAT_LFN_NAME_SIZE]; 1196 1089 fat_dentry_t *d; 1197 1090 … … 1200 1093 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1201 1094 1202 /* 1203 * Our strategy for readdir() is to use the position pointer as 1204 * an index into the array of all dentries. On entry, it points 1205 * to the first unread dentry. If we skip any dentries, we bump 1206 * the position pointer accordingly. 1207 */ 1208 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs); 1209 while (bnum < nodep->size / BPS(bs)) { 1210 aoff64_t o; 1211 1212 rc = fat_block_get(&b, bs, nodep, bnum, 1213 BLOCK_FLAGS_NONE); 1214 if (rc != EOK) 1215 goto err; 1216 for (o = pos % (BPS(bs) / sizeof(fat_dentry_t)); 1217 o < BPS(bs) / sizeof(fat_dentry_t); 1218 o++, pos++) { 1219 d = ((fat_dentry_t *)b->data) + o; 1220 switch (fat_classify_dentry(d)) { 1221 case FAT_DENTRY_SKIP: 1222 case FAT_DENTRY_FREE: 1223 continue; 1224 case FAT_DENTRY_LAST: 1225 rc = block_put(b); 1226 if (rc != EOK) 1227 goto err; 1228 goto miss; 1229 default: 1230 case FAT_DENTRY_VALID: 1231 fat_dentry_name_get(d, name); 1232 rc = block_put(b); 1233 if (rc != EOK) 1234 goto err; 1235 goto hit; 1236 } 1237 } 1238 rc = block_put(b); 1239 if (rc != EOK) 1240 goto err; 1241 bnum++; 1242 } 1243 miss: 1244 rc = fat_node_put(fn); 1245 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1246 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1247 return; 1095 fat_directory_t di; 1096 rc = fat_directory_open(nodep, &di); 1097 if (rc != EOK) 1098 goto err; 1099 rc = fat_directory_seek(&di, pos); 1100 if (rc != EOK) { 1101 (void) fat_directory_close(&di); 1102 goto err; 1103 } 1104 1105 rc = fat_directory_read(&di, name, &d); 1106 if (rc == EOK) 1107 goto hit; 1108 if (rc == ENOENT) 1109 goto miss; 1248 1110 1249 1111 err: 1250 1112 (void) fat_node_put(fn); 1251 1113 async_answer_0(callid, rc); 1252 async_answer_0(rid, rc); 1253 return; 1114 return rc; 1115 1116 miss: 1117 rc = fat_directory_close(&di); 1118 if (rc != EOK) 1119 goto err; 1120 rc = fat_node_put(fn); 1121 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1122 *rbytes = 0; 1123 return rc != EOK ? rc : ENOENT; 1254 1124 1255 1125 hit: 1256 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1126 pos = di.pos; 1127 rc = fat_directory_close(&di); 1128 if (rc != EOK) 1129 goto err; 1130 (void) async_data_read_finalize(callid, name, 1131 str_size(name) + 1); 1257 1132 bytes = (pos - spos) + 1; 1258 1133 } 1259 1134 1260 1135 rc = fat_node_put(fn); 1261 async_answer_1(rid, rc, (sysarg_t)bytes); 1262 } 1263 1264 void fat_write(ipc_callid_t rid, ipc_call_t *request) 1265 { 1266 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1267 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1268 aoff64_t pos = 1269 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1136 *rbytes = bytes; 1137 return rc; 1138 } 1139 1140 static int 1141 fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 1142 size_t *wbytes, aoff64_t *nsize) 1143 { 1270 1144 fs_node_t *fn; 1271 1145 fat_node_t *nodep; 1272 1146 fat_bs_t *bs; 1273 size_t bytes , size;1147 size_t bytes; 1274 1148 block_t *b; 1275 1149 aoff64_t boundary; … … 1277 1151 int rc; 1278 1152 1279 rc = fat_node_get(&fn, devmap_handle, index); 1280 if (rc != EOK) { 1281 async_answer_0(rid, rc); 1282 return; 1283 } 1284 if (!fn) { 1285 async_answer_0(rid, ENOENT); 1286 return; 1287 } 1153 rc = fat_node_get(&fn, service_id, index); 1154 if (rc != EOK) 1155 return rc; 1156 if (!fn) 1157 return ENOENT; 1288 1158 nodep = FAT_NODE(fn); 1289 1159 1290 1160 ipc_callid_t callid; 1291 1161 size_t len; … … 1293 1163 (void) fat_node_put(fn); 1294 1164 async_answer_0(callid, EINVAL); 1295 async_answer_0(rid, EINVAL); 1296 return; 1297 } 1298 1299 bs = block_bb_get(devmap_handle); 1165 return EINVAL; 1166 } 1167 1168 bs = block_bb_get(service_id); 1300 1169 1301 1170 /* … … 1304 1173 * but this one greatly simplifies fat_write(). Note that we can afford 1305 1174 * to do this because the client must be ready to handle the return 1306 * value signalizing a smaller number of bytes written. 1307 */ 1175 * value signalizing a smaller number of bytes written. 1176 */ 1308 1177 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1309 1178 if (bytes == BPS(bs)) 1310 1179 flags |= BLOCK_FLAGS_NOREAD; 1311 1180 1312 1181 boundary = ROUND_UP(nodep->size, BPC(bs)); 1313 1182 if (pos < boundary) { … … 1322 1191 (void) fat_node_put(fn); 1323 1192 async_answer_0(callid, rc); 1324 async_answer_0(rid, rc); 1325 return; 1193 return rc; 1326 1194 } 1327 1195 rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags); … … 1329 1197 (void) fat_node_put(fn); 1330 1198 async_answer_0(callid, rc); 1331 async_answer_0(rid, rc); 1332 return; 1199 return rc; 1333 1200 } 1334 1201 (void) async_data_write_finalize(callid, … … 1338 1205 if (rc != EOK) { 1339 1206 (void) fat_node_put(fn); 1340 async_answer_0(rid, rc); 1341 return; 1207 return rc; 1342 1208 } 1343 1209 if (pos + bytes > nodep->size) { … … 1345 1211 nodep->dirty = true; /* need to sync node */ 1346 1212 } 1347 size = nodep->size; 1213 *wbytes = bytes; 1214 *nsize = nodep->size; 1348 1215 rc = fat_node_put(fn); 1349 async_answer_2(rid, rc, bytes, nodep->size); 1350 return; 1216 return rc; 1351 1217 } else { 1352 1218 /* … … 1355 1221 */ 1356 1222 unsigned nclsts; 1357 fat_cluster_t mcl, lcl; 1358 1223 fat_cluster_t mcl, lcl; 1224 1359 1225 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1360 1226 /* create an independent chain of nclsts clusters in all FATs */ 1361 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);1227 rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl); 1362 1228 if (rc != EOK) { 1363 1229 /* could not allocate a chain of nclsts clusters */ 1364 1230 (void) fat_node_put(fn); 1365 1231 async_answer_0(callid, rc); 1366 async_answer_0(rid, rc); 1367 return; 1232 return rc; 1368 1233 } 1369 1234 /* zero fill any gaps */ 1370 1235 rc = fat_fill_gap(bs, nodep, mcl, pos); 1371 1236 if (rc != EOK) { 1372 (void) fat_free_clusters(bs, devmap_handle, mcl);1237 (void) fat_free_clusters(bs, service_id, mcl); 1373 1238 (void) fat_node_put(fn); 1374 1239 async_answer_0(callid, rc); 1375 async_answer_0(rid, rc); 1376 return; 1377 } 1378 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL, 1240 return rc; 1241 } 1242 rc = _fat_block_get(&b, bs, service_id, lcl, NULL, 1379 1243 (pos / BPS(bs)) % SPC(bs), flags); 1380 1244 if (rc != EOK) { 1381 (void) fat_free_clusters(bs, devmap_handle, mcl);1245 (void) fat_free_clusters(bs, service_id, mcl); 1382 1246 (void) fat_node_put(fn); 1383 1247 async_answer_0(callid, rc); 1384 async_answer_0(rid, rc); 1385 return; 1248 return rc; 1386 1249 } 1387 1250 (void) async_data_write_finalize(callid, … … 1390 1253 rc = block_put(b); 1391 1254 if (rc != EOK) { 1392 (void) fat_free_clusters(bs, devmap_handle, mcl);1255 (void) fat_free_clusters(bs, service_id, mcl); 1393 1256 (void) fat_node_put(fn); 1394 async_answer_0(rid, rc); 1395 return; 1257 return rc; 1396 1258 } 1397 1259 /* … … 1401 1263 rc = fat_append_clusters(bs, nodep, mcl, lcl); 1402 1264 if (rc != EOK) { 1403 (void) fat_free_clusters(bs, devmap_handle, mcl);1265 (void) fat_free_clusters(bs, service_id, mcl); 1404 1266 (void) fat_node_put(fn); 1405 async_answer_0(rid, rc);1406 return;1407 }1408 nodep->size = size = pos + bytes;1267 return rc; 1268 } 1269 *nsize = nodep->size = pos + bytes; 1270 rc = fat_node_put(fn); 1409 1271 nodep->dirty = true; /* need to sync node */ 1410 rc = fat_node_put(fn); 1411 async_answer_2(rid, rc, bytes, size); 1412 return; 1413 } 1414 } 1415 1416 void fat_truncate(ipc_callid_t rid, ipc_call_t *request) 1417 { 1418 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1419 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1420 aoff64_t size = 1421 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 1272 *wbytes = bytes; 1273 return rc; 1274 } 1275 } 1276 1277 static int 1278 fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size) 1279 { 1422 1280 fs_node_t *fn; 1423 1281 fat_node_t *nodep; … … 1425 1283 int rc; 1426 1284 1427 rc = fat_node_get(&fn, devmap_handle, index); 1428 if (rc != EOK) { 1429 async_answer_0(rid, rc); 1430 return; 1431 } 1432 if (!fn) { 1433 async_answer_0(rid, ENOENT); 1434 return; 1435 } 1285 rc = fat_node_get(&fn, service_id, index); 1286 if (rc != EOK) 1287 return rc; 1288 if (!fn) 1289 return ENOENT; 1436 1290 nodep = FAT_NODE(fn); 1437 1291 1438 bs = block_bb_get( devmap_handle);1292 bs = block_bb_get(service_id); 1439 1293 1440 1294 if (nodep->size == size) { … … 1452 1306 nodep->size = size; 1453 1307 nodep->dirty = true; /* need to sync node */ 1454 rc = EOK; 1308 rc = EOK; 1455 1309 } else { 1456 1310 /* … … 1463 1317 } else { 1464 1318 fat_cluster_t lastc; 1465 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,1319 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 1466 1320 &lastc, NULL, (size - 1) / BPC(bs)); 1467 1321 if (rc != EOK) … … 1473 1327 nodep->size = size; 1474 1328 nodep->dirty = true; /* need to sync node */ 1475 rc = EOK; 1329 rc = EOK; 1476 1330 } 1477 1331 out: 1478 1332 fat_node_put(fn); 1479 async_answer_0(rid, rc); 1480 return; 1481 } 1482 1483 void fat_close(ipc_callid_t rid, ipc_call_t *request) 1484 { 1485 async_answer_0(rid, EOK); 1486 } 1487 1488 void fat_destroy(ipc_callid_t rid, ipc_call_t *request) 1489 { 1490 devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request); 1491 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1333 return rc; 1334 } 1335 1336 static int fat_close(service_id_t service_id, fs_index_t index) 1337 { 1338 return EOK; 1339 } 1340 1341 static int fat_destroy(service_id_t service_id, fs_index_t index) 1342 { 1492 1343 fs_node_t *fn; 1493 1344 fat_node_t *nodep; 1494 1345 int rc; 1495 1346 1496 rc = fat_node_get(&fn, devmap_handle, index); 1497 if (rc != EOK) { 1498 async_answer_0(rid, rc); 1499 return; 1500 } 1501 if (!fn) { 1502 async_answer_0(rid, ENOENT); 1503 return; 1504 } 1347 rc = fat_node_get(&fn, service_id, index); 1348 if (rc != EOK) 1349 return rc; 1350 if (!fn) 1351 return ENOENT; 1505 1352 1506 1353 nodep = FAT_NODE(fn); … … 1512 1359 1513 1360 rc = fat_destroy_node(fn); 1514 async_answer_0(rid, rc); 1515 } 1516 1517 void fat_open_node(ipc_callid_t rid, ipc_call_t *request) 1518 { 1519 libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1520 } 1521 1522 void fat_stat(ipc_callid_t rid, ipc_call_t *request) 1523 { 1524 libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request); 1525 } 1526 1527 void fat_sync(ipc_callid_t rid, ipc_call_t *request) 1528 { 1529 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 1530 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 1531 1361 return rc; 1362 } 1363 1364 static int fat_sync(service_id_t service_id, fs_index_t index) 1365 { 1532 1366 fs_node_t *fn; 1533 int rc = fat_node_get(&fn, devmap_handle, index); 1534 if (rc != EOK) { 1535 async_answer_0(rid, rc); 1536 return; 1537 } 1538 if (!fn) { 1539 async_answer_0(rid, ENOENT); 1540 return; 1541 } 1542 1367 int rc = fat_node_get(&fn, service_id, index); 1368 if (rc != EOK) 1369 return rc; 1370 if (!fn) 1371 return ENOENT; 1372 1543 1373 fat_node_t *nodep = FAT_NODE(fn); 1544 1374 1545 1375 nodep->dirty = true; 1546 1376 rc = fat_node_sync(nodep); 1547 1377 1548 1378 fat_node_put(fn); 1549 async_answer_0(rid, rc); 1550 } 1379 return rc; 1380 } 1381 1382 vfs_out_ops_t fat_ops = { 1383 .mounted = fat_mounted, 1384 .unmounted = fat_unmounted, 1385 .read = fat_read, 1386 .write = fat_write, 1387 .truncate = fat_truncate, 1388 .close = fat_close, 1389 .destroy = fat_destroy, 1390 .sync = fat_sync, 1391 }; 1551 1392 1552 1393 /**
Note:
See TracChangeset
for help on using the changeset viewer.