Ignore:
File:
1 edited

Legend:

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

    r5a9a1aaf refcebe1  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3029/** @addtogroup fs
    3130 * @{
    32  */
     31 */ 
    3332
    3433/**
     
    4039#include "fat_dentry.h"
    4140#include "fat_fat.h"
    42 #include "fat_directory.h"
    4341#include "../../vfs/vfs.h"
    4442#include <libfs.h>
     
    5856#include <align.h>
    5957#include <malloc.h>
    60 #include <str.h>
    6158
    6259#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    7067
    7168/** List of cached free FAT nodes. */
    72 static LIST_INITIALIZE(ffn_head);
     69static LIST_INITIALIZE(ffn_list);
    7370
    7471/*
     
    8885static aoff64_t fat_size_get(fs_node_t *);
    8986static unsigned fat_lnkcnt_get(fs_node_t *);
    90 static char fat_plb_get_char(unsigned);
    9187static bool fat_is_directory(fs_node_t *);
    9288static bool fat_is_file(fs_node_t *node);
     
    108104        node->dirty = false;
    109105        node->lastc_cached_valid = false;
    110         node->lastc_cached_value = 0;
     106        node->lastc_cached_value = FAT_CLST_LAST1;
    111107        node->currc_cached_valid = false;
    112108        node->currc_cached_bn = 0;
    113         node->currc_cached_value = 0;
     109        node->currc_cached_value = FAT_CLST_LAST1;
    114110}
    115111
     
    120116        fat_dentry_t *d;
    121117        int rc;
    122 
     118       
    123119        assert(node->dirty);
    124120
    125121        bs = block_bb_get(node->idx->devmap_handle);
    126 
     122       
    127123        /* Read the block that contains the dentry of interest. */
    128124        rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     
    140136                d->attr = FAT_ATTR_SUBDIR;
    141137        }
    142 
     138       
    143139        /* TODO: update other fields? (e.g time fields) */
    144 
     140       
    145141        b->dirty = true;                /* need to sync block */
    146142        rc = block_put(b);
     
    150146static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
    151147{
    152         link_t *lnk;
    153148        fat_node_t *nodep;
    154149        int rc;
     
    162157restart:
    163158        fibril_mutex_lock(&ffn_mutex);
    164         for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     159        list_foreach(ffn_list, lnk) {
    165160                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
    166161                if (!fibril_mutex_trylock(&nodep->lock)) {
     
    199194                free(nodep);
    200195
    201                 /* Need to restart because we changed the ffn_head list. */
     196                /* Need to restart because we changed ffn_list. */
    202197                goto restart;
    203198        }
     
    214209
    215210        fibril_mutex_lock(&ffn_mutex);
    216         if (!list_empty(&ffn_head)) {
     211        if (!list_empty(&ffn_list)) {
    217212                /* Try to use a cached free node structure. */
    218213                fat_idx_t *idxp_tmp;
    219                 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
     214                nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
     215                    ffn_link);
    220216                if (!fibril_mutex_trylock(&nodep->lock))
    221217                        goto skip_cache;
     
    259255        fn->data = nodep;
    260256        nodep->bp = fn;
    261 
     257       
    262258        *nodepp = nodep;
    263259        return EOK;
     
    295291         * We must instantiate the node from the file system.
    296292         */
    297 
     293       
    298294        assert(idxp->pfc);
    299295
     
    313309
    314310        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 
    322311        if (d->attr & FAT_ATTR_SUBDIR) {
    323                 /*
     312                /* 
    324313                 * The only directory which does not have this bit set is the
    325314                 * root directory itself. The root directory node is handled
     
    327316                 */
    328317                nodep->type = FAT_DIRECTORY;
    329 
    330318                /*
    331319                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    333321                 * size of the directory by walking the FAT.
    334322                 */
    335                 uint32_t clusters;
    336                 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, nodep->firstc);
     323                uint16_t clusters;
     324                rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
     325                    uint16_t_le2host(d->firstc));
    337326                if (rc != EOK) {
    338327                        (void) block_put(b);
     
    345334                nodep->size = uint32_t_le2host(d->size);
    346335        }
    347 
     336        nodep->firstc = uint16_t_le2host(d->firstc);
    348337        nodep->lnkcnt = 1;
    349338        nodep->refcnt = 1;
     
    374363int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    375364{
     365        fat_bs_t *bs;
    376366        fat_node_t *parentp = FAT_NODE(pfn);
    377         char name[FAT_LFN_NAME_SIZE];
     367        char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     368        unsigned i, j;
     369        unsigned blocks;
    378370        fat_dentry_t *d;
    379371        devmap_handle_t devmap_handle;
     372        block_t *b;
    380373        int rc;
    381374
     
    383376        devmap_handle = parentp->idx->devmap_handle;
    384377        fibril_mutex_unlock(&parentp->idx->lock);
    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;
     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;
    405400                        }
    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);
    410424                                return rc;
    411425                        }
    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
    424432        *rfn = NULL;
    425433        return EOK;
     
    464472                if (nodep->idx) {
    465473                        fibril_mutex_lock(&ffn_mutex);
    466                         list_append(&nodep->ffn_link, &ffn_head);
     474                        list_append(&nodep->ffn_link, &ffn_list);
    467475                        fibril_mutex_unlock(&ffn_mutex);
    468476                } else {
     
    513521        rc = fat_idx_get_new(&idxp, devmap_handle);
    514522        if (rc != EOK) {
    515                 (void) fat_free_clusters(bs, devmap_handle, mcl);
     523                (void) fat_free_clusters(bs, devmap_handle, mcl);       
    516524                (void) fat_node_put(FS_NODE(nodep));
    517525                return rc;
     
    583591        fat_bs_t *bs;
    584592        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;
    587596        int rc;
    588597
     
    598607        fibril_mutex_unlock(&childp->lock);
    599608
    600         if (!fat_valid_name(name))
     609        if (!fat_dentry_name_verify(name)) {
     610                /*
     611                 * Attempt to create unsupported name.
     612                 */
    601613                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       
    603621        fibril_mutex_lock(&parentp->idx->lock);
    604622        bs = block_bb_get(parentp->idx->devmap_handle);
    605         rc = fat_directory_open(parentp, &di);
    606         if (rc != EOK)
    607                 return rc;
    608 
     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);
     664                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
     687hit:
    609688        /*
    610689         * At this point we only establish the link between the parent and the
     
    613692         * dentry data is kept in the child node structure.
    614693         */
    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 
     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);
    624698        fibril_mutex_unlock(&parentp->idx->lock);
    625         if (rc != EOK)
     699        if (rc != EOK) 
    626700                return rc;
    627701
    628702        fibril_mutex_lock(&childp->idx->lock);
    629 
     703       
    630704        if (childp->type == FAT_DIRECTORY) {
    631705                /*
     
    646720                d = (fat_dentry_t *) b->data;
    647721                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    648                     (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
     722                    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
    649723                        memset(d, 0, sizeof(fat_dentry_t));
    650724                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    656730                d++;
    657731                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    658                     (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
     732                    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
    659733                        memset(d, 0, sizeof(fat_dentry_t));
    660734                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    661735                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    662736                        d->attr = FAT_ATTR_SUBDIR;
    663                         d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
    664                             host2uint16_t_le(FAT_CLST_ROOTPAR) :
     737                        d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     738                            host2uint16_t_le(FAT_CLST_RES0) :
    665739                            host2uint16_t_le(parentp->firstc);
    666740                        /* TODO: initialize also the date/time members. */
     
    676750
    677751        childp->idx->pfc = parentp->firstc;
    678         childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
     752        childp->idx->pdi = i * DPS(bs) + j;
    679753        fibril_mutex_unlock(&childp->idx->lock);
    680754
     
    696770        fat_node_t *parentp = FAT_NODE(pfn);
    697771        fat_node_t *childp = FAT_NODE(cfn);
     772        fat_bs_t *bs;
     773        fat_dentry_t *d;
     774        block_t *b;
    698775        bool has_children;
    699776        int rc;
     
    701778        if (!parentp)
    702779                return EBUSY;
    703 
     780       
    704781        rc = fat_has_children(&has_children, cfn);
    705782        if (rc != EOK)
     
    712789        assert(childp->lnkcnt == 1);
    713790        fibril_mutex_lock(&childp->idx->lock);
    714        
    715         fat_directory_t di;
    716         rc = fat_directory_open(parentp,&di);
    717         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)
    718797                goto error;
    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);
     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);
    726804        if (rc != EOK)
    727805                goto error;
     
    742820
    743821error:
    744         (void) fat_directory_close(&di);
     822        fibril_mutex_unlock(&parentp->idx->lock);
     823        fibril_mutex_unlock(&childp->lock);
    745824        fibril_mutex_unlock(&childp->idx->lock);
    746         fibril_mutex_unlock(&childp->lock);
    747         fibril_mutex_unlock(&parentp->lock);
    748825        return rc;
    749826}
     
    762839                return EOK;
    763840        }
    764 
     841       
    765842        fibril_mutex_lock(&nodep->idx->lock);
    766843        bs = block_bb_get(nodep->idx->devmap_handle);
     
    770847        for (i = 0; i < blocks; i++) {
    771848                fat_dentry_t *d;
    772 
     849       
    773850                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    774851                if (rc != EOK) {
     
    798875                if (rc != EOK) {
    799876                        fibril_mutex_unlock(&nodep->idx->lock);
    800                         return rc;
     877                        return rc;     
    801878                }
    802879        }
     
    821898{
    822899        return FAT_NODE(fn)->lnkcnt;
    823 }
    824 
    825 char fat_plb_get_char(unsigned pos)
    826 {
    827         return fat_reg.plb_ro[pos % PLB_SIZE];
    828900}
    829901
     
    858930        .size_get = fat_size_get,
    859931        .lnkcnt_get = fat_lnkcnt_get,
    860         .plb_get_char = fat_plb_get_char,
    861932        .is_directory = fat_is_directory,
    862933        .is_file = fat_is_file,
     
    865936
    866937/*
    867  * VFS operations.
     938 * FAT VFS_OUT operations.
    868939 */
    869940
    870 void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
    871 {
    872         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     941static int
     942fat_mounted(devmap_handle_t devmap_handle, const char *opts, fs_index_t *index,
     943    aoff64_t *size, unsigned *linkcnt)
     944{
    873945        enum cache_mode cmode;
    874946        fat_bs_t *bs;
    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 
     947        int rc;
     948       
    885949        /* Check for option enabling write through. */
    886950        if (str_cmp(opts, "wtcache") == 0)
     
    889953                cmode = CACHE_MODE_WB;
    890954
    891         free(opts);
    892 
    893955        /* initialize libblock */
    894         rc = block_init(devmap_handle, BS_SIZE);
    895         if (rc != EOK) {
    896                 async_answer_0(rid, rc);
    897                 return;
    898         }
     956        rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
     957        if (rc != EOK)
     958                return rc;
    899959
    900960        /* prepare the boot block */
     
    902962        if (rc != EOK) {
    903963                block_fini(devmap_handle);
    904                 async_answer_0(rid, rc);
    905                 return;
     964                return rc;
    906965        }
    907966
    908967        /* get the buffer with the boot sector */
    909968        bs = block_bb_get(devmap_handle);
    910 
     969       
    911970        if (BPS(bs) != BS_SIZE) {
    912971                block_fini(devmap_handle);
    913                 async_answer_0(rid, ENOTSUP);
    914                 return;
     972                return ENOTSUP;
    915973        }
    916974
     
    919977        if (rc != EOK) {
    920978                block_fini(devmap_handle);
    921                 async_answer_0(rid, rc);
    922                 return;
     979                return rc;
    923980        }
    924981
     
    928985                (void) block_cache_fini(devmap_handle);
    929986                block_fini(devmap_handle);
    930                 async_answer_0(rid, rc);
    931                 return;
     987                return rc;
    932988        }
    933989
     
    936992                (void) block_cache_fini(devmap_handle);
    937993                block_fini(devmap_handle);
    938                 async_answer_0(rid, rc);
    939                 return;
     994                return rc;
    940995        }
    941996
     
    9461001                block_fini(devmap_handle);
    9471002                fat_idx_fini_by_devmap_handle(devmap_handle);
    948                 async_answer_0(rid, ENOMEM);
    949                 return;
    950         }
    951 
     1003                return ENOMEM;
     1004        }
    9521005        fs_node_initialize(rfn);
    9531006        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    9571010                block_fini(devmap_handle);
    9581011                fat_idx_fini_by_devmap_handle(devmap_handle);
    959                 async_answer_0(rid, ENOMEM);
    960                 return;
     1012                return ENOMEM;
    9611013        }
    9621014        fat_node_initialize(rootp);
     
    9691021                block_fini(devmap_handle);
    9701022                fat_idx_fini_by_devmap_handle(devmap_handle);
    971                 async_answer_0(rid, ENOMEM);
    972                 return;
     1023                return ENOMEM;
    9731024        }
    9741025        assert(ridxp->index == 0);
     
    9761027
    9771028        rootp->type = FAT_DIRECTORY;
    978         rootp->firstc = FAT_ROOT_CLST(bs);
     1029        rootp->firstc = FAT_CLST_ROOT;
    9791030        rootp->refcnt = 1;
    9801031        rootp->lnkcnt = 0;      /* FS root is not linked */
    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 
     1032        rootp->size = RDE(bs) * sizeof(fat_dentry_t);
    9991033        rootp->idx = ridxp;
    10001034        ridxp->nodep = rootp;
    10011035        rootp->bp = rfn;
    10021036        rfn->data = rootp;
    1003 
     1037       
    10041038        fibril_mutex_unlock(&ridxp->lock);
    10051039
    1006         async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
    1007 }
    1008 
    1009 void 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 
    1014 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
    1015 {
    1016         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1040        *index = ridxp->index;
     1041        *size = rootp->size;
     1042        *linkcnt = rootp->lnkcnt;
     1043
     1044        return EOK;
     1045}
     1046
     1047static int fat_unmounted(devmap_handle_t devmap_handle)
     1048{
    10171049        fs_node_t *fn;
    10181050        fat_node_t *nodep;
     
    10201052
    10211053        rc = fat_root_get(&fn, devmap_handle);
    1022         if (rc != EOK) {
    1023                 async_answer_0(rid, rc);
    1024                 return;
    1025         }
     1054        if (rc != EOK)
     1055                return rc;
    10261056        nodep = FAT_NODE(fn);
    10271057
     
    10321062        if (nodep->refcnt != 2) {
    10331063                (void) fat_node_put(fn);
    1034                 async_answer_0(rid, EBUSY);
    1035                 return;
    1036         }
    1037 
     1064                return EBUSY;
     1065        }
     1066       
    10381067        /*
    10391068         * Put the root node and force it to the FAT free node list.
     
    10521081        block_fini(devmap_handle);
    10531082
    1054         async_answer_0(rid, EOK);
    1055 }
    1056 
    1057 void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
    1058 {
    1059         libfs_unmount(&fat_libfs_ops, rid, request);
    1060 }
    1061 
    1062 void 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 
    1067 void 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));
     1083        return EOK;
     1084}
     1085
     1086static int
     1087fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
     1088    size_t *rbytes)
     1089{
    10731090        fs_node_t *fn;
    10741091        fat_node_t *nodep;
     
    10791096
    10801097        rc = fat_node_get(&fn, devmap_handle, index);
    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         }
     1098        if (rc != EOK)
     1099                return rc;
     1100        if (!fn)
     1101                return ENOENT;
    10891102        nodep = FAT_NODE(fn);
    10901103
     
    10941107                fat_node_put(fn);
    10951108                async_answer_0(callid, EINVAL);
    1096                 async_answer_0(rid, EINVAL);
    1097                 return;
     1109                return EINVAL;
    10981110        }
    10991111
     
    11181130                                fat_node_put(fn);
    11191131                                async_answer_0(callid, rc);
    1120                                 async_answer_0(rid, rc);
    1121                                 return;
     1132                                return rc;
    11221133                        }
    11231134                        (void) async_data_read_finalize(callid,
     
    11261137                        if (rc != EOK) {
    11271138                                fat_node_put(fn);
    1128                                 async_answer_0(rid, rc);
    1129                                 return;
     1139                                return rc;
    11301140                        }
    11311141                }
    11321142        } else {
     1143                unsigned bnum;
    11331144                aoff64_t spos = pos;
    1134                 char name[FAT_LFN_NAME_SIZE];
     1145                char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    11351146                fat_dentry_t *d;
    11361147
     
    11391150                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    11401151
    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;
     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                }
     1193miss:
     1194                rc = fat_node_put(fn);
     1195                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     1196                *rbytes = 0;
     1197                return rc != EOK ? rc : ENOENT;
    11531198
    11541199err:
    11551200                (void) fat_node_put(fn);
    11561201                async_answer_0(callid, rc);
    1157                 async_answer_0(rid, rc);
    1158                 return;
    1159 
    1160 miss:
    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;
     1202                return rc;
    11681203
    11691204hit:
    1170                 pos = di.pos;
    1171                 rc = fat_directory_close(&di);
    1172                 if (rc!=EOK)
    1173                         goto err;
    11741205                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    1175                 bytes = (pos - spos)+1;
     1206                bytes = (pos - spos) + 1;
    11761207        }
    11771208
    11781209        rc = fat_node_put(fn);
    1179         async_answer_1(rid, rc, (sysarg_t)bytes);
    1180 }
    1181 
    1182 void 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));
     1210        *rbytes = bytes;
     1211        return rc;
     1212}
     1213
     1214static int
     1215fat_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
     1216    size_t *wbytes, aoff64_t *nsize)
     1217{
    11881218        fs_node_t *fn;
    11891219        fat_node_t *nodep;
    11901220        fat_bs_t *bs;
    1191         size_t bytes, size;
     1221        size_t bytes;
    11921222        block_t *b;
    11931223        aoff64_t boundary;
    11941224        int flags = BLOCK_FLAGS_NONE;
    11951225        int rc;
    1196 
     1226       
    11971227        rc = fat_node_get(&fn, devmap_handle, index);
    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         }
     1228        if (rc != EOK)
     1229                return rc;
     1230        if (!fn)
     1231                return ENOENT;
    12061232        nodep = FAT_NODE(fn);
    1207 
     1233       
    12081234        ipc_callid_t callid;
    12091235        size_t len;
     
    12111237                (void) fat_node_put(fn);
    12121238                async_answer_0(callid, EINVAL);
    1213                 async_answer_0(rid, EINVAL);
    1214                 return;
     1239                return EINVAL;
    12151240        }
    12161241
     
    12221247         * but this one greatly simplifies fat_write(). Note that we can afford
    12231248         * to do this because the client must be ready to handle the return
    1224          * value signalizing a smaller number of bytes written.
    1225          */
     1249         * value signalizing a smaller number of bytes written. 
     1250         */ 
    12261251        bytes = min(len, BPS(bs) - pos % BPS(bs));
    12271252        if (bytes == BPS(bs))
    12281253                flags |= BLOCK_FLAGS_NOREAD;
    1229 
     1254       
    12301255        boundary = ROUND_UP(nodep->size, BPC(bs));
    12311256        if (pos < boundary) {
     
    12401265                        (void) fat_node_put(fn);
    12411266                        async_answer_0(callid, rc);
    1242                         async_answer_0(rid, rc);
    1243                         return;
     1267                        return rc;
    12441268                }
    12451269                rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
     
    12471271                        (void) fat_node_put(fn);
    12481272                        async_answer_0(callid, rc);
    1249                         async_answer_0(rid, rc);
    1250                         return;
     1273                        return rc;
    12511274                }
    12521275                (void) async_data_write_finalize(callid,
     
    12561279                if (rc != EOK) {
    12571280                        (void) fat_node_put(fn);
    1258                         async_answer_0(rid, rc);
    1259                         return;
     1281                        return rc;
    12601282                }
    12611283                if (pos + bytes > nodep->size) {
     
    12631285                        nodep->dirty = true;    /* need to sync node */
    12641286                }
    1265                 size = nodep->size;
     1287                *wbytes = bytes;
     1288                *nsize = nodep->size;
    12661289                rc = fat_node_put(fn);
    1267                 async_answer_2(rid, rc, bytes, nodep->size);
    1268                 return;
     1290                return rc;
    12691291        } else {
    12701292                /*
     
    12731295                 */
    12741296                unsigned nclsts;
    1275                 fat_cluster_t mcl, lcl;
    1276 
     1297                fat_cluster_t mcl, lcl; 
     1298 
    12771299                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    12781300                /* create an independent chain of nclsts clusters in all FATs */
     
    12821304                        (void) fat_node_put(fn);
    12831305                        async_answer_0(callid, rc);
    1284                         async_answer_0(rid, rc);
    1285                         return;
     1306                        return rc;
    12861307                }
    12871308                /* zero fill any gaps */
     
    12911312                        (void) fat_node_put(fn);
    12921313                        async_answer_0(callid, rc);
    1293                         async_answer_0(rid, rc);
    1294                         return;
     1314                        return rc;
    12951315                }
    12961316                rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
     
    13001320                        (void) fat_node_put(fn);
    13011321                        async_answer_0(callid, rc);
    1302                         async_answer_0(rid, rc);
    1303                         return;
     1322                        return rc;
    13041323                }
    13051324                (void) async_data_write_finalize(callid,
     
    13101329                        (void) fat_free_clusters(bs, devmap_handle, mcl);
    13111330                        (void) fat_node_put(fn);
    1312                         async_answer_0(rid, rc);
    1313                         return;
     1331                        return rc;
    13141332                }
    13151333                /*
     
    13211339                        (void) fat_free_clusters(bs, devmap_handle, mcl);
    13221340                        (void) fat_node_put(fn);
    1323                         async_answer_0(rid, rc);
    1324                         return;
    1325                 }
    1326                 nodep->size = size = pos + bytes;
     1341                        return rc;
     1342                }
     1343                *nsize = nodep->size = pos + bytes;
     1344                rc = fat_node_put(fn);
    13271345                nodep->dirty = true;            /* need to sync node */
    1328                 rc = fat_node_put(fn);
    1329                 async_answer_2(rid, rc, bytes, size);
    1330                 return;
    1331         }
    1332 }
    1333 
    1334 void 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));
     1346                *wbytes = bytes;
     1347                return rc;
     1348        }
     1349}
     1350
     1351static int
     1352fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
     1353{
    13401354        fs_node_t *fn;
    13411355        fat_node_t *nodep;
     
    13441358
    13451359        rc = fat_node_get(&fn, devmap_handle, index);
    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         }
     1360        if (rc != EOK)
     1361                return rc;
     1362        if (!fn)
     1363                return ENOENT;
    13541364        nodep = FAT_NODE(fn);
    13551365
     
    13701380                nodep->size = size;
    13711381                nodep->dirty = true;            /* need to sync node */
    1372                 rc = EOK;
     1382                rc = EOK;       
    13731383        } else {
    13741384                /*
     
    13911401                nodep->size = size;
    13921402                nodep->dirty = true;            /* need to sync node */
    1393                 rc = EOK;
     1403                rc = EOK;       
    13941404        }
    13951405out:
    13961406        fat_node_put(fn);
    1397         async_answer_0(rid, rc);
    1398         return;
    1399 }
    1400 
    1401 void fat_close(ipc_callid_t rid, ipc_call_t *request)
    1402 {
    1403         async_answer_0(rid, EOK);
    1404 }
    1405 
    1406 void 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);
     1407        return rc;
     1408}
     1409
     1410static int fat_close(devmap_handle_t devmap_handle, fs_index_t index)
     1411{
     1412        return EOK;
     1413}
     1414
     1415static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index)
     1416{
    14101417        fs_node_t *fn;
    14111418        fat_node_t *nodep;
     
    14131420
    14141421        rc = fat_node_get(&fn, devmap_handle, index);
    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         }
     1422        if (rc != EOK)
     1423                return rc;
     1424        if (!fn)
     1425                return ENOENT;
    14231426
    14241427        nodep = FAT_NODE(fn);
     
    14301433
    14311434        rc = fat_destroy_node(fn);
    1432         async_answer_0(rid, rc);
    1433 }
    1434 
    1435 void 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 
    1440 void 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 
    1445 void 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 
     1435        return rc;
     1436}
     1437
     1438static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index)
     1439{
    14501440        fs_node_t *fn;
    14511441        int rc = fat_node_get(&fn, devmap_handle, index);
    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 
     1442        if (rc != EOK)
     1443                return rc;
     1444        if (!fn)
     1445                return ENOENT;
     1446       
    14611447        fat_node_t *nodep = FAT_NODE(fn);
    1462 
     1448       
    14631449        nodep->dirty = true;
    14641450        rc = fat_node_sync(nodep);
    1465 
     1451       
    14661452        fat_node_put(fn);
    1467         async_answer_0(rid, rc);
    1468 }
     1453        return rc;
     1454}
     1455
     1456vfs_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};
    14691466
    14701467/**
Note: See TracChangeset for help on using the changeset viewer.