Changes in uspace/srv/fs/fat/fat_ops.c [0be611b:efcebe1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
r0be611b refcebe1 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 30 29 /** @addtogroup fs 31 30 * @{ 32 */ 31 */ 33 32 34 33 /** … … 40 39 #include "fat_dentry.h" 41 40 #include "fat_fat.h" 42 #include "fat_directory.h"43 41 #include "../../vfs/vfs.h" 44 42 #include <libfs.h> 45 43 #include <libblock.h> 46 44 #include <ipc/services.h> 47 #include <ipc/ loc.h>45 #include <ipc/devmap.h> 48 46 #include <macros.h> 49 47 #include <async.h> … … 58 56 #include <align.h> 59 57 #include <malloc.h> 60 #include <str.h>61 58 62 59 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 75 72 * Forward declarations of FAT libfs operations. 76 73 */ 77 static int fat_root_get(fs_node_t **, service_id_t);74 static int fat_root_get(fs_node_t **, devmap_handle_t); 78 75 static int fat_match(fs_node_t **, fs_node_t *, const char *); 79 static int fat_node_get(fs_node_t **, service_id_t, fs_index_t);76 static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t); 80 77 static int fat_node_open(fs_node_t *); 81 78 static int fat_node_put(fs_node_t *); 82 static int fat_create_node(fs_node_t **, service_id_t, int);79 static int fat_create_node(fs_node_t **, devmap_handle_t, int); 83 80 static int fat_destroy_node(fs_node_t *); 84 81 static int fat_link(fs_node_t *, fs_node_t *, const char *); … … 90 87 static bool fat_is_directory(fs_node_t *); 91 88 static bool fat_is_file(fs_node_t *node); 92 static service_id_t fat_device_get(fs_node_t *node);89 static devmap_handle_t fat_device_get(fs_node_t *node); 93 90 94 91 /* … … 107 104 node->dirty = false; 108 105 node->lastc_cached_valid = false; 109 node->lastc_cached_value = 0;106 node->lastc_cached_value = FAT_CLST_LAST1; 110 107 node->currc_cached_valid = false; 111 108 node->currc_cached_bn = 0; 112 node->currc_cached_value = 0;109 node->currc_cached_value = FAT_CLST_LAST1; 113 110 } 114 111 … … 119 116 fat_dentry_t *d; 120 117 int rc; 121 118 122 119 assert(node->dirty); 123 120 124 bs = block_bb_get(node->idx-> service_id);125 121 bs = block_bb_get(node->idx->devmap_handle); 122 126 123 /* Read the block that contains the dentry of interest. */ 127 rc = _fat_block_get(&b, bs, node->idx-> service_id, node->idx->pfc,124 rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc, 128 125 NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 129 126 BLOCK_FLAGS_NONE); … … 139 136 d->attr = FAT_ATTR_SUBDIR; 140 137 } 141 138 142 139 /* TODO: update other fields? (e.g time fields) */ 143 140 144 141 b->dirty = true; /* need to sync block */ 145 142 rc = block_put(b); … … 147 144 } 148 145 149 static int fat_node_fini_by_ service_id(service_id_t service_id)146 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle) 150 147 { 151 148 fat_node_t *nodep; … … 171 168 goto restart; 172 169 } 173 if (nodep->idx-> service_id != service_id) {170 if (nodep->idx->devmap_handle != devmap_handle) { 174 171 fibril_mutex_unlock(&nodep->idx->lock); 175 172 fibril_mutex_unlock(&nodep->lock); … … 258 255 fn->data = nodep; 259 256 nodep->bp = fn; 260 257 261 258 *nodepp = nodep; 262 259 return EOK; … … 294 291 * We must instantiate the node from the file system. 295 292 */ 296 293 297 294 assert(idxp->pfc); 298 295 … … 301 298 return rc; 302 299 303 bs = block_bb_get(idxp-> service_id);300 bs = block_bb_get(idxp->devmap_handle); 304 301 305 302 /* Read the block that contains the dentry of interest. */ 306 rc = _fat_block_get(&b, bs, idxp-> service_id, idxp->pfc, NULL,303 rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL, 307 304 (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE); 308 305 if (rc != EOK) { … … 312 309 313 310 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 } else318 nodep->firstc = uint16_t_le2host(d->firstc);319 320 311 if (d->attr & FAT_ATTR_SUBDIR) { 321 /* 312 /* 322 313 * The only directory which does not have this bit set is the 323 314 * root directory itself. The root directory node is handled … … 325 316 */ 326 317 nodep->type = FAT_DIRECTORY; 327 328 318 /* 329 319 * Unfortunately, the 'size' field of the FAT dentry is not … … 331 321 * size of the directory by walking the FAT. 332 322 */ 333 uint 32_t clusters;334 rc = fat_clusters_get(&clusters, bs, idxp-> service_id,335 nodep->firstc);323 uint16_t clusters; 324 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, 325 uint16_t_le2host(d->firstc)); 336 326 if (rc != EOK) { 337 327 (void) block_put(b); … … 344 334 nodep->size = uint32_t_le2host(d->size); 345 335 } 346 336 nodep->firstc = uint16_t_le2host(d->firstc); 347 337 nodep->lnkcnt = 1; 348 338 nodep->refcnt = 1; … … 366 356 */ 367 357 368 int fat_root_get(fs_node_t **rfn, service_id_t service_id)369 { 370 return fat_node_get(rfn, service_id, 0);358 int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle) 359 { 360 return fat_node_get(rfn, devmap_handle, 0); 371 361 } 372 362 373 363 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 374 364 { 365 fat_bs_t *bs; 375 366 fat_node_t *parentp = FAT_NODE(pfn); 376 char name[FAT_LFN_NAME_SIZE]; 367 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 368 unsigned i, j; 369 unsigned blocks; 377 370 fat_dentry_t *d; 378 service_id_t service_id; 371 devmap_handle_t devmap_handle; 372 block_t *b; 379 373 int rc; 380 374 381 375 fibril_mutex_lock(&parentp->idx->lock); 382 service_id = parentp->idx->service_id;376 devmap_handle = parentp->idx->devmap_handle; 383 377 fibril_mutex_unlock(&parentp->idx->lock); 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; 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; 405 400 } 406 rc = fat_node_get_core(&nodep, idx); 407 fibril_mutex_unlock(&idx->lock); 408 if (rc != EOK) { 409 (void) fat_directory_close(&di); 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); 410 424 return rc; 411 425 } 412 *rfn = FS_NODE(nodep); 413 rc = fat_directory_close(&di); 414 if (rc != EOK) 415 (void) fat_node_put(*rfn); 416 return rc; 417 } else { 418 rc = fat_directory_next(&di); 419 if (rc != EOK) 420 break; 421 } 422 } 423 (void) fat_directory_close(&di); 426 } 427 rc = block_put(b); 428 if (rc != EOK) 429 return rc; 430 } 431 424 432 *rfn = NULL; 425 433 return EOK; … … 427 435 428 436 /** Instantiate a FAT in-core node. */ 429 int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)437 int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index) 430 438 { 431 439 fat_node_t *nodep; … … 433 441 int rc; 434 442 435 idxp = fat_idx_get_by_index( service_id, index);443 idxp = fat_idx_get_by_index(devmap_handle, index); 436 444 if (!idxp) { 437 445 *rfn = NULL; … … 484 492 } 485 493 486 int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags)494 int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags) 487 495 { 488 496 fat_idx_t *idxp; … … 492 500 int rc; 493 501 494 bs = block_bb_get( service_id);502 bs = block_bb_get(devmap_handle); 495 503 if (flags & L_DIRECTORY) { 496 504 /* allocate a cluster */ 497 rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl);505 rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl); 498 506 if (rc != EOK) 499 507 return rc; 500 508 /* populate the new cluster with unused dentries */ 501 rc = fat_zero_cluster(bs, service_id, mcl);509 rc = fat_zero_cluster(bs, devmap_handle, mcl); 502 510 if (rc != EOK) { 503 (void) fat_free_clusters(bs, service_id, mcl);511 (void) fat_free_clusters(bs, devmap_handle, mcl); 504 512 return rc; 505 513 } … … 508 516 rc = fat_node_get_new(&nodep); 509 517 if (rc != EOK) { 510 (void) fat_free_clusters(bs, service_id, mcl);511 return rc; 512 } 513 rc = fat_idx_get_new(&idxp, service_id);518 (void) fat_free_clusters(bs, devmap_handle, mcl); 519 return rc; 520 } 521 rc = fat_idx_get_new(&idxp, devmap_handle); 514 522 if (rc != EOK) { 515 (void) fat_free_clusters(bs, service_id, mcl);523 (void) fat_free_clusters(bs, devmap_handle, mcl); 516 524 (void) fat_node_put(FS_NODE(nodep)); 517 525 return rc; … … 562 570 assert(!has_children); 563 571 564 bs = block_bb_get(nodep->idx-> service_id);572 bs = block_bb_get(nodep->idx->devmap_handle); 565 573 if (nodep->firstc != FAT_CLST_RES0) { 566 574 assert(nodep->size); 567 575 /* Free all clusters allocated to the node. */ 568 rc = fat_free_clusters(bs, nodep->idx-> service_id,576 rc = fat_free_clusters(bs, nodep->idx->devmap_handle, 569 577 nodep->firstc); 570 578 } … … 583 591 fat_bs_t *bs; 584 592 block_t *b; 585 fat_directory_t di; 586 fat_dentry_t de; 593 unsigned i, j; 594 unsigned blocks; 595 fat_cluster_t mcl, lcl; 587 596 int rc; 588 597 … … 598 607 fibril_mutex_unlock(&childp->lock); 599 608 600 if (!fat_valid_name(name)) 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 601 613 return ENOTSUP; 602 614 } 615 616 /* 617 * Get us an unused parent node's dentry or grow the parent and allocate 618 * a new one. 619 */ 620 603 621 fibril_mutex_lock(&parentp->idx->lock); 604 bs = block_bb_get(parentp->idx->service_id); 605 rc = fat_directory_open(parentp, &di); 622 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); 606 662 if (rc != EOK) { 607 663 fibril_mutex_unlock(&parentp->idx->lock); 608 664 return rc; 609 665 } 610 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: 611 688 /* 612 689 * At this point we only establish the link between the parent and the … … 615 692 * dentry data is kept in the child node structure. 616 693 */ 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 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); 631 698 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK) 700 return rc; 632 701 633 702 fibril_mutex_lock(&childp->idx->lock); 634 703 635 704 if (childp->type == FAT_DIRECTORY) { 636 705 /* … … 651 720 d = (fat_dentry_t *) b->data; 652 721 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 653 ( bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {722 (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) { 654 723 memset(d, 0, sizeof(fat_dentry_t)); 655 724 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 661 730 d++; 662 731 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 663 ( bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {732 (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) { 664 733 memset(d, 0, sizeof(fat_dentry_t)); 665 734 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 666 735 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 667 736 d->attr = FAT_ATTR_SUBDIR; 668 d->firstc = (parentp->firstc == FAT_ ROOT_CLST(bs)) ?669 host2uint16_t_le(FAT_CLST_R OOTPAR) :737 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 738 host2uint16_t_le(FAT_CLST_RES0) : 670 739 host2uint16_t_le(parentp->firstc); 671 740 /* TODO: initialize also the date/time members. */ … … 681 750 682 751 childp->idx->pfc = parentp->firstc; 683 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */752 childp->idx->pdi = i * DPS(bs) + j; 684 753 fibril_mutex_unlock(&childp->idx->lock); 685 754 … … 701 770 fat_node_t *parentp = FAT_NODE(pfn); 702 771 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs; 773 fat_dentry_t *d; 774 block_t *b; 703 775 bool has_children; 704 776 int rc; … … 706 778 if (!parentp) 707 779 return EBUSY; 708 780 709 781 rc = fat_has_children(&has_children, cfn); 710 782 if (rc != EOK) … … 717 789 assert(childp->lnkcnt == 1); 718 790 fibril_mutex_lock(&childp->idx->lock); 719 720 fat_directory_t di; 721 rc = fat_directory_open(parentp, &di); 722 if (rc != EOK) 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) 723 797 goto error; 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); 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); 731 804 if (rc != EOK) 732 805 goto error; … … 747 820 748 821 error: 749 (void) fat_directory_close(&di); 822 fibril_mutex_unlock(&parentp->idx->lock); 823 fibril_mutex_unlock(&childp->lock); 750 824 fibril_mutex_unlock(&childp->idx->lock); 751 fibril_mutex_unlock(&childp->lock);752 fibril_mutex_unlock(&parentp->lock);753 825 return rc; 754 826 } … … 767 839 return EOK; 768 840 } 769 841 770 842 fibril_mutex_lock(&nodep->idx->lock); 771 bs = block_bb_get(nodep->idx-> service_id);843 bs = block_bb_get(nodep->idx->devmap_handle); 772 844 773 845 blocks = nodep->size / BPS(bs); … … 775 847 for (i = 0; i < blocks; i++) { 776 848 fat_dentry_t *d; 777 849 778 850 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 779 851 if (rc != EOK) { … … 803 875 if (rc != EOK) { 804 876 fibril_mutex_unlock(&nodep->idx->lock); 805 return rc; 877 return rc; 806 878 } 807 879 } … … 838 910 } 839 911 840 service_id_t fat_device_get(fs_node_t *node)912 devmap_handle_t fat_device_get(fs_node_t *node) 841 913 { 842 914 return 0; … … 868 940 869 941 static int 870 fat_mounted( service_id_t service_id, const char *opts, fs_index_t *index,942 fat_mounted(devmap_handle_t devmap_handle, const char *opts, fs_index_t *index, 871 943 aoff64_t *size, unsigned *linkcnt) 872 944 { … … 874 946 fat_bs_t *bs; 875 947 int rc; 876 948 877 949 /* Check for option enabling write through. */ 878 950 if (str_cmp(opts, "wtcache") == 0) … … 882 954 883 955 /* initialize libblock */ 884 rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);956 rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE); 885 957 if (rc != EOK) 886 958 return rc; 887 959 888 960 /* prepare the boot block */ 889 rc = block_bb_read( service_id, BS_BLOCK);961 rc = block_bb_read(devmap_handle, BS_BLOCK); 890 962 if (rc != EOK) { 891 block_fini( service_id);963 block_fini(devmap_handle); 892 964 return rc; 893 965 } 894 966 895 967 /* get the buffer with the boot sector */ 896 bs = block_bb_get( service_id);968 bs = block_bb_get(devmap_handle); 897 969 898 970 if (BPS(bs) != BS_SIZE) { 899 block_fini( service_id);971 block_fini(devmap_handle); 900 972 return ENOTSUP; 901 973 } 902 974 903 975 /* Initialize the block cache */ 904 rc = block_cache_init( service_id, BPS(bs), 0 /* XXX */, cmode);976 rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode); 905 977 if (rc != EOK) { 906 block_fini( service_id);978 block_fini(devmap_handle); 907 979 return rc; 908 980 } 909 981 910 982 /* Do some simple sanity checks on the file system. */ 911 rc = fat_sanity_check(bs, service_id);983 rc = fat_sanity_check(bs, devmap_handle); 912 984 if (rc != EOK) { 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);985 (void) block_cache_fini(devmap_handle); 986 block_fini(devmap_handle); 987 return rc; 988 } 989 990 rc = fat_idx_init_by_devmap_handle(devmap_handle); 919 991 if (rc != EOK) { 920 (void) block_cache_fini( service_id);921 block_fini( service_id);992 (void) block_cache_fini(devmap_handle); 993 block_fini(devmap_handle); 922 994 return rc; 923 995 } … … 926 998 fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t)); 927 999 if (!rfn) { 928 (void) block_cache_fini( service_id);929 block_fini( service_id);930 fat_idx_fini_by_ service_id(service_id);1000 (void) block_cache_fini(devmap_handle); 1001 block_fini(devmap_handle); 1002 fat_idx_fini_by_devmap_handle(devmap_handle); 931 1003 return ENOMEM; 932 1004 } 933 934 1005 fs_node_initialize(rfn); 935 1006 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); 936 1007 if (!rootp) { 937 1008 free(rfn); 938 (void) block_cache_fini( service_id);939 block_fini( service_id);940 fat_idx_fini_by_ service_id(service_id);1009 (void) block_cache_fini(devmap_handle); 1010 block_fini(devmap_handle); 1011 fat_idx_fini_by_devmap_handle(devmap_handle); 941 1012 return ENOMEM; 942 1013 } 943 1014 fat_node_initialize(rootp); 944 1015 945 fat_idx_t *ridxp = fat_idx_get_by_pos( service_id, FAT_CLST_ROOTPAR, 0);1016 fat_idx_t *ridxp = fat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0); 946 1017 if (!ridxp) { 947 1018 free(rfn); 948 1019 free(rootp); 949 (void) block_cache_fini( service_id);950 block_fini( service_id);951 fat_idx_fini_by_ service_id(service_id);1020 (void) block_cache_fini(devmap_handle); 1021 block_fini(devmap_handle); 1022 fat_idx_fini_by_devmap_handle(devmap_handle); 952 1023 return ENOMEM; 953 1024 } … … 956 1027 957 1028 rootp->type = FAT_DIRECTORY; 958 rootp->firstc = FAT_ ROOT_CLST(bs);1029 rootp->firstc = FAT_CLST_ROOT; 959 1030 rootp->refcnt = 1; 960 1031 rootp->lnkcnt = 0; /* FS root is not linked */ 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 1032 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 977 1033 rootp->idx = ridxp; 978 1034 ridxp->nodep = rootp; 979 1035 rootp->bp = rfn; 980 1036 rfn->data = rootp; 981 1037 982 1038 fibril_mutex_unlock(&ridxp->lock); 983 1039 … … 989 1045 } 990 1046 991 static int fat_unmounted( service_id_t service_id)1047 static int fat_unmounted(devmap_handle_t devmap_handle) 992 1048 { 993 1049 fs_node_t *fn; … … 995 1051 int rc; 996 1052 997 rc = fat_root_get(&fn, service_id);1053 rc = fat_root_get(&fn, devmap_handle); 998 1054 if (rc != EOK) 999 1055 return rc; … … 1008 1064 return EBUSY; 1009 1065 } 1010 1066 1011 1067 /* 1012 1068 * Put the root node and force it to the FAT free node list. … … 1020 1076 * stop using libblock for this instance. 1021 1077 */ 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);1078 (void) fat_node_fini_by_devmap_handle(devmap_handle); 1079 fat_idx_fini_by_devmap_handle(devmap_handle); 1080 (void) block_cache_fini(devmap_handle); 1081 block_fini(devmap_handle); 1026 1082 1027 1083 return EOK; … … 1029 1085 1030 1086 static int 1031 fat_read( service_id_t service_id, fs_index_t index, aoff64_t pos,1087 fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos, 1032 1088 size_t *rbytes) 1033 1089 { … … 1039 1095 int rc; 1040 1096 1041 rc = fat_node_get(&fn, service_id, index);1097 rc = fat_node_get(&fn, devmap_handle, index); 1042 1098 if (rc != EOK) 1043 1099 return rc; … … 1054 1110 } 1055 1111 1056 bs = block_bb_get( service_id);1112 bs = block_bb_get(devmap_handle); 1057 1113 1058 1114 if (nodep->type == FAT_FILE) { … … 1085 1141 } 1086 1142 } else { 1143 unsigned bnum; 1087 1144 aoff64_t spos = pos; 1088 char name[FAT_ LFN_NAME_SIZE];1145 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 1089 1146 fat_dentry_t *d; 1090 1147 … … 1093 1150 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1094 1151 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; 1110 1111 err: 1112 (void) fat_node_put(fn); 1113 async_answer_0(callid, rc); 1114 return rc; 1115 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 } 1116 1193 miss: 1117 rc = fat_directory_close(&di);1118 if (rc != EOK)1119 goto err;1120 1194 rc = fat_node_put(fn); 1121 1195 async_answer_0(callid, rc != EOK ? rc : ENOENT); … … 1123 1197 return rc != EOK ? rc : ENOENT; 1124 1198 1199 err: 1200 (void) fat_node_put(fn); 1201 async_answer_0(callid, rc); 1202 return rc; 1203 1125 1204 hit: 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); 1205 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1132 1206 bytes = (pos - spos) + 1; 1133 1207 } … … 1139 1213 1140 1214 static int 1141 fat_write( service_id_t service_id, fs_index_t index, aoff64_t pos,1215 fat_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos, 1142 1216 size_t *wbytes, aoff64_t *nsize) 1143 1217 { … … 1151 1225 int rc; 1152 1226 1153 rc = fat_node_get(&fn, service_id, index);1227 rc = fat_node_get(&fn, devmap_handle, index); 1154 1228 if (rc != EOK) 1155 1229 return rc; … … 1157 1231 return ENOENT; 1158 1232 nodep = FAT_NODE(fn); 1159 1233 1160 1234 ipc_callid_t callid; 1161 1235 size_t len; … … 1166 1240 } 1167 1241 1168 bs = block_bb_get( service_id);1242 bs = block_bb_get(devmap_handle); 1169 1243 1170 1244 /* … … 1173 1247 * but this one greatly simplifies fat_write(). Note that we can afford 1174 1248 * to do this because the client must be ready to handle the return 1175 * value signalizing a smaller number of bytes written. 1176 */ 1249 * value signalizing a smaller number of bytes written. 1250 */ 1177 1251 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1178 1252 if (bytes == BPS(bs)) 1179 1253 flags |= BLOCK_FLAGS_NOREAD; 1180 1254 1181 1255 boundary = ROUND_UP(nodep->size, BPC(bs)); 1182 1256 if (pos < boundary) { … … 1221 1295 */ 1222 1296 unsigned nclsts; 1223 fat_cluster_t mcl, lcl; 1224 1297 fat_cluster_t mcl, lcl; 1298 1225 1299 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1226 1300 /* create an independent chain of nclsts clusters in all FATs */ 1227 rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl);1301 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl); 1228 1302 if (rc != EOK) { 1229 1303 /* could not allocate a chain of nclsts clusters */ … … 1235 1309 rc = fat_fill_gap(bs, nodep, mcl, pos); 1236 1310 if (rc != EOK) { 1237 (void) fat_free_clusters(bs, service_id, mcl);1311 (void) fat_free_clusters(bs, devmap_handle, mcl); 1238 1312 (void) fat_node_put(fn); 1239 1313 async_answer_0(callid, rc); 1240 1314 return rc; 1241 1315 } 1242 rc = _fat_block_get(&b, bs, service_id, lcl, NULL,1316 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL, 1243 1317 (pos / BPS(bs)) % SPC(bs), flags); 1244 1318 if (rc != EOK) { 1245 (void) fat_free_clusters(bs, service_id, mcl);1319 (void) fat_free_clusters(bs, devmap_handle, mcl); 1246 1320 (void) fat_node_put(fn); 1247 1321 async_answer_0(callid, rc); … … 1253 1327 rc = block_put(b); 1254 1328 if (rc != EOK) { 1255 (void) fat_free_clusters(bs, service_id, mcl);1329 (void) fat_free_clusters(bs, devmap_handle, mcl); 1256 1330 (void) fat_node_put(fn); 1257 1331 return rc; … … 1263 1337 rc = fat_append_clusters(bs, nodep, mcl, lcl); 1264 1338 if (rc != EOK) { 1265 (void) fat_free_clusters(bs, service_id, mcl);1339 (void) fat_free_clusters(bs, devmap_handle, mcl); 1266 1340 (void) fat_node_put(fn); 1267 1341 return rc; … … 1276 1350 1277 1351 static int 1278 fat_truncate( service_id_t service_id, fs_index_t index, aoff64_t size)1352 fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size) 1279 1353 { 1280 1354 fs_node_t *fn; … … 1283 1357 int rc; 1284 1358 1285 rc = fat_node_get(&fn, service_id, index);1359 rc = fat_node_get(&fn, devmap_handle, index); 1286 1360 if (rc != EOK) 1287 1361 return rc; … … 1290 1364 nodep = FAT_NODE(fn); 1291 1365 1292 bs = block_bb_get( service_id);1366 bs = block_bb_get(devmap_handle); 1293 1367 1294 1368 if (nodep->size == size) { … … 1306 1380 nodep->size = size; 1307 1381 nodep->dirty = true; /* need to sync node */ 1308 rc = EOK; 1382 rc = EOK; 1309 1383 } else { 1310 1384 /* … … 1317 1391 } else { 1318 1392 fat_cluster_t lastc; 1319 rc = fat_cluster_walk(bs, service_id, nodep->firstc,1393 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc, 1320 1394 &lastc, NULL, (size - 1) / BPC(bs)); 1321 1395 if (rc != EOK) … … 1327 1401 nodep->size = size; 1328 1402 nodep->dirty = true; /* need to sync node */ 1329 rc = EOK; 1403 rc = EOK; 1330 1404 } 1331 1405 out: … … 1334 1408 } 1335 1409 1336 static int fat_close( service_id_t service_id, fs_index_t index)1410 static int fat_close(devmap_handle_t devmap_handle, fs_index_t index) 1337 1411 { 1338 1412 return EOK; 1339 1413 } 1340 1414 1341 static int fat_destroy( service_id_t service_id, fs_index_t index)1415 static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index) 1342 1416 { 1343 1417 fs_node_t *fn; … … 1345 1419 int rc; 1346 1420 1347 rc = fat_node_get(&fn, service_id, index);1421 rc = fat_node_get(&fn, devmap_handle, index); 1348 1422 if (rc != EOK) 1349 1423 return rc; … … 1362 1436 } 1363 1437 1364 static int fat_sync( service_id_t service_id, fs_index_t index)1438 static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index) 1365 1439 { 1366 1440 fs_node_t *fn; 1367 int rc = fat_node_get(&fn, service_id, index);1441 int rc = fat_node_get(&fn, devmap_handle, index); 1368 1442 if (rc != EOK) 1369 1443 return rc; 1370 1444 if (!fn) 1371 1445 return ENOENT; 1372 1446 1373 1447 fat_node_t *nodep = FAT_NODE(fn); 1374 1448 1375 1449 nodep->dirty = true; 1376 1450 rc = fat_node_sync(nodep); 1377 1451 1378 1452 fat_node_put(fn); 1379 1453 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.