Changes in uspace/srv/fs/fat/fat_ops.c [c7bbf029:b69e4c0] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
rc7bbf029 rb69e4c0 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) … … 67 70 68 71 /** List of cached free FAT nodes. */ 69 static LIST_INITIALIZE(ffn_ head);72 static LIST_INITIALIZE(ffn_list); 70 73 71 74 /* 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) 148 { 149 link_t *lnk; 149 static int fat_node_fini_by_service_id(service_id_t service_id) 150 { 150 151 fat_node_t *nodep; 151 152 int rc; … … 159 160 restart: 160 161 fibril_mutex_lock(&ffn_mutex); 161 for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {162 list_foreach(ffn_list, lnk) { 162 163 nodep = list_get_instance(lnk, fat_node_t, ffn_link); 163 164 if (!fibril_mutex_trylock(&nodep->lock)) { … … 170 171 goto restart; 171 172 } 172 if (nodep->idx-> devmap_handle != devmap_handle) {173 if (nodep->idx->service_id != service_id) { 173 174 fibril_mutex_unlock(&nodep->idx->lock); 174 175 fibril_mutex_unlock(&nodep->lock); … … 196 197 free(nodep); 197 198 198 /* Need to restart because we changed the ffn_headlist. */199 /* Need to restart because we changed ffn_list. */ 199 200 goto restart; 200 201 } … … 211 212 212 213 fibril_mutex_lock(&ffn_mutex); 213 if (!list_empty(&ffn_ head)) {214 if (!list_empty(&ffn_list)) { 214 215 /* Try to use a cached free node structure. */ 215 216 fat_idx_t *idxp_tmp; 216 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link); 217 nodep = list_get_instance(list_first(&ffn_list), fat_node_t, 218 ffn_link); 217 219 if (!fibril_mutex_trylock(&nodep->lock)) 218 220 goto skip_cache; … … 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; … … 473 464 if (nodep->idx) { 474 465 fibril_mutex_lock(&ffn_mutex); 475 list_append(&nodep->ffn_link, &ffn_ head);466 list_append(&nodep->ffn_link, &ffn_list); 476 467 fibril_mutex_unlock(&ffn_mutex); 477 468 } else { … … 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);501 rc = fat_zero_cluster(bs, service_id, mcl); 511 502 if (rc != EOK) { 512 (void) fat_free_clusters(bs, devmap_handle, mcl);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); 951 enum cache_mode cmode; 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 { 873 enum cache_mode cmode = CACHE_MODE_WB; 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 875 fat_instance_t *instance; 876 int rc; 877 878 instance = malloc(sizeof(fat_instance_t)); 879 if (!instance) 880 return ENOMEM; 881 instance->lfn_enabled = true; 882 883 /* Parse mount options. */ 884 char *mntopts = (char *) opts; 885 char *saveptr; 886 char *opt; 887 while ((opt = strtok_r(mntopts, " ,", &saveptr)) != NULL) { 888 if (str_cmp(opt, "wtcache") == 0) 889 cmode = CACHE_MODE_WT; 890 else if (str_cmp(opt, "nolfn") == 0) 891 instance->lfn_enabled = false; 892 mntopts = NULL; 893 } 894 895 /* initialize libblock */ 896 rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE); 958 897 if (rc != EOK) { 959 async_answer_0(rid, rc); 960 return; 961 } 962 963 /* Check for option enabling write through. */ 964 if (str_cmp(opts, "wtcache") == 0) 965 cmode = CACHE_MODE_WT; 966 else 967 cmode = CACHE_MODE_WB; 968 969 free(opts); 970 971 /* initialize libblock */ 972 rc = block_init(devmap_handle, BS_SIZE); 898 free(instance); 899 return rc; 900 } 901 902 /* prepare the boot block */ 903 rc = block_bb_read(service_id, BS_BLOCK); 973 904 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; 905 free(instance); 906 block_fini(service_id); 907 return rc; 984 908 } 985 909 986 910 /* get the buffer with the boot sector */ 987 bs = block_bb_get( devmap_handle);911 bs = block_bb_get(service_id); 988 912 989 913 if (BPS(bs) != BS_SIZE) { 990 block_fini(devmap_handle);991 async_answer_0(rid, ENOTSUP);992 return ;914 free(instance); 915 block_fini(service_id); 916 return ENOTSUP; 993 917 } 994 918 995 919 /* Initialize the block cache */ 996 rc = block_cache_init( devmap_handle, BPS(bs), 0 /* XXX */, cmode);920 rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode); 997 921 if (rc != EOK) { 998 block_fini(devmap_handle);999 async_answer_0(rid, rc);1000 return ;922 free(instance); 923 block_fini(service_id); 924 return rc; 1001 925 } 1002 926 1003 927 /* Do some simple sanity checks on the file system. */ 1004 rc = fat_sanity_check(bs, devmap_handle);928 rc = fat_sanity_check(bs, service_id); 1005 929 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);930 free(instance); 931 (void) block_cache_fini(service_id); 932 block_fini(service_id); 933 return rc; 934 } 935 936 rc = fat_idx_init_by_service_id(service_id); 1013 937 if (rc != EOK) { 1014 (void) block_cache_fini(devmap_handle);1015 block_fini(devmap_handle);1016 async_answer_0(rid, rc);1017 return ;938 free(instance); 939 (void) block_cache_fini(service_id); 940 block_fini(service_id); 941 return rc; 1018 942 } 1019 943 … … 1021 945 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 1022 946 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 } 947 free(instance); 948 (void) block_cache_fini(service_id); 949 block_fini(service_id); 950 fat_idx_fini_by_service_id(service_id); 951 return ENOMEM; 952 } 953 1029 954 fs_node_initialize(rfn); 1030 955 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); 1031 956 if (!rootp) { 957 free(instance); 1032 958 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; 959 (void) block_cache_fini(service_id); 960 block_fini(service_id); 961 fat_idx_fini_by_service_id(service_id); 962 return ENOMEM; 1038 963 } 1039 964 fat_node_initialize(rootp); 1040 965 1041 fat_idx_t *ridxp = fat_idx_get_by_pos( devmap_handle, FAT_CLST_ROOTPAR, 0);966 fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0); 1042 967 if (!ridxp) { 968 free(instance); 1043 969 free(rfn); 1044 970 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; 971 (void) block_cache_fini(service_id); 972 block_fini(service_id); 973 fat_idx_fini_by_service_id(service_id); 974 return ENOMEM; 1050 975 } 1051 976 assert(ridxp->index == 0); … … 1053 978 1054 979 rootp->type = FAT_DIRECTORY; 1055 rootp->firstc = FAT_ CLST_ROOT;980 rootp->firstc = FAT_ROOT_CLST(bs); 1056 981 rootp->refcnt = 1; 1057 982 rootp->lnkcnt = 0; /* FS root is not linked */ 1058 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 983 984 if (FAT_IS_FAT32(bs)) { 985 uint32_t clusters; 986 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc); 987 if (rc != EOK) { 988 fibril_mutex_unlock(&ridxp->lock); 989 free(instance); 990 free(rfn); 991 free(rootp); 992 (void) block_cache_fini(service_id); 993 block_fini(service_id); 994 fat_idx_fini_by_service_id(service_id); 995 return ENOTSUP; 996 } 997 rootp->size = BPS(bs) * SPC(bs) * clusters; 998 } else 999 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 1000 1001 rc = fs_instance_create(service_id, instance); 1002 if (rc != EOK) { 1003 fibril_mutex_unlock(&ridxp->lock); 1004 free(instance); 1005 free(rfn); 1006 free(rootp); 1007 (void) block_cache_fini(service_id); 1008 block_fini(service_id); 1009 fat_idx_fini_by_service_id(service_id); 1010 return rc; 1011 } 1012 1059 1013 rootp->idx = ridxp; 1060 1014 ridxp->nodep = rootp; 1061 1015 rootp->bp = rfn; 1062 1016 rfn->data = rootp; 1063 1017 1064 1018 fibril_mutex_unlock(&ridxp->lock); 1065 1019 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); 1020 *index = ridxp->index; 1021 *size = rootp->size; 1022 *linkcnt = rootp->lnkcnt; 1023 1024 return EOK; 1025 } 1026 1027 static int fat_update_fat32_fsinfo(service_id_t service_id) 1028 { 1029 fat_bs_t *bs; 1030 fat32_fsinfo_t *info; 1031 block_t *b; 1032 int rc; 1033 1034 bs = block_bb_get(service_id); 1035 assert(FAT_IS_FAT32(bs)); 1036 1037 rc = block_get(&b, service_id, uint16_t_le2host(bs->fat32.fsinfo_sec), 1038 BLOCK_FLAGS_NONE); 1039 if (rc != EOK) 1040 return rc; 1041 1042 info = (fat32_fsinfo_t *) b->data; 1043 1044 if (bcmp(info->sig1, FAT32_FSINFO_SIG1, sizeof(info->sig1)) || 1045 bcmp(info->sig2, FAT32_FSINFO_SIG2, sizeof(info->sig2)) || 1046 bcmp(info->sig3, FAT32_FSINFO_SIG3, sizeof(info->sig3))) { 1047 (void) block_put(b); 1048 return EINVAL; 1049 } 1050 1051 /* For now, invalidate the counter. */ 1052 info->free_clusters = host2uint16_t_le(-1); 1053 1054 b->dirty = true; 1055 return block_put(b); 1056 } 1057 1058 static int fat_unmounted(service_id_t service_id) 1059 { 1077 1060 fs_node_t *fn; 1078 1061 fat_node_t *nodep; 1079 int rc; 1080 1081 rc = fat_root_get(&fn, devmap_handle); 1082 if (rc != EOK) { 1083 async_answer_0(rid, rc); 1084 return; 1085 } 1062 fat_bs_t *bs; 1063 int rc; 1064 1065 bs = block_bb_get(service_id); 1066 1067 rc = fat_root_get(&fn, service_id); 1068 if (rc != EOK) 1069 return rc; 1086 1070 nodep = FAT_NODE(fn); 1087 1071 … … 1092 1076 if (nodep->refcnt != 2) { 1093 1077 (void) fat_node_put(fn); 1094 async_answer_0(rid, EBUSY); 1095 return; 1096 } 1097 1078 return EBUSY; 1079 } 1080 1081 if (FAT_IS_FAT32(bs)) { 1082 /* 1083 * Attempt to update the FAT32 FS info. 1084 */ 1085 (void) fat_update_fat32_fsinfo(service_id); 1086 } 1087 1098 1088 /* 1099 1089 * Put the root node and force it to the FAT free node list. … … 1107 1097 * stop using libblock for this instance. 1108 1098 */ 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)); 1099 (void) fat_node_fini_by_service_id(service_id); 1100 fat_idx_fini_by_service_id(service_id); 1101 (void) block_cache_fini(service_id); 1102 block_fini(service_id); 1103 1104 void *data; 1105 if (fs_instance_get(service_id, &data) == EOK) { 1106 fs_instance_destroy(service_id); 1107 free(data); 1108 } 1109 1110 return EOK; 1111 } 1112 1113 static int 1114 fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos, 1115 size_t *rbytes) 1116 { 1133 1117 fs_node_t *fn; 1134 1118 fat_node_t *nodep; … … 1138 1122 int rc; 1139 1123 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 } 1124 rc = fat_node_get(&fn, service_id, index); 1125 if (rc != EOK) 1126 return rc; 1127 if (!fn) 1128 return ENOENT; 1149 1129 nodep = FAT_NODE(fn); 1150 1130 … … 1154 1134 fat_node_put(fn); 1155 1135 async_answer_0(callid, EINVAL); 1156 async_answer_0(rid, EINVAL); 1157 return; 1158 } 1159 1160 bs = block_bb_get(devmap_handle); 1136 return EINVAL; 1137 } 1138 1139 bs = block_bb_get(service_id); 1161 1140 1162 1141 if (nodep->type == FAT_FILE) { … … 1178 1157 fat_node_put(fn); 1179 1158 async_answer_0(callid, rc); 1180 async_answer_0(rid, rc); 1181 return; 1159 return rc; 1182 1160 } 1183 1161 (void) async_data_read_finalize(callid, … … 1186 1164 if (rc != EOK) { 1187 1165 fat_node_put(fn); 1188 async_answer_0(rid, rc); 1189 return; 1166 return rc; 1190 1167 } 1191 1168 } 1192 1169 } else { 1193 unsigned bnum;1194 1170 aoff64_t spos = pos; 1195 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1171 char name[FAT_LFN_NAME_SIZE]; 1196 1172 fat_dentry_t *d; 1197 1173 … … 1200 1176 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1201 1177 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; 1178 fat_directory_t di; 1179 rc = fat_directory_open(nodep, &di); 1180 if (rc != EOK) 1181 goto err; 1182 rc = fat_directory_seek(&di, pos); 1183 if (rc != EOK) { 1184 (void) fat_directory_close(&di); 1185 goto err; 1186 } 1187 1188 rc = fat_directory_read(&di, name, &d); 1189 if (rc == EOK) 1190 goto hit; 1191 if (rc == ENOENT) 1192 goto miss; 1248 1193 1249 1194 err: 1250 1195 (void) fat_node_put(fn); 1251 1196 async_answer_0(callid, rc); 1252 async_answer_0(rid, rc); 1253 return; 1197 return rc; 1198 1199 miss: 1200 rc = fat_directory_close(&di); 1201 if (rc != EOK) 1202 goto err; 1203 rc = fat_node_put(fn); 1204 async_answer_0(callid, rc != EOK ? rc : ENOENT); 1205 *rbytes = 0; 1206 return rc != EOK ? rc : ENOENT; 1254 1207 1255 1208 hit: 1256 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1209 pos = di.pos; 1210 rc = fat_directory_close(&di); 1211 if (rc != EOK) 1212 goto err; 1213 (void) async_data_read_finalize(callid, name, 1214 str_size(name) + 1); 1257 1215 bytes = (pos - spos) + 1; 1258 1216 } 1259 1217 1260 1218 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)); 1219 *rbytes = bytes; 1220 return rc; 1221 } 1222 1223 static int 1224 fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos, 1225 size_t *wbytes, aoff64_t *nsize) 1226 { 1270 1227 fs_node_t *fn; 1271 1228 fat_node_t *nodep; 1272 1229 fat_bs_t *bs; 1273 size_t bytes , size;1230 size_t bytes; 1274 1231 block_t *b; 1275 1232 aoff64_t boundary; … … 1277 1234 int rc; 1278 1235 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 } 1236 rc = fat_node_get(&fn, service_id, index); 1237 if (rc != EOK) 1238 return rc; 1239 if (!fn) 1240 return ENOENT; 1288 1241 nodep = FAT_NODE(fn); 1289 1242 1290 1243 ipc_callid_t callid; 1291 1244 size_t len; … … 1293 1246 (void) fat_node_put(fn); 1294 1247 async_answer_0(callid, EINVAL); 1295 async_answer_0(rid, EINVAL); 1296 return; 1297 } 1298 1299 bs = block_bb_get(devmap_handle); 1248 return EINVAL; 1249 } 1250 1251 bs = block_bb_get(service_id); 1300 1252 1301 1253 /* … … 1304 1256 * but this one greatly simplifies fat_write(). Note that we can afford 1305 1257 * to do this because the client must be ready to handle the return 1306 * value signalizing a smaller number of bytes written. 1307 */ 1258 * value signalizing a smaller number of bytes written. 1259 */ 1308 1260 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1309 1261 if (bytes == BPS(bs)) 1310 1262 flags |= BLOCK_FLAGS_NOREAD; 1311 1263 1312 1264 boundary = ROUND_UP(nodep->size, BPC(bs)); 1313 1265 if (pos < boundary) { … … 1322 1274 (void) fat_node_put(fn); 1323 1275 async_answer_0(callid, rc); 1324 async_answer_0(rid, rc); 1325 return; 1276 return rc; 1326 1277 } 1327 1278 rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags); … … 1329 1280 (void) fat_node_put(fn); 1330 1281 async_answer_0(callid, rc); 1331 async_answer_0(rid, rc); 1332 return; 1282 return rc; 1333 1283 } 1334 1284 (void) async_data_write_finalize(callid, … … 1338 1288 if (rc != EOK) { 1339 1289 (void) fat_node_put(fn); 1340 async_answer_0(rid, rc); 1341 return; 1290 return rc; 1342 1291 } 1343 1292 if (pos + bytes > nodep->size) { … … 1345 1294 nodep->dirty = true; /* need to sync node */ 1346 1295 } 1347 size = nodep->size; 1296 *wbytes = bytes; 1297 *nsize = nodep->size; 1348 1298 rc = fat_node_put(fn); 1349 async_answer_2(rid, rc, bytes, nodep->size); 1350 return; 1299 return rc; 1351 1300 } else { 1352 1301 /* … … 1355 1304 */ 1356 1305 unsigned nclsts; 1357 fat_cluster_t mcl, lcl; 1358 1306 fat_cluster_t mcl, lcl; 1307 1359 1308 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1360 1309 /* create an independent chain of nclsts clusters in all FATs */ 1361 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);1310 rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl); 1362 1311 if (rc != EOK) { 1363 1312 /* could not allocate a chain of nclsts clusters */ 1364 1313 (void) fat_node_put(fn); 1365 1314 async_answer_0(callid, rc); 1366 async_answer_0(rid, rc); 1367 return; 1315 return rc; 1368 1316 } 1369 1317 /* zero fill any gaps */ 1370 1318 rc = fat_fill_gap(bs, nodep, mcl, pos); 1371 1319 if (rc != EOK) { 1372 (void) fat_free_clusters(bs, devmap_handle, mcl);1320 (void) fat_free_clusters(bs, service_id, mcl); 1373 1321 (void) fat_node_put(fn); 1374 1322 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, 1323 return rc; 1324 } 1325 rc = _fat_block_get(&b, bs, service_id, lcl, NULL, 1379 1326 (pos / BPS(bs)) % SPC(bs), flags); 1380 1327 if (rc != EOK) { 1381 (void) fat_free_clusters(bs, devmap_handle, mcl);1328 (void) fat_free_clusters(bs, service_id, mcl); 1382 1329 (void) fat_node_put(fn); 1383 1330 async_answer_0(callid, rc); 1384 async_answer_0(rid, rc); 1385 return; 1331 return rc; 1386 1332 } 1387 1333 (void) async_data_write_finalize(callid, … … 1390 1336 rc = block_put(b); 1391 1337 if (rc != EOK) { 1392 (void) fat_free_clusters(bs, devmap_handle, mcl);1338 (void) fat_free_clusters(bs, service_id, mcl); 1393 1339 (void) fat_node_put(fn); 1394 async_answer_0(rid, rc); 1395 return; 1340 return rc; 1396 1341 } 1397 1342 /* … … 1401 1346 rc = fat_append_clusters(bs, nodep, mcl, lcl); 1402 1347 if (rc != EOK) { 1403 (void) fat_free_clusters(bs, devmap_handle, mcl);1348 (void) fat_free_clusters(bs, service_id, mcl); 1404 1349 (void) fat_node_put(fn); 1405 async_answer_0(rid, rc);1406 return;1407 }1408 nodep->size = size = pos + bytes;1350 return rc; 1351 } 1352 *nsize = nodep->size = pos + bytes; 1353 rc = fat_node_put(fn); 1409 1354 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)); 1355 *wbytes = bytes; 1356 return rc; 1357 } 1358 } 1359 1360 static int 1361 fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size) 1362 { 1422 1363 fs_node_t *fn; 1423 1364 fat_node_t *nodep; … … 1425 1366 int rc; 1426 1367 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 } 1368 rc = fat_node_get(&fn, service_id, index); 1369 if (rc != EOK) 1370 return rc; 1371 if (!fn) 1372 return ENOENT; 1436 1373 nodep = FAT_NODE(fn); 1437 1374 1438 bs = block_bb_get( devmap_handle);1375 bs = block_bb_get(service_id); 1439 1376 1440 1377 if (nodep->size == size) { … … 1452 1389 nodep->size = size; 1453 1390 nodep->dirty = true; /* need to sync node */ 1454 rc = EOK; 1391 rc = EOK; 1455 1392 } else { 1456 1393 /* … … 1463 1400 } else { 1464 1401 fat_cluster_t lastc; 1465 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,1402 rc = fat_cluster_walk(bs, service_id, nodep->firstc, 1466 1403 &lastc, NULL, (size - 1) / BPC(bs)); 1467 1404 if (rc != EOK) … … 1473 1410 nodep->size = size; 1474 1411 nodep->dirty = true; /* need to sync node */ 1475 rc = EOK; 1412 rc = EOK; 1476 1413 } 1477 1414 out: 1478 1415 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); 1416 return rc; 1417 } 1418 1419 static int fat_close(service_id_t service_id, fs_index_t index) 1420 { 1421 return EOK; 1422 } 1423 1424 static int fat_destroy(service_id_t service_id, fs_index_t index) 1425 { 1492 1426 fs_node_t *fn; 1493 1427 fat_node_t *nodep; 1494 1428 int rc; 1495 1429 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 } 1430 rc = fat_node_get(&fn, service_id, index); 1431 if (rc != EOK) 1432 return rc; 1433 if (!fn) 1434 return ENOENT; 1505 1435 1506 1436 nodep = FAT_NODE(fn); … … 1512 1442 1513 1443 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 1444 return rc; 1445 } 1446 1447 static int fat_sync(service_id_t service_id, fs_index_t index) 1448 { 1532 1449 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 1450 int rc = fat_node_get(&fn, service_id, index); 1451 if (rc != EOK) 1452 return rc; 1453 if (!fn) 1454 return ENOENT; 1455 1543 1456 fat_node_t *nodep = FAT_NODE(fn); 1544 1457 1545 1458 nodep->dirty = true; 1546 1459 rc = fat_node_sync(nodep); 1547 1460 1548 1461 fat_node_put(fn); 1549 async_answer_0(rid, rc); 1550 } 1462 return rc; 1463 } 1464 1465 vfs_out_ops_t fat_ops = { 1466 .mounted = fat_mounted, 1467 .unmounted = fat_unmounted, 1468 .read = fat_read, 1469 .write = fat_write, 1470 .truncate = fat_truncate, 1471 .close = fat_close, 1472 .destroy = fat_destroy, 1473 .sync = fat_sync, 1474 }; 1551 1475 1552 1476 /**
Note:
See TracChangeset
for help on using the changeset viewer.