Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat_ops.c

    refcebe1 r5a9a1aaf  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    3940#include "fat_dentry.h"
    4041#include "fat_fat.h"
     42#include "fat_directory.h"
    4143#include "../../vfs/vfs.h"
    4244#include <libfs.h>
     
    5658#include <align.h>
    5759#include <malloc.h>
     60#include <str.h>
    5861
    5962#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    6770
    6871/** List of cached free FAT nodes. */
    69 static LIST_INITIALIZE(ffn_list);
     72static LIST_INITIALIZE(ffn_head);
    7073
    7174/*
     
    8588static aoff64_t fat_size_get(fs_node_t *);
    8689static unsigned fat_lnkcnt_get(fs_node_t *);
     90static char fat_plb_get_char(unsigned);
    8791static bool fat_is_directory(fs_node_t *);
    8892static bool fat_is_file(fs_node_t *node);
     
    104108        node->dirty = false;
    105109        node->lastc_cached_valid = false;
    106         node->lastc_cached_value = FAT_CLST_LAST1;
     110        node->lastc_cached_value = 0;
    107111        node->currc_cached_valid = false;
    108112        node->currc_cached_bn = 0;
    109         node->currc_cached_value = FAT_CLST_LAST1;
     113        node->currc_cached_value = 0;
    110114}
    111115
     
    116120        fat_dentry_t *d;
    117121        int rc;
    118        
     122
    119123        assert(node->dirty);
    120124
    121125        bs = block_bb_get(node->idx->devmap_handle);
    122        
     126
    123127        /* Read the block that contains the dentry of interest. */
    124128        rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     
    136140                d->attr = FAT_ATTR_SUBDIR;
    137141        }
    138        
     142
    139143        /* TODO: update other fields? (e.g time fields) */
    140        
     144
    141145        b->dirty = true;                /* need to sync block */
    142146        rc = block_put(b);
     
    146150static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
    147151{
     152        link_t *lnk;
    148153        fat_node_t *nodep;
    149154        int rc;
     
    157162restart:
    158163        fibril_mutex_lock(&ffn_mutex);
    159         list_foreach(ffn_list, lnk) {
     164        for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
    160165                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
    161166                if (!fibril_mutex_trylock(&nodep->lock)) {
     
    194199                free(nodep);
    195200
    196                 /* Need to restart because we changed ffn_list. */
     201                /* Need to restart because we changed the ffn_head list. */
    197202                goto restart;
    198203        }
     
    209214
    210215        fibril_mutex_lock(&ffn_mutex);
    211         if (!list_empty(&ffn_list)) {
     216        if (!list_empty(&ffn_head)) {
    212217                /* Try to use a cached free node structure. */
    213218                fat_idx_t *idxp_tmp;
    214                 nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
    215                     ffn_link);
     219                nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
    216220                if (!fibril_mutex_trylock(&nodep->lock))
    217221                        goto skip_cache;
     
    255259        fn->data = nodep;
    256260        nodep->bp = fn;
    257        
     261
    258262        *nodepp = nodep;
    259263        return EOK;
     
    291295         * We must instantiate the node from the file system.
    292296         */
    293        
     297
    294298        assert(idxp->pfc);
    295299
     
    309313
    310314        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     315        if (FAT_IS_FAT32(bs)) {
     316                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     317                    (uint16_t_le2host(d->firstc_hi) << 16);
     318        }
     319        else
     320                nodep->firstc = uint16_t_le2host(d->firstc);
     321
    311322        if (d->attr & FAT_ATTR_SUBDIR) {
    312                 /* 
     323                /*
    313324                 * The only directory which does not have this bit set is the
    314325                 * root directory itself. The root directory node is handled
     
    316327                 */
    317328                nodep->type = FAT_DIRECTORY;
     329
    318330                /*
    319331                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    321333                 * size of the directory by walking the FAT.
    322334                 */
    323                 uint16_t clusters;
    324                 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
    325                     uint16_t_le2host(d->firstc));
     335                uint32_t clusters;
     336                rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, nodep->firstc);
    326337                if (rc != EOK) {
    327338                        (void) block_put(b);
     
    334345                nodep->size = uint32_t_le2host(d->size);
    335346        }
    336         nodep->firstc = uint16_t_le2host(d->firstc);
     347
    337348        nodep->lnkcnt = 1;
    338349        nodep->refcnt = 1;
     
    363374int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    364375{
    365         fat_bs_t *bs;
    366376        fat_node_t *parentp = FAT_NODE(pfn);
    367         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    368         unsigned i, j;
    369         unsigned blocks;
     377        char name[FAT_LFN_NAME_SIZE];
    370378        fat_dentry_t *d;
    371379        devmap_handle_t devmap_handle;
    372         block_t *b;
    373380        int rc;
    374381
     
    376383        devmap_handle = parentp->idx->devmap_handle;
    377384        fibril_mutex_unlock(&parentp->idx->lock);
    378 
    379         bs = block_bb_get(devmap_handle);
    380         blocks = parentp->size / BPS(bs);
    381         for (i = 0; i < blocks; i++) {
    382                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    383                 if (rc != EOK)
    384                         return rc;
    385                 for (j = 0; j < DPS(bs); j++) {
    386                         d = ((fat_dentry_t *)b->data) + j;
    387                         switch (fat_classify_dentry(d)) {
    388                         case FAT_DENTRY_SKIP:
    389                         case FAT_DENTRY_FREE:
    390                                 continue;
    391                         case FAT_DENTRY_LAST:
    392                                 /* miss */
    393                                 rc = block_put(b);
    394                                 *rfn = NULL;
    395                                 return rc;
    396                         default:
    397                         case FAT_DENTRY_VALID:
    398                                 fat_dentry_name_get(d, name);
    399                                 break;
     385       
     386        fat_directory_t di;
     387        rc = fat_directory_open(parentp, &di);
     388        if (rc != EOK)
     389                return rc;
     390
     391        while (fat_directory_read(&di, name, &d) == EOK) {
     392                if (fat_dentry_namecmp(name, component) == 0) {
     393                        /* hit */
     394                        fat_node_t *nodep;
     395                        aoff64_t o = di.pos % (BPS(di.bs) / sizeof(fat_dentry_t));
     396                        fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
     397                                parentp->firstc, di.bnum * DPS(di.bs) + o);
     398                        if (!idx) {
     399                                /*
     400                                 * Can happen if memory is low or if we
     401                                 * run out of 32-bit indices.
     402                                 */
     403                                rc = fat_directory_close(&di);
     404                                return (rc == EOK) ? ENOMEM : rc;
    400405                        }
    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);
    424410                                return rc;
    425411                        }
    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);
    429416                        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);
    432424        *rfn = NULL;
    433425        return EOK;
     
    472464                if (nodep->idx) {
    473465                        fibril_mutex_lock(&ffn_mutex);
    474                         list_append(&nodep->ffn_link, &ffn_list);
     466                        list_append(&nodep->ffn_link, &ffn_head);
    475467                        fibril_mutex_unlock(&ffn_mutex);
    476468                } else {
     
    521513        rc = fat_idx_get_new(&idxp, devmap_handle);
    522514        if (rc != EOK) {
    523                 (void) fat_free_clusters(bs, devmap_handle, mcl);       
     515                (void) fat_free_clusters(bs, devmap_handle, mcl);
    524516                (void) fat_node_put(FS_NODE(nodep));
    525517                return rc;
     
    591583        fat_bs_t *bs;
    592584        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;
    596587        int rc;
    597588
     
    607598        fibril_mutex_unlock(&childp->lock);
    608599
    609         if (!fat_dentry_name_verify(name)) {
    610                 /*
    611                  * Attempt to create unsupported name.
    612                  */
     600        if (!fat_valid_name(name))
    613601                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
    621603        fibril_mutex_lock(&parentp->idx->lock);
    622604        bs = block_bb_get(parentp->idx->devmap_handle);
    623 
    624         blocks = parentp->size / BPS(bs);
    625 
    626         for (i = 0; i < blocks; i++) {
    627                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    628                 if (rc != EOK) {
    629                         fibril_mutex_unlock(&parentp->idx->lock);
    630                         return rc;
    631                 }
    632                 for (j = 0; j < DPS(bs); j++) {
    633                         d = ((fat_dentry_t *)b->data) + j;
    634                         switch (fat_classify_dentry(d)) {
    635                         case FAT_DENTRY_SKIP:
    636                         case FAT_DENTRY_VALID:
    637                                 /* skipping used and meta entries */
    638                                 continue;
    639                         case FAT_DENTRY_FREE:
    640                         case FAT_DENTRY_LAST:
    641                                 /* found an empty slot */
    642                                 goto hit;
    643                         }
    644                 }
    645                 rc = block_put(b);
    646                 if (rc != EOK) {
    647                         fibril_mutex_unlock(&parentp->idx->lock);
    648                         return rc;
    649                 }
    650         }
    651         j = 0;
    652        
    653         /*
    654          * We need to grow the parent in order to create a new unused dentry.
    655          */
    656         if (parentp->firstc == FAT_CLST_ROOT) {
    657                 /* Can't grow the root directory. */
    658                 fibril_mutex_unlock(&parentp->idx->lock);
    659                 return ENOSPC;
    660         }
    661         rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
    662         if (rc != EOK) {
    663                 fibril_mutex_unlock(&parentp->idx->lock);
     605        rc = fat_directory_open(parentp, &di);
     606        if (rc != EOK)
    664607                return rc;
    665         }
    666         rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
    667         if (rc != EOK) {
    668                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    669                 fibril_mutex_unlock(&parentp->idx->lock);
    670                 return rc;
    671         }
    672         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    673         if (rc != EOK) {
    674                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    675                 fibril_mutex_unlock(&parentp->idx->lock);
    676                 return rc;
    677         }
    678         parentp->size += BPS(bs) * SPC(bs);
    679         parentp->dirty = true;          /* need to sync node */
    680         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    681         if (rc != EOK) {
    682                 fibril_mutex_unlock(&parentp->idx->lock);
    683                 return rc;
    684         }
    685         d = (fat_dentry_t *)b->data;
    686 
    687 hit:
     608
    688609        /*
    689610         * At this point we only establish the link between the parent and the
     
    692613         * dentry data is kept in the child node structure.
    693614         */
    694         memset(d, 0, sizeof(fat_dentry_t));
    695         fat_dentry_name_set(d, name);
    696         b->dirty = true;                /* need to sync block */
    697         rc = block_put(b);
     615        memset(&de, 0, sizeof(fat_dentry_t));
     616
     617        rc = fat_directory_write(&di, name, &de);
     618        if (rc!=EOK)
     619                return rc;
     620        rc = fat_directory_close(&di);
     621        if (rc!=EOK)
     622                return rc;
     623
    698624        fibril_mutex_unlock(&parentp->idx->lock);
    699         if (rc != EOK) 
     625        if (rc != EOK)
    700626                return rc;
    701627
    702628        fibril_mutex_lock(&childp->idx->lock);
    703        
     629
    704630        if (childp->type == FAT_DIRECTORY) {
    705631                /*
     
    720646                d = (fat_dentry_t *) b->data;
    721647                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    722                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     648                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    723649                        memset(d, 0, sizeof(fat_dentry_t));
    724650                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    730656                d++;
    731657                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    732                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     658                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    733659                        memset(d, 0, sizeof(fat_dentry_t));
    734660                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    735661                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    736662                        d->attr = FAT_ATTR_SUBDIR;
    737                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    738                             host2uint16_t_le(FAT_CLST_RES0) :
     663                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     664                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    739665                            host2uint16_t_le(parentp->firstc);
    740666                        /* TODO: initialize also the date/time members. */
     
    750676
    751677        childp->idx->pfc = parentp->firstc;
    752         childp->idx->pdi = i * DPS(bs) + j;
     678        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    753679        fibril_mutex_unlock(&childp->idx->lock);
    754680
     
    770696        fat_node_t *parentp = FAT_NODE(pfn);
    771697        fat_node_t *childp = FAT_NODE(cfn);
    772         fat_bs_t *bs;
    773         fat_dentry_t *d;
    774         block_t *b;
    775698        bool has_children;
    776699        int rc;
     
    778701        if (!parentp)
    779702                return EBUSY;
    780        
     703
    781704        rc = fat_has_children(&has_children, cfn);
    782705        if (rc != EOK)
     
    789712        assert(childp->lnkcnt == 1);
    790713        fibril_mutex_lock(&childp->idx->lock);
    791         bs = block_bb_get(childp->idx->devmap_handle);
    792 
    793         rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
    794             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    795             BLOCK_FLAGS_NONE);
    796         if (rc != EOK)
     714       
     715        fat_directory_t di;
     716        rc = fat_directory_open(parentp,&di);
     717        if (rc != EOK)
    797718                goto error;
    798         d = (fat_dentry_t *)b->data +
    799             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    800         /* mark the dentry as not-currently-used */
    801         d->name[0] = FAT_DENTRY_ERASED;
    802         b->dirty = true;                /* need to sync block */
    803         rc = block_put(b);
     719        rc = fat_directory_seek(&di, childp->idx->pdi);
     720        if (rc != EOK)
     721                goto error;
     722        rc = fat_directory_erase(&di);
     723        if (rc != EOK)
     724                goto error;
     725        rc = fat_directory_close(&di);
    804726        if (rc != EOK)
    805727                goto error;
     
    820742
    821743error:
    822         fibril_mutex_unlock(&parentp->idx->lock);
     744        (void) fat_directory_close(&di);
     745        fibril_mutex_unlock(&childp->idx->lock);
    823746        fibril_mutex_unlock(&childp->lock);
    824         fibril_mutex_unlock(&childp->idx->lock);
     747        fibril_mutex_unlock(&parentp->lock);
    825748        return rc;
    826749}
     
    839762                return EOK;
    840763        }
    841        
     764
    842765        fibril_mutex_lock(&nodep->idx->lock);
    843766        bs = block_bb_get(nodep->idx->devmap_handle);
     
    847770        for (i = 0; i < blocks; i++) {
    848771                fat_dentry_t *d;
    849        
     772
    850773                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    851774                if (rc != EOK) {
     
    875798                if (rc != EOK) {
    876799                        fibril_mutex_unlock(&nodep->idx->lock);
    877                         return rc;     
     800                        return rc;
    878801                }
    879802        }
     
    898821{
    899822        return FAT_NODE(fn)->lnkcnt;
     823}
     824
     825char fat_plb_get_char(unsigned pos)
     826{
     827        return fat_reg.plb_ro[pos % PLB_SIZE];
    900828}
    901829
     
    930858        .size_get = fat_size_get,
    931859        .lnkcnt_get = fat_lnkcnt_get,
     860        .plb_get_char = fat_plb_get_char,
    932861        .is_directory = fat_is_directory,
    933862        .is_file = fat_is_file,
     
    936865
    937866/*
    938  * FAT VFS_OUT operations.
     867 * VFS operations.
    939868 */
    940869
    941 static int
    942 fat_mounted(devmap_handle_t devmap_handle, const char *opts, fs_index_t *index,
    943     aoff64_t *size, unsigned *linkcnt)
    944 {
     870void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
     871{
     872        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    945873        enum cache_mode cmode;
    946874        fat_bs_t *bs;
    947         int rc;
    948        
     875
     876        /* Accept the mount options */
     877        char *opts;
     878        int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
     879
     880        if (rc != EOK) {
     881                async_answer_0(rid, rc);
     882                return;
     883        }
     884
    949885        /* Check for option enabling write through. */
    950886        if (str_cmp(opts, "wtcache") == 0)
     
    953889                cmode = CACHE_MODE_WB;
    954890
     891        free(opts);
     892
    955893        /* initialize libblock */
    956         rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
    957         if (rc != EOK)
    958                 return rc;
     894        rc = block_init(devmap_handle, BS_SIZE);
     895        if (rc != EOK) {
     896                async_answer_0(rid, rc);
     897                return;
     898        }
    959899
    960900        /* prepare the boot block */
     
    962902        if (rc != EOK) {
    963903                block_fini(devmap_handle);
    964                 return rc;
     904                async_answer_0(rid, rc);
     905                return;
    965906        }
    966907
    967908        /* get the buffer with the boot sector */
    968909        bs = block_bb_get(devmap_handle);
    969        
     910
    970911        if (BPS(bs) != BS_SIZE) {
    971912                block_fini(devmap_handle);
    972                 return ENOTSUP;
     913                async_answer_0(rid, ENOTSUP);
     914                return;
    973915        }
    974916
     
    977919        if (rc != EOK) {
    978920                block_fini(devmap_handle);
    979                 return rc;
     921                async_answer_0(rid, rc);
     922                return;
    980923        }
    981924
     
    985928                (void) block_cache_fini(devmap_handle);
    986929                block_fini(devmap_handle);
    987                 return rc;
     930                async_answer_0(rid, rc);
     931                return;
    988932        }
    989933
     
    992936                (void) block_cache_fini(devmap_handle);
    993937                block_fini(devmap_handle);
    994                 return rc;
     938                async_answer_0(rid, rc);
     939                return;
    995940        }
    996941
     
    1001946                block_fini(devmap_handle);
    1002947                fat_idx_fini_by_devmap_handle(devmap_handle);
    1003                 return ENOMEM;
    1004         }
     948                async_answer_0(rid, ENOMEM);
     949                return;
     950        }
     951
    1005952        fs_node_initialize(rfn);
    1006953        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    1010957                block_fini(devmap_handle);
    1011958                fat_idx_fini_by_devmap_handle(devmap_handle);
    1012                 return ENOMEM;
     959                async_answer_0(rid, ENOMEM);
     960                return;
    1013961        }
    1014962        fat_node_initialize(rootp);
     
    1021969                block_fini(devmap_handle);
    1022970                fat_idx_fini_by_devmap_handle(devmap_handle);
    1023                 return ENOMEM;
     971                async_answer_0(rid, ENOMEM);
     972                return;
    1024973        }
    1025974        assert(ridxp->index == 0);
     
    1027976
    1028977        rootp->type = FAT_DIRECTORY;
    1029         rootp->firstc = FAT_CLST_ROOT;
     978        rootp->firstc = FAT_ROOT_CLST(bs);
    1030979        rootp->refcnt = 1;
    1031980        rootp->lnkcnt = 0;      /* FS root is not linked */
    1032         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     981
     982        if (FAT_IS_FAT32(bs)) {
     983                uint32_t clusters;
     984                rc = fat_clusters_get(&clusters, bs, devmap_handle, rootp->firstc);
     985                if (rc != EOK) {
     986                        free(rfn);
     987                        free(rootp);
     988                        free(ridxp); /* TODO: Is it right way to free ridxp? */
     989                        (void) block_cache_fini(devmap_handle);
     990                        block_fini(devmap_handle);
     991                        fat_idx_fini_by_devmap_handle(devmap_handle);
     992                        async_answer_0(rid, ENOTSUP);
     993                        return;
     994                }
     995                rootp->size = BPS(bs) * SPC(bs) * clusters;
     996        } else
     997                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     998
    1033999        rootp->idx = ridxp;
    10341000        ridxp->nodep = rootp;
    10351001        rootp->bp = rfn;
    10361002        rfn->data = rootp;
    1037        
     1003
    10381004        fibril_mutex_unlock(&ridxp->lock);
    10391005
    1040         *index = ridxp->index;
    1041         *size = rootp->size;
    1042         *linkcnt = rootp->lnkcnt;
    1043 
    1044         return EOK;
    1045 }
    1046 
    1047 static int fat_unmounted(devmap_handle_t devmap_handle)
    1048 {
     1006        async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
     1007}
     1008
     1009void fat_mount(ipc_callid_t rid, ipc_call_t *request)
     1010{
     1011        libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
     1012}
     1013
     1014void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
     1015{
     1016        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    10491017        fs_node_t *fn;
    10501018        fat_node_t *nodep;
     
    10521020
    10531021        rc = fat_root_get(&fn, devmap_handle);
    1054         if (rc != EOK)
    1055                 return rc;
     1022        if (rc != EOK) {
     1023                async_answer_0(rid, rc);
     1024                return;
     1025        }
    10561026        nodep = FAT_NODE(fn);
    10571027
     
    10621032        if (nodep->refcnt != 2) {
    10631033                (void) fat_node_put(fn);
    1064                 return EBUSY;
    1065         }
    1066        
     1034                async_answer_0(rid, EBUSY);
     1035                return;
     1036        }
     1037
    10671038        /*
    10681039         * Put the root node and force it to the FAT free node list.
     
    10811052        block_fini(devmap_handle);
    10821053
    1083         return EOK;
    1084 }
    1085 
    1086 static int
    1087 fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
    1088     size_t *rbytes)
    1089 {
     1054        async_answer_0(rid, EOK);
     1055}
     1056
     1057void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
     1058{
     1059        libfs_unmount(&fat_libfs_ops, rid, request);
     1060}
     1061
     1062void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
     1063{
     1064        libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
     1065}
     1066
     1067void fat_read(ipc_callid_t rid, ipc_call_t *request)
     1068{
     1069        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1070        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1071        aoff64_t pos =
     1072            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    10901073        fs_node_t *fn;
    10911074        fat_node_t *nodep;
     
    10961079
    10971080        rc = fat_node_get(&fn, devmap_handle, index);
    1098         if (rc != EOK)
    1099                 return rc;
    1100         if (!fn)
    1101                 return ENOENT;
     1081        if (rc != EOK) {
     1082                async_answer_0(rid, rc);
     1083                return;
     1084        }
     1085        if (!fn) {
     1086                async_answer_0(rid, ENOENT);
     1087                return;
     1088        }
    11021089        nodep = FAT_NODE(fn);
    11031090
     
    11071094                fat_node_put(fn);
    11081095                async_answer_0(callid, EINVAL);
    1109                 return EINVAL;
     1096                async_answer_0(rid, EINVAL);
     1097                return;
    11101098        }
    11111099
     
    11301118                                fat_node_put(fn);
    11311119                                async_answer_0(callid, rc);
    1132                                 return rc;
     1120                                async_answer_0(rid, rc);
     1121                                return;
    11331122                        }
    11341123                        (void) async_data_read_finalize(callid,
     
    11371126                        if (rc != EOK) {
    11381127                                fat_node_put(fn);
    1139                                 return rc;
     1128                                async_answer_0(rid, rc);
     1129                                return;
    11401130                        }
    11411131                }
    11421132        } else {
    1143                 unsigned bnum;
    11441133                aoff64_t spos = pos;
    1145                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1134                char name[FAT_LFN_NAME_SIZE];
    11461135                fat_dentry_t *d;
    11471136
     
    11501139                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    11511140
    1152                 /*
    1153                  * Our strategy for readdir() is to use the position pointer as
    1154                  * an index into the array of all dentries. On entry, it points
    1155                  * to the first unread dentry. If we skip any dentries, we bump
    1156                  * the position pointer accordingly.
    1157                  */
    1158                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1159                 while (bnum < nodep->size / BPS(bs)) {
    1160                         aoff64_t o;
    1161 
    1162                         rc = fat_block_get(&b, bs, nodep, bnum,
    1163                             BLOCK_FLAGS_NONE);
    1164                         if (rc != EOK)
    1165                                 goto err;
    1166                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1167                             o < BPS(bs) / sizeof(fat_dentry_t);
    1168                             o++, pos++) {
    1169                                 d = ((fat_dentry_t *)b->data) + o;
    1170                                 switch (fat_classify_dentry(d)) {
    1171                                 case FAT_DENTRY_SKIP:
    1172                                 case FAT_DENTRY_FREE:
    1173                                         continue;
    1174                                 case FAT_DENTRY_LAST:
    1175                                         rc = block_put(b);
    1176                                         if (rc != EOK)
    1177                                                 goto err;
    1178                                         goto miss;
    1179                                 default:
    1180                                 case FAT_DENTRY_VALID:
    1181                                         fat_dentry_name_get(d, name);
    1182                                         rc = block_put(b);
    1183                                         if (rc != EOK)
    1184                                                 goto err;
    1185                                         goto hit;
    1186                                 }
    1187                         }
    1188                         rc = block_put(b);
    1189                         if (rc != EOK)
    1190                                 goto err;
    1191                         bnum++;
    1192                 }
    1193 miss:
    1194                 rc = fat_node_put(fn);
    1195                 async_answer_0(callid, rc != EOK ? rc : ENOENT);
    1196                 *rbytes = 0;
    1197                 return rc != EOK ? rc : ENOENT;
     1141                fat_directory_t di;
     1142                rc = fat_directory_open(nodep, &di);
     1143                if (rc != EOK) goto err;
     1144                rc = fat_directory_seek(&di, pos);
     1145                if (rc != EOK) {
     1146                        (void) fat_directory_close(&di);
     1147                        goto err;
     1148                }
     1149
     1150                rc = fat_directory_read(&di, name, &d);
     1151                if (rc == EOK) goto hit;
     1152                if (rc == ENOENT) goto miss;
    11981153
    11991154err:
    12001155                (void) fat_node_put(fn);
    12011156                async_answer_0(callid, rc);
    1202                 return rc;
     1157                async_answer_0(rid, rc);
     1158                return;
     1159
     1160miss:
     1161                rc = fat_directory_close(&di);
     1162                if (rc!=EOK)
     1163                        goto err;
     1164                rc = fat_node_put(fn);
     1165                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     1166                async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
     1167                return;
    12031168
    12041169hit:
     1170                pos = di.pos;
     1171                rc = fat_directory_close(&di);
     1172                if (rc!=EOK)
     1173                        goto err;
    12051174                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    1206                 bytes = (pos - spos) + 1;
     1175                bytes = (pos - spos)+1;
    12071176        }
    12081177
    12091178        rc = fat_node_put(fn);
    1210         *rbytes = bytes;
    1211         return rc;
    1212 }
    1213 
    1214 static int
    1215 fat_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
    1216     size_t *wbytes, aoff64_t *nsize)
    1217 {
     1179        async_answer_1(rid, rc, (sysarg_t)bytes);
     1180}
     1181
     1182void fat_write(ipc_callid_t rid, ipc_call_t *request)
     1183{
     1184        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1185        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1186        aoff64_t pos =
     1187            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    12181188        fs_node_t *fn;
    12191189        fat_node_t *nodep;
    12201190        fat_bs_t *bs;
    1221         size_t bytes;
     1191        size_t bytes, size;
    12221192        block_t *b;
    12231193        aoff64_t boundary;
    12241194        int flags = BLOCK_FLAGS_NONE;
    12251195        int rc;
    1226        
     1196
    12271197        rc = fat_node_get(&fn, devmap_handle, index);
    1228         if (rc != EOK)
    1229                 return rc;
    1230         if (!fn)
    1231                 return ENOENT;
     1198        if (rc != EOK) {
     1199                async_answer_0(rid, rc);
     1200                return;
     1201        }
     1202        if (!fn) {
     1203                async_answer_0(rid, ENOENT);
     1204                return;
     1205        }
    12321206        nodep = FAT_NODE(fn);
    1233        
     1207
    12341208        ipc_callid_t callid;
    12351209        size_t len;
     
    12371211                (void) fat_node_put(fn);
    12381212                async_answer_0(callid, EINVAL);
    1239                 return EINVAL;
     1213                async_answer_0(rid, EINVAL);
     1214                return;
    12401215        }
    12411216
     
    12471222         * but this one greatly simplifies fat_write(). Note that we can afford
    12481223         * to do this because the client must be ready to handle the return
    1249          * value signalizing a smaller number of bytes written. 
    1250          */ 
     1224         * value signalizing a smaller number of bytes written.
     1225         */
    12511226        bytes = min(len, BPS(bs) - pos % BPS(bs));
    12521227        if (bytes == BPS(bs))
    12531228                flags |= BLOCK_FLAGS_NOREAD;
    1254        
     1229
    12551230        boundary = ROUND_UP(nodep->size, BPC(bs));
    12561231        if (pos < boundary) {
     
    12651240                        (void) fat_node_put(fn);
    12661241                        async_answer_0(callid, rc);
    1267                         return rc;
     1242                        async_answer_0(rid, rc);
     1243                        return;
    12681244                }
    12691245                rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
     
    12711247                        (void) fat_node_put(fn);
    12721248                        async_answer_0(callid, rc);
    1273                         return rc;
     1249                        async_answer_0(rid, rc);
     1250                        return;
    12741251                }
    12751252                (void) async_data_write_finalize(callid,
     
    12791256                if (rc != EOK) {
    12801257                        (void) fat_node_put(fn);
    1281                         return rc;
     1258                        async_answer_0(rid, rc);
     1259                        return;
    12821260                }
    12831261                if (pos + bytes > nodep->size) {
     
    12851263                        nodep->dirty = true;    /* need to sync node */
    12861264                }
    1287                 *wbytes = bytes;
    1288                 *nsize = nodep->size;
     1265                size = nodep->size;
    12891266                rc = fat_node_put(fn);
    1290                 return rc;
     1267                async_answer_2(rid, rc, bytes, nodep->size);
     1268                return;
    12911269        } else {
    12921270                /*
     
    12951273                 */
    12961274                unsigned nclsts;
    1297                 fat_cluster_t mcl, lcl; 
    1298  
     1275                fat_cluster_t mcl, lcl;
     1276
    12991277                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13001278                /* create an independent chain of nclsts clusters in all FATs */
     
    13041282                        (void) fat_node_put(fn);
    13051283                        async_answer_0(callid, rc);
    1306                         return rc;
     1284                        async_answer_0(rid, rc);
     1285                        return;
    13071286                }
    13081287                /* zero fill any gaps */
     
    13121291                        (void) fat_node_put(fn);
    13131292                        async_answer_0(callid, rc);
    1314                         return rc;
     1293                        async_answer_0(rid, rc);
     1294                        return;
    13151295                }
    13161296                rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
     
    13201300                        (void) fat_node_put(fn);
    13211301                        async_answer_0(callid, rc);
    1322                         return rc;
     1302                        async_answer_0(rid, rc);
     1303                        return;
    13231304                }
    13241305                (void) async_data_write_finalize(callid,
     
    13291310                        (void) fat_free_clusters(bs, devmap_handle, mcl);
    13301311                        (void) fat_node_put(fn);
    1331                         return rc;
     1312                        async_answer_0(rid, rc);
     1313                        return;
    13321314                }
    13331315                /*
     
    13391321                        (void) fat_free_clusters(bs, devmap_handle, mcl);
    13401322                        (void) fat_node_put(fn);
    1341                         return rc;
    1342                 }
    1343                 *nsize = nodep->size = pos + bytes;
     1323                        async_answer_0(rid, rc);
     1324                        return;
     1325                }
     1326                nodep->size = size = pos + bytes;
     1327                nodep->dirty = true;            /* need to sync node */
    13441328                rc = fat_node_put(fn);
    1345                 nodep->dirty = true;            /* need to sync node */
    1346                 *wbytes = bytes;
    1347                 return rc;
    1348         }
    1349 }
    1350 
    1351 static int
    1352 fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
    1353 {
     1329                async_answer_2(rid, rc, bytes, size);
     1330                return;
     1331        }
     1332}
     1333
     1334void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
     1335{
     1336        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1337        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1338        aoff64_t size =
     1339            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    13541340        fs_node_t *fn;
    13551341        fat_node_t *nodep;
     
    13581344
    13591345        rc = fat_node_get(&fn, devmap_handle, index);
    1360         if (rc != EOK)
    1361                 return rc;
    1362         if (!fn)
    1363                 return ENOENT;
     1346        if (rc != EOK) {
     1347                async_answer_0(rid, rc);
     1348                return;
     1349        }
     1350        if (!fn) {
     1351                async_answer_0(rid, ENOENT);
     1352                return;
     1353        }
    13641354        nodep = FAT_NODE(fn);
    13651355
     
    13801370                nodep->size = size;
    13811371                nodep->dirty = true;            /* need to sync node */
    1382                 rc = EOK;       
     1372                rc = EOK;
    13831373        } else {
    13841374                /*
     
    14011391                nodep->size = size;
    14021392                nodep->dirty = true;            /* need to sync node */
    1403                 rc = EOK;       
     1393                rc = EOK;
    14041394        }
    14051395out:
    14061396        fat_node_put(fn);
    1407         return rc;
    1408 }
    1409 
    1410 static int fat_close(devmap_handle_t devmap_handle, fs_index_t index)
    1411 {
    1412         return EOK;
    1413 }
    1414 
    1415 static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index)
    1416 {
     1397        async_answer_0(rid, rc);
     1398        return;
     1399}
     1400
     1401void fat_close(ipc_callid_t rid, ipc_call_t *request)
     1402{
     1403        async_answer_0(rid, EOK);
     1404}
     1405
     1406void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
     1407{
     1408        devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
     1409        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    14171410        fs_node_t *fn;
    14181411        fat_node_t *nodep;
     
    14201413
    14211414        rc = fat_node_get(&fn, devmap_handle, index);
    1422         if (rc != EOK)
    1423                 return rc;
    1424         if (!fn)
    1425                 return ENOENT;
     1415        if (rc != EOK) {
     1416                async_answer_0(rid, rc);
     1417                return;
     1418        }
     1419        if (!fn) {
     1420                async_answer_0(rid, ENOENT);
     1421                return;
     1422        }
    14261423
    14271424        nodep = FAT_NODE(fn);
     
    14331430
    14341431        rc = fat_destroy_node(fn);
    1435         return rc;
    1436 }
    1437 
    1438 static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index)
    1439 {
     1432        async_answer_0(rid, rc);
     1433}
     1434
     1435void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
     1436{
     1437        libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
     1438}
     1439
     1440void fat_stat(ipc_callid_t rid, ipc_call_t *request)
     1441{
     1442        libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
     1443}
     1444
     1445void fat_sync(ipc_callid_t rid, ipc_call_t *request)
     1446{
     1447        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1448        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     1449
    14401450        fs_node_t *fn;
    14411451        int rc = fat_node_get(&fn, devmap_handle, index);
    1442         if (rc != EOK)
    1443                 return rc;
    1444         if (!fn)
    1445                 return ENOENT;
    1446        
     1452        if (rc != EOK) {
     1453                async_answer_0(rid, rc);
     1454                return;
     1455        }
     1456        if (!fn) {
     1457                async_answer_0(rid, ENOENT);
     1458                return;
     1459        }
     1460
    14471461        fat_node_t *nodep = FAT_NODE(fn);
    1448        
     1462
    14491463        nodep->dirty = true;
    14501464        rc = fat_node_sync(nodep);
    1451        
     1465
    14521466        fat_node_put(fn);
    1453         return rc;
    1454 }
    1455 
    1456 vfs_out_ops_t fat_ops = {
    1457         .mounted = fat_mounted,
    1458         .unmounted = fat_unmounted,
    1459         .read = fat_read,
    1460         .write = fat_write,
    1461         .truncate = fat_truncate,
    1462         .close = fat_close,
    1463         .destroy = fat_destroy,
    1464         .sync = fat_sync,
    1465 };
     1467        async_answer_0(rid, rc);
     1468}
    14661469
    14671470/**
Note: See TracChangeset for help on using the changeset viewer.