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