Ignore:
File:
1 edited

Legend:

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

    rc7bbf029 rb69e4c0  
    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>
    4345#include <libblock.h>
    4446#include <ipc/services.h>
    45 #include <ipc/devmap.h>
     47#include <ipc/loc.h>
    4648#include <macros.h>
    4749#include <async.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_head);
     72static LIST_INITIALIZE(ffn_list);
    7073
    7174/*
    7275 * Forward declarations of FAT libfs operations.
    7376 */
    74 static int fat_root_get(fs_node_t **, devmap_handle_t);
     77static int fat_root_get(fs_node_t **, service_id_t);
    7578static int fat_match(fs_node_t **, fs_node_t *, const char *);
    76 static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
     79static int fat_node_get(fs_node_t **, service_id_t, fs_index_t);
    7780static int fat_node_open(fs_node_t *);
    7881static int fat_node_put(fs_node_t *);
    79 static int fat_create_node(fs_node_t **, devmap_handle_t, int);
     82static int fat_create_node(fs_node_t **, service_id_t, int);
    8083static int fat_destroy_node(fs_node_t *);
    8184static int fat_link(fs_node_t *, fs_node_t *, const char *);
     
    8588static aoff64_t fat_size_get(fs_node_t *);
    8689static unsigned fat_lnkcnt_get(fs_node_t *);
    87 static char fat_plb_get_char(unsigned);
    8890static bool fat_is_directory(fs_node_t *);
    8991static bool fat_is_file(fs_node_t *node);
    90 static devmap_handle_t fat_device_get(fs_node_t *node);
     92static service_id_t fat_service_get(fs_node_t *node);
    9193
    9294/*
     
    105107        node->dirty = false;
    106108        node->lastc_cached_valid = false;
    107         node->lastc_cached_value = FAT_CLST_LAST1;
     109        node->lastc_cached_value = 0;
    108110        node->currc_cached_valid = false;
    109111        node->currc_cached_bn = 0;
    110         node->currc_cached_value = FAT_CLST_LAST1;
     112        node->currc_cached_value = 0;
    111113}
    112114
     
    117119        fat_dentry_t *d;
    118120        int rc;
    119        
     121
    120122        assert(node->dirty);
    121123
    122         bs = block_bb_get(node->idx->devmap_handle);
    123        
     124        bs = block_bb_get(node->idx->service_id);
     125
    124126        /* Read the block that contains the dentry of interest. */
    125         rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     127        rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
    126128            NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    127129            BLOCK_FLAGS_NONE);
     
    137139                d->attr = FAT_ATTR_SUBDIR;
    138140        }
    139        
     141
    140142        /* TODO: update other fields? (e.g time fields) */
    141        
     143
    142144        b->dirty = true;                /* need to sync block */
    143145        rc = block_put(b);
     
    145147}
    146148
    147 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
    148 {
    149         link_t *lnk;
     149static int fat_node_fini_by_service_id(service_id_t service_id)
     150{
    150151        fat_node_t *nodep;
    151152        int rc;
     
    159160restart:
    160161        fibril_mutex_lock(&ffn_mutex);
    161         for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     162        list_foreach(ffn_list, lnk) {
    162163                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
    163164                if (!fibril_mutex_trylock(&nodep->lock)) {
     
    170171                        goto restart;
    171172                }
    172                 if (nodep->idx->devmap_handle != devmap_handle) {
     173                if (nodep->idx->service_id != service_id) {
    173174                        fibril_mutex_unlock(&nodep->idx->lock);
    174175                        fibril_mutex_unlock(&nodep->lock);
     
    196197                free(nodep);
    197198
    198                 /* Need to restart because we changed the ffn_head list. */
     199                /* Need to restart because we changed ffn_list. */
    199200                goto restart;
    200201        }
     
    211212
    212213        fibril_mutex_lock(&ffn_mutex);
    213         if (!list_empty(&ffn_head)) {
     214        if (!list_empty(&ffn_list)) {
    214215                /* Try to use a cached free node structure. */
    215216                fat_idx_t *idxp_tmp;
    216                 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
     217                nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
     218                    ffn_link);
    217219                if (!fibril_mutex_trylock(&nodep->lock))
    218220                        goto skip_cache;
     
    256258        fn->data = nodep;
    257259        nodep->bp = fn;
    258        
     260
    259261        *nodepp = nodep;
    260262        return EOK;
     
    292294         * We must instantiate the node from the file system.
    293295         */
    294        
     296
    295297        assert(idxp->pfc);
    296298
     
    299301                return rc;
    300302
    301         bs = block_bb_get(idxp->devmap_handle);
     303        bs = block_bb_get(idxp->service_id);
    302304
    303305        /* Read the block that contains the dentry of interest. */
    304         rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL,
     306        rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL,
    305307            (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    306308        if (rc != EOK) {
     
    310312
    311313        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     314        if (FAT_IS_FAT32(bs)) {
     315                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     316                    (uint16_t_le2host(d->firstc_hi) << 16);
     317        } else
     318                nodep->firstc = uint16_t_le2host(d->firstc);
     319
    312320        if (d->attr & FAT_ATTR_SUBDIR) {
    313                 /* 
     321                /*
    314322                 * The only directory which does not have this bit set is the
    315323                 * root directory itself. The root directory node is handled
     
    317325                 */
    318326                nodep->type = FAT_DIRECTORY;
     327
    319328                /*
    320329                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    322331                 * size of the directory by walking the FAT.
    323332                 */
    324                 uint16_t clusters;
    325                 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
    326                     uint16_t_le2host(d->firstc));
     333                uint32_t clusters;
     334                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
     335                    nodep->firstc);
    327336                if (rc != EOK) {
    328337                        (void) block_put(b);
     
    335344                nodep->size = uint32_t_le2host(d->size);
    336345        }
    337         nodep->firstc = uint16_t_le2host(d->firstc);
     346
    338347        nodep->lnkcnt = 1;
    339348        nodep->refcnt = 1;
     
    357366 */
    358367
    359 int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
    360 {
    361         return fat_node_get(rfn, devmap_handle, 0);
     368int fat_root_get(fs_node_t **rfn, service_id_t service_id)
     369{
     370        return fat_node_get(rfn, service_id, 0);
    362371}
    363372
    364373int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    365374{
    366         fat_bs_t *bs;
    367375        fat_node_t *parentp = FAT_NODE(pfn);
    368         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    369         unsigned i, j;
    370         unsigned blocks;
     376        char name[FAT_LFN_NAME_SIZE];
    371377        fat_dentry_t *d;
    372         devmap_handle_t devmap_handle;
    373         block_t *b;
     378        service_id_t service_id;
    374379        int rc;
    375380
    376381        fibril_mutex_lock(&parentp->idx->lock);
    377         devmap_handle = parentp->idx->devmap_handle;
     382        service_id = parentp->idx->service_id;
    378383        fibril_mutex_unlock(&parentp->idx->lock);
    379 
    380         bs = block_bb_get(devmap_handle);
    381         blocks = parentp->size / BPS(bs);
    382         for (i = 0; i < blocks; i++) {
    383                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    384                 if (rc != EOK)
    385                         return rc;
    386                 for (j = 0; j < DPS(bs); j++) {
    387                         d = ((fat_dentry_t *)b->data) + j;
    388                         switch (fat_classify_dentry(d)) {
    389                         case FAT_DENTRY_SKIP:
    390                         case FAT_DENTRY_FREE:
    391                                 continue;
    392                         case FAT_DENTRY_LAST:
    393                                 /* miss */
    394                                 rc = block_put(b);
    395                                 *rfn = NULL;
    396                                 return rc;
    397                         default:
    398                         case FAT_DENTRY_VALID:
    399                                 fat_dentry_name_get(d, name);
    400                                 break;
     384       
     385        fat_directory_t di;
     386        rc = fat_directory_open(parentp, &di);
     387        if (rc != EOK)
     388                return rc;
     389
     390        while (fat_directory_read(&di, name, &d) == EOK) {
     391                if (fat_dentry_namecmp(name, component) == 0) {
     392                        /* hit */
     393                        fat_node_t *nodep;
     394                        aoff64_t o = di.pos %
     395                            (BPS(di.bs) / sizeof(fat_dentry_t));
     396                        fat_idx_t *idx = fat_idx_get_by_pos(service_id,
     397                            parentp->firstc, di.bnum * DPS(di.bs) + o);
     398                        if (!idx) {
     399                                /*
     400                                 * Can happen if memory is low or if we
     401                                 * run out of 32-bit indices.
     402                                 */
     403                                rc = fat_directory_close(&di);
     404                                return (rc == EOK) ? ENOMEM : rc;
    401405                        }
    402                         if (fat_dentry_namecmp(name, component) == 0) {
    403                                 /* hit */
    404                                 fat_node_t *nodep;
    405                                 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
    406                                     parentp->firstc, i * DPS(bs) + j);
    407                                 if (!idx) {
    408                                         /*
    409                                          * Can happen if memory is low or if we
    410                                          * run out of 32-bit indices.
    411                                          */
    412                                         rc = block_put(b);
    413                                         return (rc == EOK) ? ENOMEM : rc;
    414                                 }
    415                                 rc = fat_node_get_core(&nodep, idx);
    416                                 fibril_mutex_unlock(&idx->lock);
    417                                 if (rc != EOK) {
    418                                         (void) block_put(b);
    419                                         return rc;
    420                                 }
    421                                 *rfn = FS_NODE(nodep);
    422                                 rc = block_put(b);
    423                                 if (rc != EOK)
    424                                         (void) fat_node_put(*rfn);
     406                        rc = fat_node_get_core(&nodep, idx);
     407                        fibril_mutex_unlock(&idx->lock);
     408                        if (rc != EOK) {
     409                                (void) fat_directory_close(&di);
    425410                                return rc;
    426411                        }
    427                 }
    428                 rc = block_put(b);
    429                 if (rc != EOK)
     412                        *rfn = FS_NODE(nodep);
     413                        rc = fat_directory_close(&di);
     414                        if (rc != EOK)
     415                                (void) fat_node_put(*rfn);
    430416                        return rc;
    431         }
    432 
     417                } else {
     418                        rc = fat_directory_next(&di);
     419                        if (rc != EOK)
     420                                break;
     421                }
     422        }
     423        (void) fat_directory_close(&di);
    433424        *rfn = NULL;
    434425        return EOK;
     
    436427
    437428/** Instantiate a FAT in-core node. */
    438 int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
     429int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
    439430{
    440431        fat_node_t *nodep;
     
    442433        int rc;
    443434
    444         idxp = fat_idx_get_by_index(devmap_handle, index);
     435        idxp = fat_idx_get_by_index(service_id, index);
    445436        if (!idxp) {
    446437                *rfn = NULL;
     
    473464                if (nodep->idx) {
    474465                        fibril_mutex_lock(&ffn_mutex);
    475                         list_append(&nodep->ffn_link, &ffn_head);
     466                        list_append(&nodep->ffn_link, &ffn_list);
    476467                        fibril_mutex_unlock(&ffn_mutex);
    477468                } else {
     
    493484}
    494485
    495 int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
     486int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    496487{
    497488        fat_idx_t *idxp;
     
    501492        int rc;
    502493
    503         bs = block_bb_get(devmap_handle);
     494        bs = block_bb_get(service_id);
    504495        if (flags & L_DIRECTORY) {
    505496                /* allocate a cluster */
    506                 rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);
     497                rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl);
    507498                if (rc != EOK)
    508499                        return rc;
    509500                /* populate the new cluster with unused dentries */
    510                 rc = fat_zero_cluster(bs, devmap_handle, mcl);
     501                rc = fat_zero_cluster(bs, service_id, mcl);
    511502                if (rc != EOK) {
    512                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     503                        (void) fat_free_clusters(bs, service_id, mcl);
    513504                        return rc;
    514505                }
     
    517508        rc = fat_node_get_new(&nodep);
    518509        if (rc != EOK) {
    519                 (void) fat_free_clusters(bs, devmap_handle, mcl);
    520                 return rc;
    521         }
    522         rc = fat_idx_get_new(&idxp, devmap_handle);
     510                (void) fat_free_clusters(bs, service_id, mcl);
     511                return rc;
     512        }
     513        rc = fat_idx_get_new(&idxp, service_id);
    523514        if (rc != EOK) {
    524                 (void) fat_free_clusters(bs, devmap_handle, mcl);       
     515                (void) fat_free_clusters(bs, service_id, mcl); 
    525516                (void) fat_node_put(FS_NODE(nodep));
    526517                return rc;
     
    571562        assert(!has_children);
    572563
    573         bs = block_bb_get(nodep->idx->devmap_handle);
     564        bs = block_bb_get(nodep->idx->service_id);
    574565        if (nodep->firstc != FAT_CLST_RES0) {
    575566                assert(nodep->size);
    576567                /* Free all clusters allocated to the node. */
    577                 rc = fat_free_clusters(bs, nodep->idx->devmap_handle,
     568                rc = fat_free_clusters(bs, nodep->idx->service_id,
    578569                    nodep->firstc);
    579570        }
     
    592583        fat_bs_t *bs;
    593584        block_t *b;
    594         unsigned i, j;
    595         unsigned blocks;
    596         fat_cluster_t mcl, lcl;
     585        fat_directory_t di;
     586        fat_dentry_t de;
    597587        int rc;
    598588
     
    608598        fibril_mutex_unlock(&childp->lock);
    609599
    610         if (!fat_dentry_name_verify(name)) {
    611                 /*
    612                  * Attempt to create unsupported name.
    613                  */
     600        if (!fat_valid_name(name))
    614601                return ENOTSUP;
    615         }
    616 
    617         /*
    618          * Get us an unused parent node's dentry or grow the parent and allocate
    619          * a new one.
    620          */
    621        
     602
    622603        fibril_mutex_lock(&parentp->idx->lock);
    623         bs = block_bb_get(parentp->idx->devmap_handle);
    624 
    625         blocks = parentp->size / BPS(bs);
    626 
    627         for (i = 0; i < blocks; i++) {
    628                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    629                 if (rc != EOK) {
    630                         fibril_mutex_unlock(&parentp->idx->lock);
    631                         return rc;
    632                 }
    633                 for (j = 0; j < DPS(bs); j++) {
    634                         d = ((fat_dentry_t *)b->data) + j;
    635                         switch (fat_classify_dentry(d)) {
    636                         case FAT_DENTRY_SKIP:
    637                         case FAT_DENTRY_VALID:
    638                                 /* skipping used and meta entries */
    639                                 continue;
    640                         case FAT_DENTRY_FREE:
    641                         case FAT_DENTRY_LAST:
    642                                 /* found an empty slot */
    643                                 goto hit;
    644                         }
    645                 }
    646                 rc = block_put(b);
    647                 if (rc != EOK) {
    648                         fibril_mutex_unlock(&parentp->idx->lock);
    649                         return rc;
    650                 }
    651         }
    652         j = 0;
    653        
    654         /*
    655          * We need to grow the parent in order to create a new unused dentry.
    656          */
    657         if (parentp->firstc == FAT_CLST_ROOT) {
    658                 /* Can't grow the root directory. */
    659                 fibril_mutex_unlock(&parentp->idx->lock);
    660                 return ENOSPC;
    661         }
    662         rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
     604        bs = block_bb_get(parentp->idx->service_id);
     605        rc = fat_directory_open(parentp, &di);
    663606        if (rc != EOK) {
    664607                fibril_mutex_unlock(&parentp->idx->lock);
    665608                return rc;
    666609        }
    667         rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
    668         if (rc != EOK) {
    669                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    670                 fibril_mutex_unlock(&parentp->idx->lock);
    671                 return rc;
    672         }
    673         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    674         if (rc != EOK) {
    675                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    676                 fibril_mutex_unlock(&parentp->idx->lock);
    677                 return rc;
    678         }
    679         parentp->size += BPS(bs) * SPC(bs);
    680         parentp->dirty = true;          /* need to sync node */
    681         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    682         if (rc != EOK) {
    683                 fibril_mutex_unlock(&parentp->idx->lock);
    684                 return rc;
    685         }
    686         d = (fat_dentry_t *)b->data;
    687 
    688 hit:
     610
    689611        /*
    690612         * At this point we only establish the link between the parent and the
     
    693615         * dentry data is kept in the child node structure.
    694616         */
    695         memset(d, 0, sizeof(fat_dentry_t));
    696         fat_dentry_name_set(d, name);
    697         b->dirty = true;                /* need to sync block */
    698         rc = block_put(b);
     617        memset(&de, 0, sizeof(fat_dentry_t));
     618
     619        rc = fat_directory_write(&di, name, &de);
     620        if (rc != EOK) {
     621                (void) fat_directory_close(&di);
     622                fibril_mutex_unlock(&parentp->idx->lock);
     623                return rc;
     624        }
     625        rc = fat_directory_close(&di);
     626        if (rc != EOK) {
     627                fibril_mutex_unlock(&parentp->idx->lock);
     628                return rc;
     629        }
     630
    699631        fibril_mutex_unlock(&parentp->idx->lock);
    700         if (rc != EOK)
    701                 return rc;
    702632
    703633        fibril_mutex_lock(&childp->idx->lock);
    704        
     634
    705635        if (childp->type == FAT_DIRECTORY) {
    706636                /*
     
    721651                d = (fat_dentry_t *) b->data;
    722652                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    723                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     653                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    724654                        memset(d, 0, sizeof(fat_dentry_t));
    725655                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    731661                d++;
    732662                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    733                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     663                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    734664                        memset(d, 0, sizeof(fat_dentry_t));
    735665                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    736666                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    737667                        d->attr = FAT_ATTR_SUBDIR;
    738                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    739                             host2uint16_t_le(FAT_CLST_RES0) :
     668                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     669                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    740670                            host2uint16_t_le(parentp->firstc);
    741671                        /* TODO: initialize also the date/time members. */
     
    751681
    752682        childp->idx->pfc = parentp->firstc;
    753         childp->idx->pdi = i * DPS(bs) + j;
     683        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    754684        fibril_mutex_unlock(&childp->idx->lock);
    755685
     
    771701        fat_node_t *parentp = FAT_NODE(pfn);
    772702        fat_node_t *childp = FAT_NODE(cfn);
    773         fat_bs_t *bs;
    774         fat_dentry_t *d;
    775         block_t *b;
    776703        bool has_children;
    777704        int rc;
     
    779706        if (!parentp)
    780707                return EBUSY;
    781        
     708
    782709        rc = fat_has_children(&has_children, cfn);
    783710        if (rc != EOK)
     
    790717        assert(childp->lnkcnt == 1);
    791718        fibril_mutex_lock(&childp->idx->lock);
    792         bs = block_bb_get(childp->idx->devmap_handle);
    793 
    794         rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
    795             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    796             BLOCK_FLAGS_NONE);
    797         if (rc != EOK)
     719       
     720        fat_directory_t di;
     721        rc = fat_directory_open(parentp, &di);
     722        if (rc != EOK)
    798723                goto error;
    799         d = (fat_dentry_t *)b->data +
    800             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    801         /* mark the dentry as not-currently-used */
    802         d->name[0] = FAT_DENTRY_ERASED;
    803         b->dirty = true;                /* need to sync block */
    804         rc = block_put(b);
     724        rc = fat_directory_seek(&di, childp->idx->pdi);
     725        if (rc != EOK)
     726                goto error;
     727        rc = fat_directory_erase(&di);
     728        if (rc != EOK)
     729                goto error;
     730        rc = fat_directory_close(&di);
    805731        if (rc != EOK)
    806732                goto error;
     
    821747
    822748error:
    823         fibril_mutex_unlock(&parentp->idx->lock);
     749        (void) fat_directory_close(&di);
     750        fibril_mutex_unlock(&childp->idx->lock);
    824751        fibril_mutex_unlock(&childp->lock);
    825         fibril_mutex_unlock(&childp->idx->lock);
     752        fibril_mutex_unlock(&parentp->lock);
    826753        return rc;
    827754}
     
    840767                return EOK;
    841768        }
    842        
     769
    843770        fibril_mutex_lock(&nodep->idx->lock);
    844         bs = block_bb_get(nodep->idx->devmap_handle);
     771        bs = block_bb_get(nodep->idx->service_id);
    845772
    846773        blocks = nodep->size / BPS(bs);
     
    848775        for (i = 0; i < blocks; i++) {
    849776                fat_dentry_t *d;
    850        
     777
    851778                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    852779                if (rc != EOK) {
     
    876803                if (rc != EOK) {
    877804                        fibril_mutex_unlock(&nodep->idx->lock);
    878                         return rc;     
     805                        return rc;
    879806                }
    880807        }
     
    901828}
    902829
    903 char fat_plb_get_char(unsigned pos)
    904 {
    905         return fat_reg.plb_ro[pos % PLB_SIZE];
    906 }
    907 
    908830bool fat_is_directory(fs_node_t *fn)
    909831{
     
    916838}
    917839
    918 devmap_handle_t fat_device_get(fs_node_t *node)
     840service_id_t fat_service_get(fs_node_t *node)
    919841{
    920842        return 0;
     
    936858        .size_get = fat_size_get,
    937859        .lnkcnt_get = fat_lnkcnt_get,
    938         .plb_get_char = fat_plb_get_char,
    939860        .is_directory = fat_is_directory,
    940861        .is_file = fat_is_file,
    941         .device_get = fat_device_get
     862        .service_get = fat_service_get
    942863};
    943864
    944865/*
    945  * VFS operations.
     866 * FAT VFS_OUT operations.
    946867 */
    947868
    948 void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
    949 {
    950         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    951         enum cache_mode cmode;
     869static int
     870fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
     871    aoff64_t *size, unsigned *linkcnt)
     872{
     873        enum cache_mode cmode = CACHE_MODE_WB;
    952874        fat_bs_t *bs;
    953        
    954         /* Accept the mount options */
    955         char *opts;
    956         int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
    957        
     875        fat_instance_t *instance;
     876        int rc;
     877
     878        instance = malloc(sizeof(fat_instance_t));
     879        if (!instance)
     880                return ENOMEM;
     881        instance->lfn_enabled = true;
     882
     883        /* Parse mount options. */
     884        char *mntopts = (char *) opts;
     885        char *saveptr;
     886        char *opt;
     887        while ((opt = strtok_r(mntopts, " ,", &saveptr)) != NULL) {
     888                if (str_cmp(opt, "wtcache") == 0)
     889                        cmode = CACHE_MODE_WT;
     890                else if (str_cmp(opt, "nolfn") == 0)
     891                        instance->lfn_enabled = false;
     892                mntopts = NULL;
     893        }
     894
     895        /* initialize libblock */
     896        rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
    958897        if (rc != EOK) {
    959                 async_answer_0(rid, rc);
    960                 return;
    961         }
    962 
    963         /* Check for option enabling write through. */
    964         if (str_cmp(opts, "wtcache") == 0)
    965                 cmode = CACHE_MODE_WT;
    966         else
    967                 cmode = CACHE_MODE_WB;
    968 
    969         free(opts);
    970 
    971         /* initialize libblock */
    972         rc = block_init(devmap_handle, BS_SIZE);
     898                free(instance);
     899                return rc;
     900        }
     901
     902        /* prepare the boot block */
     903        rc = block_bb_read(service_id, BS_BLOCK);
    973904        if (rc != EOK) {
    974                 async_answer_0(rid, rc);
    975                 return;
    976         }
    977 
    978         /* prepare the boot block */
    979         rc = block_bb_read(devmap_handle, BS_BLOCK);
    980         if (rc != EOK) {
    981                 block_fini(devmap_handle);
    982                 async_answer_0(rid, rc);
    983                 return;
     905                free(instance);
     906                block_fini(service_id);
     907                return rc;
    984908        }
    985909
    986910        /* get the buffer with the boot sector */
    987         bs = block_bb_get(devmap_handle);
     911        bs = block_bb_get(service_id);
    988912       
    989913        if (BPS(bs) != BS_SIZE) {
    990                 block_fini(devmap_handle);
    991                 async_answer_0(rid, ENOTSUP);
    992                 return;
     914                free(instance);
     915                block_fini(service_id);
     916                return ENOTSUP;
    993917        }
    994918
    995919        /* Initialize the block cache */
    996         rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode);
     920        rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
    997921        if (rc != EOK) {
    998                 block_fini(devmap_handle);
    999                 async_answer_0(rid, rc);
    1000                 return;
     922                free(instance);
     923                block_fini(service_id);
     924                return rc;
    1001925        }
    1002926
    1003927        /* Do some simple sanity checks on the file system. */
    1004         rc = fat_sanity_check(bs, devmap_handle);
     928        rc = fat_sanity_check(bs, service_id);
    1005929        if (rc != EOK) {
    1006                 (void) block_cache_fini(devmap_handle);
    1007                 block_fini(devmap_handle);
    1008                 async_answer_0(rid, rc);
    1009                 return;
    1010         }
    1011 
    1012         rc = fat_idx_init_by_devmap_handle(devmap_handle);
     930                free(instance);
     931                (void) block_cache_fini(service_id);
     932                block_fini(service_id);
     933                return rc;
     934        }
     935
     936        rc = fat_idx_init_by_service_id(service_id);
    1013937        if (rc != EOK) {
    1014                 (void) block_cache_fini(devmap_handle);
    1015                 block_fini(devmap_handle);
    1016                 async_answer_0(rid, rc);
    1017                 return;
     938                free(instance);
     939                (void) block_cache_fini(service_id);
     940                block_fini(service_id);
     941                return rc;
    1018942        }
    1019943
     
    1021945        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    1022946        if (!rfn) {
    1023                 (void) block_cache_fini(devmap_handle);
    1024                 block_fini(devmap_handle);
    1025                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1026                 async_answer_0(rid, ENOMEM);
    1027                 return;
    1028         }
     947                free(instance);
     948                (void) block_cache_fini(service_id);
     949                block_fini(service_id);
     950                fat_idx_fini_by_service_id(service_id);
     951                return ENOMEM;
     952        }
     953
    1029954        fs_node_initialize(rfn);
    1030955        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
    1031956        if (!rootp) {
     957                free(instance);
    1032958                free(rfn);
    1033                 (void) block_cache_fini(devmap_handle);
    1034                 block_fini(devmap_handle);
    1035                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1036                 async_answer_0(rid, ENOMEM);
    1037                 return;
     959                (void) block_cache_fini(service_id);
     960                block_fini(service_id);
     961                fat_idx_fini_by_service_id(service_id);
     962                return ENOMEM;
    1038963        }
    1039964        fat_node_initialize(rootp);
    1040965
    1041         fat_idx_t *ridxp = fat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0);
     966        fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
    1042967        if (!ridxp) {
     968                free(instance);
    1043969                free(rfn);
    1044970                free(rootp);
    1045                 (void) block_cache_fini(devmap_handle);
    1046                 block_fini(devmap_handle);
    1047                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1048                 async_answer_0(rid, ENOMEM);
    1049                 return;
     971                (void) block_cache_fini(service_id);
     972                block_fini(service_id);
     973                fat_idx_fini_by_service_id(service_id);
     974                return ENOMEM;
    1050975        }
    1051976        assert(ridxp->index == 0);
     
    1053978
    1054979        rootp->type = FAT_DIRECTORY;
    1055         rootp->firstc = FAT_CLST_ROOT;
     980        rootp->firstc = FAT_ROOT_CLST(bs);
    1056981        rootp->refcnt = 1;
    1057982        rootp->lnkcnt = 0;      /* FS root is not linked */
    1058         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     983
     984        if (FAT_IS_FAT32(bs)) {
     985                uint32_t clusters;
     986                rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     987                if (rc != EOK) {
     988                        fibril_mutex_unlock(&ridxp->lock);
     989                        free(instance);
     990                        free(rfn);
     991                        free(rootp);
     992                        (void) block_cache_fini(service_id);
     993                        block_fini(service_id);
     994                        fat_idx_fini_by_service_id(service_id);
     995                        return ENOTSUP;
     996                }
     997                rootp->size = BPS(bs) * SPC(bs) * clusters;
     998        } else
     999                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     1000
     1001        rc = fs_instance_create(service_id, instance);
     1002        if (rc != EOK) {
     1003                fibril_mutex_unlock(&ridxp->lock);
     1004                free(instance);
     1005                free(rfn);
     1006                free(rootp);
     1007                (void) block_cache_fini(service_id);
     1008                block_fini(service_id);
     1009                fat_idx_fini_by_service_id(service_id);
     1010                return rc;
     1011        }
     1012
    10591013        rootp->idx = ridxp;
    10601014        ridxp->nodep = rootp;
    10611015        rootp->bp = rfn;
    10621016        rfn->data = rootp;
    1063        
     1017
    10641018        fibril_mutex_unlock(&ridxp->lock);
    10651019
    1066         async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
    1067 }
    1068 
    1069 void fat_mount(ipc_callid_t rid, ipc_call_t *request)
    1070 {
    1071         libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1072 }
    1073 
    1074 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
    1075 {
    1076         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     1020        *index = ridxp->index;
     1021        *size = rootp->size;
     1022        *linkcnt = rootp->lnkcnt;
     1023
     1024        return EOK;
     1025}
     1026
     1027static int fat_update_fat32_fsinfo(service_id_t service_id)
     1028{
     1029        fat_bs_t *bs;
     1030        fat32_fsinfo_t *info;
     1031        block_t *b;
     1032        int rc;
     1033
     1034        bs = block_bb_get(service_id);
     1035        assert(FAT_IS_FAT32(bs));
     1036
     1037        rc = block_get(&b, service_id, uint16_t_le2host(bs->fat32.fsinfo_sec),
     1038            BLOCK_FLAGS_NONE);
     1039        if (rc != EOK)
     1040                return rc;
     1041
     1042        info = (fat32_fsinfo_t *) b->data;
     1043
     1044        if (bcmp(info->sig1, FAT32_FSINFO_SIG1, sizeof(info->sig1)) ||
     1045            bcmp(info->sig2, FAT32_FSINFO_SIG2, sizeof(info->sig2)) ||
     1046            bcmp(info->sig3, FAT32_FSINFO_SIG3, sizeof(info->sig3))) {
     1047                (void) block_put(b);
     1048                return EINVAL;
     1049        }
     1050
     1051        /* For now, invalidate the counter. */
     1052        info->free_clusters = host2uint16_t_le(-1);
     1053
     1054        b->dirty = true;
     1055        return block_put(b);
     1056}
     1057
     1058static int fat_unmounted(service_id_t service_id)
     1059{
    10771060        fs_node_t *fn;
    10781061        fat_node_t *nodep;
    1079         int rc;
    1080 
    1081         rc = fat_root_get(&fn, devmap_handle);
    1082         if (rc != EOK) {
    1083                 async_answer_0(rid, rc);
    1084                 return;
    1085         }
     1062        fat_bs_t *bs;
     1063        int rc;
     1064
     1065        bs = block_bb_get(service_id);
     1066
     1067        rc = fat_root_get(&fn, service_id);
     1068        if (rc != EOK)
     1069                return rc;
    10861070        nodep = FAT_NODE(fn);
    10871071
     
    10921076        if (nodep->refcnt != 2) {
    10931077                (void) fat_node_put(fn);
    1094                 async_answer_0(rid, EBUSY);
    1095                 return;
    1096         }
    1097        
     1078                return EBUSY;
     1079        }
     1080
     1081        if (FAT_IS_FAT32(bs)) {
     1082                /*
     1083                 * Attempt to update the FAT32 FS info.
     1084                 */
     1085                (void) fat_update_fat32_fsinfo(service_id);
     1086        }
     1087
    10981088        /*
    10991089         * Put the root node and force it to the FAT free node list.
     
    11071097         * stop using libblock for this instance.
    11081098         */
    1109         (void) fat_node_fini_by_devmap_handle(devmap_handle);
    1110         fat_idx_fini_by_devmap_handle(devmap_handle);
    1111         (void) block_cache_fini(devmap_handle);
    1112         block_fini(devmap_handle);
    1113 
    1114         async_answer_0(rid, EOK);
    1115 }
    1116 
    1117 void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
    1118 {
    1119         libfs_unmount(&fat_libfs_ops, rid, request);
    1120 }
    1121 
    1122 void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
    1123 {
    1124         libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1125 }
    1126 
    1127 void fat_read(ipc_callid_t rid, ipc_call_t *request)
    1128 {
    1129         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1130         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1131         aoff64_t pos =
    1132             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1099        (void) fat_node_fini_by_service_id(service_id);
     1100        fat_idx_fini_by_service_id(service_id);
     1101        (void) block_cache_fini(service_id);
     1102        block_fini(service_id);
     1103
     1104        void *data;
     1105        if (fs_instance_get(service_id, &data) == EOK) {
     1106                fs_instance_destroy(service_id);
     1107                free(data);
     1108        }
     1109
     1110        return EOK;
     1111}
     1112
     1113static int
     1114fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
     1115    size_t *rbytes)
     1116{
    11331117        fs_node_t *fn;
    11341118        fat_node_t *nodep;
     
    11381122        int rc;
    11391123
    1140         rc = fat_node_get(&fn, devmap_handle, index);
    1141         if (rc != EOK) {
    1142                 async_answer_0(rid, rc);
    1143                 return;
    1144         }
    1145         if (!fn) {
    1146                 async_answer_0(rid, ENOENT);
    1147                 return;
    1148         }
     1124        rc = fat_node_get(&fn, service_id, index);
     1125        if (rc != EOK)
     1126                return rc;
     1127        if (!fn)
     1128                return ENOENT;
    11491129        nodep = FAT_NODE(fn);
    11501130
     
    11541134                fat_node_put(fn);
    11551135                async_answer_0(callid, EINVAL);
    1156                 async_answer_0(rid, EINVAL);
    1157                 return;
    1158         }
    1159 
    1160         bs = block_bb_get(devmap_handle);
     1136                return EINVAL;
     1137        }
     1138
     1139        bs = block_bb_get(service_id);
    11611140
    11621141        if (nodep->type == FAT_FILE) {
     
    11781157                                fat_node_put(fn);
    11791158                                async_answer_0(callid, rc);
    1180                                 async_answer_0(rid, rc);
    1181                                 return;
     1159                                return rc;
    11821160                        }
    11831161                        (void) async_data_read_finalize(callid,
     
    11861164                        if (rc != EOK) {
    11871165                                fat_node_put(fn);
    1188                                 async_answer_0(rid, rc);
    1189                                 return;
     1166                                return rc;
    11901167                        }
    11911168                }
    11921169        } else {
    1193                 unsigned bnum;
    11941170                aoff64_t spos = pos;
    1195                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1171                char name[FAT_LFN_NAME_SIZE];
    11961172                fat_dentry_t *d;
    11971173
     
    12001176                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    12011177
    1202                 /*
    1203                  * Our strategy for readdir() is to use the position pointer as
    1204                  * an index into the array of all dentries. On entry, it points
    1205                  * to the first unread dentry. If we skip any dentries, we bump
    1206                  * the position pointer accordingly.
    1207                  */
    1208                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1209                 while (bnum < nodep->size / BPS(bs)) {
    1210                         aoff64_t o;
    1211 
    1212                         rc = fat_block_get(&b, bs, nodep, bnum,
    1213                             BLOCK_FLAGS_NONE);
    1214                         if (rc != EOK)
    1215                                 goto err;
    1216                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1217                             o < BPS(bs) / sizeof(fat_dentry_t);
    1218                             o++, pos++) {
    1219                                 d = ((fat_dentry_t *)b->data) + o;
    1220                                 switch (fat_classify_dentry(d)) {
    1221                                 case FAT_DENTRY_SKIP:
    1222                                 case FAT_DENTRY_FREE:
    1223                                         continue;
    1224                                 case FAT_DENTRY_LAST:
    1225                                         rc = block_put(b);
    1226                                         if (rc != EOK)
    1227                                                 goto err;
    1228                                         goto miss;
    1229                                 default:
    1230                                 case FAT_DENTRY_VALID:
    1231                                         fat_dentry_name_get(d, name);
    1232                                         rc = block_put(b);
    1233                                         if (rc != EOK)
    1234                                                 goto err;
    1235                                         goto hit;
    1236                                 }
    1237                         }
    1238                         rc = block_put(b);
    1239                         if (rc != EOK)
    1240                                 goto err;
    1241                         bnum++;
    1242                 }
    1243 miss:
    1244                 rc = fat_node_put(fn);
    1245                 async_answer_0(callid, rc != EOK ? rc : ENOENT);
    1246                 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
    1247                 return;
     1178                fat_directory_t di;
     1179                rc = fat_directory_open(nodep, &di);
     1180                if (rc != EOK)
     1181                        goto err;
     1182                rc = fat_directory_seek(&di, pos);
     1183                if (rc != EOK) {
     1184                        (void) fat_directory_close(&di);
     1185                        goto err;
     1186                }
     1187
     1188                rc = fat_directory_read(&di, name, &d);
     1189                if (rc == EOK)
     1190                        goto hit;
     1191                if (rc == ENOENT)
     1192                        goto miss;
    12481193
    12491194err:
    12501195                (void) fat_node_put(fn);
    12511196                async_answer_0(callid, rc);
    1252                 async_answer_0(rid, rc);
    1253                 return;
     1197                return rc;
     1198
     1199miss:
     1200                rc = fat_directory_close(&di);
     1201                if (rc != EOK)
     1202                        goto err;
     1203                rc = fat_node_put(fn);
     1204                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     1205                *rbytes = 0;
     1206                return rc != EOK ? rc : ENOENT;
    12541207
    12551208hit:
    1256                 (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1209                pos = di.pos;
     1210                rc = fat_directory_close(&di);
     1211                if (rc != EOK)
     1212                        goto err;
     1213                (void) async_data_read_finalize(callid, name,
     1214                    str_size(name) + 1);
    12571215                bytes = (pos - spos) + 1;
    12581216        }
    12591217
    12601218        rc = fat_node_put(fn);
    1261         async_answer_1(rid, rc, (sysarg_t)bytes);
    1262 }
    1263 
    1264 void fat_write(ipc_callid_t rid, ipc_call_t *request)
    1265 {
    1266         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1267         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1268         aoff64_t pos =
    1269             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1219        *rbytes = bytes;
     1220        return rc;
     1221}
     1222
     1223static int
     1224fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
     1225    size_t *wbytes, aoff64_t *nsize)
     1226{
    12701227        fs_node_t *fn;
    12711228        fat_node_t *nodep;
    12721229        fat_bs_t *bs;
    1273         size_t bytes, size;
     1230        size_t bytes;
    12741231        block_t *b;
    12751232        aoff64_t boundary;
     
    12771234        int rc;
    12781235       
    1279         rc = fat_node_get(&fn, devmap_handle, index);
    1280         if (rc != EOK) {
    1281                 async_answer_0(rid, rc);
    1282                 return;
    1283         }
    1284         if (!fn) {
    1285                 async_answer_0(rid, ENOENT);
    1286                 return;
    1287         }
     1236        rc = fat_node_get(&fn, service_id, index);
     1237        if (rc != EOK)
     1238                return rc;
     1239        if (!fn)
     1240                return ENOENT;
    12881241        nodep = FAT_NODE(fn);
    1289        
     1242
    12901243        ipc_callid_t callid;
    12911244        size_t len;
     
    12931246                (void) fat_node_put(fn);
    12941247                async_answer_0(callid, EINVAL);
    1295                 async_answer_0(rid, EINVAL);
    1296                 return;
    1297         }
    1298 
    1299         bs = block_bb_get(devmap_handle);
     1248                return EINVAL;
     1249        }
     1250
     1251        bs = block_bb_get(service_id);
    13001252
    13011253        /*
     
    13041256         * but this one greatly simplifies fat_write(). Note that we can afford
    13051257         * to do this because the client must be ready to handle the return
    1306          * value signalizing a smaller number of bytes written. 
    1307          */ 
     1258         * value signalizing a smaller number of bytes written.
     1259         */
    13081260        bytes = min(len, BPS(bs) - pos % BPS(bs));
    13091261        if (bytes == BPS(bs))
    13101262                flags |= BLOCK_FLAGS_NOREAD;
    1311        
     1263
    13121264        boundary = ROUND_UP(nodep->size, BPC(bs));
    13131265        if (pos < boundary) {
     
    13221274                        (void) fat_node_put(fn);
    13231275                        async_answer_0(callid, rc);
    1324                         async_answer_0(rid, rc);
    1325                         return;
     1276                        return rc;
    13261277                }
    13271278                rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
     
    13291280                        (void) fat_node_put(fn);
    13301281                        async_answer_0(callid, rc);
    1331                         async_answer_0(rid, rc);
    1332                         return;
     1282                        return rc;
    13331283                }
    13341284                (void) async_data_write_finalize(callid,
     
    13381288                if (rc != EOK) {
    13391289                        (void) fat_node_put(fn);
    1340                         async_answer_0(rid, rc);
    1341                         return;
     1290                        return rc;
    13421291                }
    13431292                if (pos + bytes > nodep->size) {
     
    13451294                        nodep->dirty = true;    /* need to sync node */
    13461295                }
    1347                 size = nodep->size;
     1296                *wbytes = bytes;
     1297                *nsize = nodep->size;
    13481298                rc = fat_node_put(fn);
    1349                 async_answer_2(rid, rc, bytes, nodep->size);
    1350                 return;
     1299                return rc;
    13511300        } else {
    13521301                /*
     
    13551304                 */
    13561305                unsigned nclsts;
    1357                 fat_cluster_t mcl, lcl; 
    1358  
     1306                fat_cluster_t mcl, lcl;
     1307
    13591308                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13601309                /* create an independent chain of nclsts clusters in all FATs */
    1361                 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);
     1310                rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl);
    13621311                if (rc != EOK) {
    13631312                        /* could not allocate a chain of nclsts clusters */
    13641313                        (void) fat_node_put(fn);
    13651314                        async_answer_0(callid, rc);
    1366                         async_answer_0(rid, rc);
    1367                         return;
     1315                        return rc;
    13681316                }
    13691317                /* zero fill any gaps */
    13701318                rc = fat_fill_gap(bs, nodep, mcl, pos);
    13711319                if (rc != EOK) {
    1372                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1320                        (void) fat_free_clusters(bs, service_id, mcl);
    13731321                        (void) fat_node_put(fn);
    13741322                        async_answer_0(callid, rc);
    1375                         async_answer_0(rid, rc);
    1376                         return;
    1377                 }
    1378                 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
     1323                        return rc;
     1324                }
     1325                rc = _fat_block_get(&b, bs, service_id, lcl, NULL,
    13791326                    (pos / BPS(bs)) % SPC(bs), flags);
    13801327                if (rc != EOK) {
    1381                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1328                        (void) fat_free_clusters(bs, service_id, mcl);
    13821329                        (void) fat_node_put(fn);
    13831330                        async_answer_0(callid, rc);
    1384                         async_answer_0(rid, rc);
    1385                         return;
     1331                        return rc;
    13861332                }
    13871333                (void) async_data_write_finalize(callid,
     
    13901336                rc = block_put(b);
    13911337                if (rc != EOK) {
    1392                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1338                        (void) fat_free_clusters(bs, service_id, mcl);
    13931339                        (void) fat_node_put(fn);
    1394                         async_answer_0(rid, rc);
    1395                         return;
     1340                        return rc;
    13961341                }
    13971342                /*
     
    14011346                rc = fat_append_clusters(bs, nodep, mcl, lcl);
    14021347                if (rc != EOK) {
    1403                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1348                        (void) fat_free_clusters(bs, service_id, mcl);
    14041349                        (void) fat_node_put(fn);
    1405                         async_answer_0(rid, rc);
    1406                         return;
    1407                 }
    1408                 nodep->size = size = pos + bytes;
     1350                        return rc;
     1351                }
     1352                *nsize = nodep->size = pos + bytes;
     1353                rc = fat_node_put(fn);
    14091354                nodep->dirty = true;            /* need to sync node */
    1410                 rc = fat_node_put(fn);
    1411                 async_answer_2(rid, rc, bytes, size);
    1412                 return;
    1413         }
    1414 }
    1415 
    1416 void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
    1417 {
    1418         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1419         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1420         aoff64_t size =
    1421             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1355                *wbytes = bytes;
     1356                return rc;
     1357        }
     1358}
     1359
     1360static int
     1361fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
     1362{
    14221363        fs_node_t *fn;
    14231364        fat_node_t *nodep;
     
    14251366        int rc;
    14261367
    1427         rc = fat_node_get(&fn, devmap_handle, index);
    1428         if (rc != EOK) {
    1429                 async_answer_0(rid, rc);
    1430                 return;
    1431         }
    1432         if (!fn) {
    1433                 async_answer_0(rid, ENOENT);
    1434                 return;
    1435         }
     1368        rc = fat_node_get(&fn, service_id, index);
     1369        if (rc != EOK)
     1370                return rc;
     1371        if (!fn)
     1372                return ENOENT;
    14361373        nodep = FAT_NODE(fn);
    14371374
    1438         bs = block_bb_get(devmap_handle);
     1375        bs = block_bb_get(service_id);
    14391376
    14401377        if (nodep->size == size) {
     
    14521389                nodep->size = size;
    14531390                nodep->dirty = true;            /* need to sync node */
    1454                 rc = EOK;       
     1391                rc = EOK;
    14551392        } else {
    14561393                /*
     
    14631400                } else {
    14641401                        fat_cluster_t lastc;
    1465                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
     1402                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    14661403                            &lastc, NULL, (size - 1) / BPC(bs));
    14671404                        if (rc != EOK)
     
    14731410                nodep->size = size;
    14741411                nodep->dirty = true;            /* need to sync node */
    1475                 rc = EOK;       
     1412                rc = EOK;
    14761413        }
    14771414out:
    14781415        fat_node_put(fn);
    1479         async_answer_0(rid, rc);
    1480         return;
    1481 }
    1482 
    1483 void fat_close(ipc_callid_t rid, ipc_call_t *request)
    1484 {
    1485         async_answer_0(rid, EOK);
    1486 }
    1487 
    1488 void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
    1489 {
    1490         devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
    1491         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
     1416        return rc;
     1417}
     1418
     1419static int fat_close(service_id_t service_id, fs_index_t index)
     1420{
     1421        return EOK;
     1422}
     1423
     1424static int fat_destroy(service_id_t service_id, fs_index_t index)
     1425{
    14921426        fs_node_t *fn;
    14931427        fat_node_t *nodep;
    14941428        int rc;
    14951429
    1496         rc = fat_node_get(&fn, devmap_handle, index);
    1497         if (rc != EOK) {
    1498                 async_answer_0(rid, rc);
    1499                 return;
    1500         }
    1501         if (!fn) {
    1502                 async_answer_0(rid, ENOENT);
    1503                 return;
    1504         }
     1430        rc = fat_node_get(&fn, service_id, index);
     1431        if (rc != EOK)
     1432                return rc;
     1433        if (!fn)
     1434                return ENOENT;
    15051435
    15061436        nodep = FAT_NODE(fn);
     
    15121442
    15131443        rc = fat_destroy_node(fn);
    1514         async_answer_0(rid, rc);
    1515 }
    1516 
    1517 void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
    1518 {
    1519         libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1520 }
    1521 
    1522 void fat_stat(ipc_callid_t rid, ipc_call_t *request)
    1523 {
    1524         libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1525 }
    1526 
    1527 void fat_sync(ipc_callid_t rid, ipc_call_t *request)
    1528 {
    1529         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1530         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1531        
     1444        return rc;
     1445}
     1446
     1447static int fat_sync(service_id_t service_id, fs_index_t index)
     1448{
    15321449        fs_node_t *fn;
    1533         int rc = fat_node_get(&fn, devmap_handle, index);
    1534         if (rc != EOK) {
    1535                 async_answer_0(rid, rc);
    1536                 return;
    1537         }
    1538         if (!fn) {
    1539                 async_answer_0(rid, ENOENT);
    1540                 return;
    1541         }
    1542        
     1450        int rc = fat_node_get(&fn, service_id, index);
     1451        if (rc != EOK)
     1452                return rc;
     1453        if (!fn)
     1454                return ENOENT;
     1455
    15431456        fat_node_t *nodep = FAT_NODE(fn);
    1544        
     1457
    15451458        nodep->dirty = true;
    15461459        rc = fat_node_sync(nodep);
    1547        
     1460
    15481461        fat_node_put(fn);
    1549         async_answer_0(rid, rc);
    1550 }
     1462        return rc;
     1463}
     1464
     1465vfs_out_ops_t fat_ops = {
     1466        .mounted = fat_mounted,
     1467        .unmounted = fat_unmounted,
     1468        .read = fat_read,
     1469        .write = fat_write,
     1470        .truncate = fat_truncate,
     1471        .close = fat_close,
     1472        .destroy = fat_destroy,
     1473        .sync = fat_sync,
     1474};
    15511475
    15521476/**
Note: See TracChangeset for help on using the changeset viewer.