Ignore:
File:
1 edited

Legend:

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

    r1313ee9 rcca29e3c  
    5252#include <adt/list.h>
    5353#include <assert.h>
    54 #include <fibril_synch.h>
     54#include <fibril_sync.h>
    5555#include <sys/mman.h>
    5656#include <align.h>
     
    6565static LIST_INITIALIZE(ffn_head);
    6666
    67 /*
    68  * Forward declarations of FAT libfs operations.
    69  */
    70 static int fat_root_get(fs_node_t **, dev_handle_t);
    71 static int fat_match(fs_node_t **, fs_node_t *, const char *);
    72 static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
    73 static int fat_node_open(fs_node_t *);
    74 static int fat_node_put(fs_node_t *);
    75 static int fat_create_node(fs_node_t **, dev_handle_t, int);
    76 static int fat_destroy_node(fs_node_t *);
    77 static int fat_link(fs_node_t *, fs_node_t *, const char *);
    78 static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
    79 static int fat_has_children(bool *, fs_node_t *);
    80 static fs_index_t fat_index_get(fs_node_t *);
    81 static size_t fat_size_get(fs_node_t *);
    82 static unsigned fat_lnkcnt_get(fs_node_t *);
    83 static char fat_plb_get_char(unsigned);
    84 static bool fat_is_directory(fs_node_t *);
    85 static bool fat_is_file(fs_node_t *node);
    86 static dev_handle_t fat_device_get(fs_node_t *node);
    87 
    88 /*
    89  * Helper functions.
    90  */
    9167static void fat_node_initialize(fat_node_t *node)
    9268{
     
    10278}
    10379
    104 static int fat_node_sync(fat_node_t *node)
     80static void fat_node_sync(fat_node_t *node)
    10581{
    10682        block_t *b;
     
    12096        rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
    12197            (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
    122         if (rc != EOK)
    123                 return rc;
     98        assert(rc == EOK);
    12499
    125100        d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
     
    136111        b->dirty = true;                /* need to sync block */
    137112        rc = block_put(b);
    138         return rc;
    139 }
    140 
    141 static int fat_node_get_new(fat_node_t **nodepp)
     113        assert(rc == EOK);
     114}
     115
     116static fat_node_t *fat_node_get_new(void)
    142117{
    143118        fs_node_t *fn;
    144119        fat_node_t *nodep;
    145         int rc;
    146120
    147121        fibril_mutex_lock(&ffn_mutex);
     
    159133                list_remove(&nodep->ffn_link);
    160134                fibril_mutex_unlock(&ffn_mutex);
    161                 if (nodep->dirty) {
    162                         rc = fat_node_sync(nodep);
    163                         if (rc != EOK) {
    164                                 idxp_tmp->nodep = NULL;
    165                                 fibril_mutex_unlock(&nodep->lock);
    166                                 fibril_mutex_unlock(&idxp_tmp->lock);
    167                                 free(nodep->bp);
    168                                 free(nodep);
    169                                 return rc;
    170                         }
    171                 }
     135                if (nodep->dirty)
     136                        fat_node_sync(nodep);
    172137                idxp_tmp->nodep = NULL;
    173138                fibril_mutex_unlock(&nodep->lock);
     
    180145                fn = (fs_node_t *)malloc(sizeof(fs_node_t));
    181146                if (!fn)
    182                         return ENOMEM;
     147                        return NULL;
    183148                nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
    184149                if (!nodep) {
    185150                        free(fn);
    186                         return ENOMEM;
     151                        return NULL;
    187152                }
    188153        }
     
    192157        nodep->bp = fn;
    193158       
    194         *nodepp = nodep;
    195         return EOK;
     159        return nodep;
    196160}
    197161
     
    200164 * @param idxp          Locked index structure.
    201165 */
    202 static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp)
     166static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
    203167{
    204168        block_t *b;
     
    217181                 */
    218182                fibril_mutex_lock(&idxp->nodep->lock);
    219                 if (!idxp->nodep->refcnt++) {
    220                         fibril_mutex_lock(&ffn_mutex);
     183                if (!idxp->nodep->refcnt++)
    221184                        list_remove(&idxp->nodep->ffn_link);
    222                         fibril_mutex_unlock(&ffn_mutex);
    223                 }
    224185                fibril_mutex_unlock(&idxp->nodep->lock);
    225                 *nodepp = idxp->nodep;
    226                 return EOK;
     186                return idxp->nodep;
    227187        }
    228188
     
    233193        assert(idxp->pfc);
    234194
    235         rc = fat_node_get_new(&nodep);
    236         if (rc != EOK)
    237                 return rc;
     195        nodep = fat_node_get_new();
     196        if (!nodep)
     197                return NULL;
    238198
    239199        bs = block_bb_get(idxp->dev_handle);
     
    245205        rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
    246206            (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
    247         if (rc != EOK) {
    248                 (void) fat_node_put(FS_NODE(nodep));
    249                 return rc;
    250         }
     207        assert(rc == EOK);
    251208
    252209        d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
     
    266223                rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
    267224                    uint16_t_le2host(d->firstc));
    268                 if (rc != EOK) {
    269                         (void) fat_node_put(FS_NODE(nodep));
    270                         return rc;
    271                 }
     225                assert(rc == EOK);
    272226                nodep->size = bps * spc * clusters;
    273227        } else {
     
    280234
    281235        rc = block_put(b);
    282         if (rc != EOK) {
    283                 (void) fat_node_put(FS_NODE(nodep));
    284                 return rc;
    285         }
     236        assert(rc == EOK);
    286237
    287238        /* Link the idx structure with the node structure. */
     
    289240        idxp->nodep = nodep;
    290241
    291         *nodepp = nodep;
    292         return EOK;
    293 }
     242        return nodep;
     243}
     244
     245/*
     246 * Forward declarations of FAT libfs operations.
     247 */
     248static fs_node_t *fat_node_get(dev_handle_t, fs_index_t);
     249static void fat_node_put(fs_node_t *);
     250static fs_node_t *fat_create_node(dev_handle_t, int);
     251static int fat_destroy_node(fs_node_t *);
     252static int fat_link(fs_node_t *, fs_node_t *, const char *);
     253static int fat_unlink(fs_node_t *, fs_node_t *, const char *);
     254static fs_node_t *fat_match(fs_node_t *, const char *);
     255static fs_index_t fat_index_get(fs_node_t *);
     256static size_t fat_size_get(fs_node_t *);
     257static unsigned fat_lnkcnt_get(fs_node_t *);
     258static bool fat_has_children(fs_node_t *);
     259static fs_node_t *fat_root_get(dev_handle_t);
     260static char fat_plb_get_char(unsigned);
     261static bool fat_is_directory(fs_node_t *);
     262static bool fat_is_file(fs_node_t *node);
    294263
    295264/*
     
    297266 */
    298267
    299 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
    300 {
    301         return fat_node_get(rfn, dev_handle, 0);
    302 }
    303 
    304 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     268/** Instantiate a FAT in-core node. */
     269fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
     270{
     271        fat_node_t *nodep;
     272        fat_idx_t *idxp;
     273
     274        idxp = fat_idx_get_by_index(dev_handle, index);
     275        if (!idxp)
     276                return NULL;
     277        /* idxp->lock held */
     278        nodep = fat_node_get_core(idxp);
     279        fibril_mutex_unlock(&idxp->lock);
     280        return FS_NODE(nodep);
     281}
     282
     283void fat_node_put(fs_node_t *fn)
     284{
     285        fat_node_t *nodep = FAT_NODE(fn);
     286        bool destroy = false;
     287
     288        fibril_mutex_lock(&nodep->lock);
     289        if (!--nodep->refcnt) {
     290                if (nodep->idx) {
     291                        fibril_mutex_lock(&ffn_mutex);
     292                        list_append(&nodep->ffn_link, &ffn_head);
     293                        fibril_mutex_unlock(&ffn_mutex);
     294                } else {
     295                        /*
     296                         * The node does not have any index structure associated
     297                         * with itself. This can only mean that we are releasing
     298                         * the node after a failed attempt to allocate the index
     299                         * structure for it.
     300                         */
     301                        destroy = true;
     302                }
     303        }
     304        fibril_mutex_unlock(&nodep->lock);
     305        if (destroy) {
     306                free(nodep->bp);
     307                free(nodep);
     308        }
     309}
     310
     311fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags)
     312{
     313        fat_idx_t *idxp;
     314        fat_node_t *nodep;
     315        fat_bs_t *bs;
     316        fat_cluster_t mcl, lcl;
     317        uint16_t bps;
     318        int rc;
     319
     320        bs = block_bb_get(dev_handle);
     321        bps = uint16_t_le2host(bs->bps);
     322        if (flags & L_DIRECTORY) {
     323                /* allocate a cluster */
     324                rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
     325                if (rc != EOK)
     326                        return NULL;
     327        }
     328
     329        nodep = fat_node_get_new();
     330        if (!nodep) {
     331                (void) fat_free_clusters(bs, dev_handle, mcl);
     332                return NULL;
     333        }
     334        idxp = fat_idx_get_new(dev_handle);
     335        if (!idxp) {
     336                (void) fat_free_clusters(bs, dev_handle, mcl); 
     337                fat_node_put(FS_NODE(nodep));
     338                return NULL;
     339        }
     340        /* idxp->lock held */
     341        if (flags & L_DIRECTORY) {
     342                /* Populate the new cluster with unused dentries. */
     343                rc = fat_zero_cluster(bs, dev_handle, mcl);
     344                assert(rc == EOK);
     345                nodep->type = FAT_DIRECTORY;
     346                nodep->firstc = mcl;
     347                nodep->size = bps * bs->spc;
     348        } else {
     349                nodep->type = FAT_FILE;
     350                nodep->firstc = FAT_CLST_RES0;
     351                nodep->size = 0;
     352        }
     353        nodep->lnkcnt = 0;      /* not linked anywhere */
     354        nodep->refcnt = 1;
     355        nodep->dirty = true;
     356
     357        nodep->idx = idxp;
     358        idxp->nodep = nodep;
     359
     360        fibril_mutex_unlock(&idxp->lock);
     361        return FS_NODE(nodep);
     362}
     363
     364int fat_destroy_node(fs_node_t *fn)
     365{
     366        fat_node_t *nodep = FAT_NODE(fn);
     367        fat_bs_t *bs;
     368        int rc = EOK;
     369
     370        /*
     371         * The node is not reachable from the file system. This means that the
     372         * link count should be zero and that the index structure cannot be
     373         * found in the position hash. Obviously, we don't need to lock the node
     374         * nor its index structure.
     375         */
     376        assert(nodep->lnkcnt == 0);
     377
     378        /*
     379         * The node may not have any children.
     380         */
     381        assert(fat_has_children(fn) == false);
     382
     383        bs = block_bb_get(nodep->idx->dev_handle);
     384        if (nodep->firstc != FAT_CLST_RES0) {
     385                assert(nodep->size);
     386                /* Free all clusters allocated to the node. */
     387                rc = fat_free_clusters(bs, nodep->idx->dev_handle,
     388                    nodep->firstc);
     389        }
     390
     391        fat_idx_destroy(nodep->idx);
     392        free(nodep->bp);
     393        free(nodep);
     394        return rc;
     395}
     396
     397int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     398{
     399        fat_node_t *parentp = FAT_NODE(pfn);
     400        fat_node_t *childp = FAT_NODE(cfn);
     401        fat_dentry_t *d;
     402        fat_bs_t *bs;
     403        block_t *b;
     404        unsigned i, j;
     405        uint16_t bps;
     406        unsigned dps;
     407        unsigned blocks;
     408        fat_cluster_t mcl, lcl;
     409        int rc;
     410
     411        fibril_mutex_lock(&childp->lock);
     412        if (childp->lnkcnt == 1) {
     413                /*
     414                 * On FAT, we don't support multiple hard links.
     415                 */
     416                fibril_mutex_unlock(&childp->lock);
     417                return EMLINK;
     418        }
     419        assert(childp->lnkcnt == 0);
     420        fibril_mutex_unlock(&childp->lock);
     421
     422        if (!fat_dentry_name_verify(name)) {
     423                /*
     424                 * Attempt to create unsupported name.
     425                 */
     426                return ENOTSUP;
     427        }
     428
     429        /*
     430         * Get us an unused parent node's dentry or grow the parent and allocate
     431         * a new one.
     432         */
     433       
     434        fibril_mutex_lock(&parentp->idx->lock);
     435        bs = block_bb_get(parentp->idx->dev_handle);
     436        bps = uint16_t_le2host(bs->bps);
     437        dps = bps / sizeof(fat_dentry_t);
     438
     439        blocks = parentp->size / bps;
     440
     441        for (i = 0; i < blocks; i++) {
     442                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     443                assert(rc == EOK);
     444                for (j = 0; j < dps; j++) {
     445                        d = ((fat_dentry_t *)b->data) + j;
     446                        switch (fat_classify_dentry(d)) {
     447                        case FAT_DENTRY_SKIP:
     448                        case FAT_DENTRY_VALID:
     449                                /* skipping used and meta entries */
     450                                continue;
     451                        case FAT_DENTRY_FREE:
     452                        case FAT_DENTRY_LAST:
     453                                /* found an empty slot */
     454                                goto hit;
     455                        }
     456                }
     457                rc = block_put(b);
     458                assert(rc == EOK);
     459        }
     460        j = 0;
     461       
     462        /*
     463         * We need to grow the parent in order to create a new unused dentry.
     464         */
     465        if (parentp->firstc == FAT_CLST_ROOT) {
     466                /* Can't grow the root directory. */
     467                fibril_mutex_unlock(&parentp->idx->lock);
     468                return ENOSPC;
     469        }
     470        rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
     471        if (rc != EOK) {
     472                fibril_mutex_unlock(&parentp->idx->lock);
     473                return rc;
     474        }
     475        rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
     476        assert(rc == EOK);
     477        rc = fat_append_clusters(bs, parentp, mcl);
     478        assert(rc == EOK);
     479        parentp->size += bps * bs->spc;
     480        parentp->dirty = true;          /* need to sync node */
     481        rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
     482        assert(rc == EOK);
     483        d = (fat_dentry_t *)b->data;
     484
     485hit:
     486        /*
     487         * At this point we only establish the link between the parent and the
     488         * child.  The dentry, except of the name and the extension, will remain
     489         * uninitialized until the corresponding node is synced. Thus the valid
     490         * dentry data is kept in the child node structure.
     491         */
     492        memset(d, 0, sizeof(fat_dentry_t));
     493        fat_dentry_name_set(d, name);
     494        b->dirty = true;                /* need to sync block */
     495        rc = block_put(b);
     496        assert(rc == EOK);
     497        fibril_mutex_unlock(&parentp->idx->lock);
     498
     499        fibril_mutex_lock(&childp->idx->lock);
     500       
     501        /*
     502         * If possible, create the Sub-directory Identifier Entry and the
     503         * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
     504         * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
     505         * not use them anyway, so this is rather a sign of our good will.
     506         */
     507        rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
     508        assert(rc == EOK);
     509        d = (fat_dentry_t *)b->data;
     510        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     511            str_cmp(d->name, FAT_NAME_DOT) == 0) {
     512                memset(d, 0, sizeof(fat_dentry_t));
     513                str_cpy(d->name, 8, FAT_NAME_DOT);
     514                str_cpy(d->ext, 3, FAT_EXT_PAD);
     515                d->attr = FAT_ATTR_SUBDIR;
     516                d->firstc = host2uint16_t_le(childp->firstc);
     517                /* TODO: initialize also the date/time members. */
     518        }
     519        d++;
     520        if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
     521            str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
     522                memset(d, 0, sizeof(fat_dentry_t));
     523                str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
     524                str_cpy(d->ext, 3, FAT_EXT_PAD);
     525                d->attr = FAT_ATTR_SUBDIR;
     526                d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
     527                    host2uint16_t_le(FAT_CLST_RES0) :
     528                    host2uint16_t_le(parentp->firstc);
     529                /* TODO: initialize also the date/time members. */
     530        }
     531        b->dirty = true;                /* need to sync block */
     532        rc = block_put(b);
     533        assert(rc == EOK);
     534
     535        childp->idx->pfc = parentp->firstc;
     536        childp->idx->pdi = i * dps + j;
     537        fibril_mutex_unlock(&childp->idx->lock);
     538
     539        fibril_mutex_lock(&childp->lock);
     540        childp->lnkcnt = 1;
     541        childp->dirty = true;           /* need to sync node */
     542        fibril_mutex_unlock(&childp->lock);
     543
     544        /*
     545         * Hash in the index structure into the position hash.
     546         */
     547        fat_idx_hashin(childp->idx);
     548
     549        return EOK;
     550}
     551
     552int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     553{
     554        fat_node_t *parentp = FAT_NODE(pfn);
     555        fat_node_t *childp = FAT_NODE(cfn);
     556        fat_bs_t *bs;
     557        fat_dentry_t *d;
     558        uint16_t bps;
     559        block_t *b;
     560        int rc;
     561
     562        if (!parentp)
     563                return EBUSY;
     564       
     565        if (fat_has_children(cfn))
     566                return ENOTEMPTY;
     567
     568        fibril_mutex_lock(&parentp->lock);
     569        fibril_mutex_lock(&childp->lock);
     570        assert(childp->lnkcnt == 1);
     571        fibril_mutex_lock(&childp->idx->lock);
     572        bs = block_bb_get(childp->idx->dev_handle);
     573        bps = uint16_t_le2host(bs->bps);
     574
     575        rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc,
     576            (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
     577            BLOCK_FLAGS_NONE);
     578        assert(rc == EOK);
     579        d = (fat_dentry_t *)b->data +
     580            (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
     581        /* mark the dentry as not-currently-used */
     582        d->name[0] = FAT_DENTRY_ERASED;
     583        b->dirty = true;                /* need to sync block */
     584        rc = block_put(b);
     585        assert(rc == EOK);
     586
     587        /* remove the index structure from the position hash */
     588        fat_idx_hashout(childp->idx);
     589        /* clear position information */
     590        childp->idx->pfc = FAT_CLST_RES0;
     591        childp->idx->pdi = 0;
     592        fibril_mutex_unlock(&childp->idx->lock);
     593        childp->lnkcnt = 0;
     594        childp->dirty = true;
     595        fibril_mutex_unlock(&childp->lock);
     596        fibril_mutex_unlock(&parentp->lock);
     597
     598        return EOK;
     599}
     600
     601fs_node_t *fat_match(fs_node_t *pfn, const char *component)
    305602{
    306603        fat_bs_t *bs;
     
    322619        for (i = 0; i < blocks; i++) {
    323620                rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    324                 if (rc != EOK) {
    325                         fibril_mutex_unlock(&parentp->idx->lock);
    326                         return rc;
    327                 }
     621                assert(rc == EOK);
    328622                for (j = 0; j < dps; j++) {
    329623                        d = ((fat_dentry_t *)b->data) + j;
     
    333627                                continue;
    334628                        case FAT_DENTRY_LAST:
    335                                 /* miss */
    336629                                rc = block_put(b);
     630                                assert(rc == EOK);
    337631                                fibril_mutex_unlock(&parentp->idx->lock);
    338                                 *rfn = NULL;
    339                                 return rc;
     632                                return NULL;
    340633                        default:
    341634                        case FAT_DENTRY_VALID:
     
    362655                                         */
    363656                                        rc = block_put(b);
    364                                         return (rc == EOK) ? ENOMEM : rc;
     657                                        assert(rc == EOK);
     658                                        return NULL;
    365659                                }
    366                                 rc = fat_node_get_core(&nodep, idx);
     660                                nodep = fat_node_get_core(idx);
    367661                                fibril_mutex_unlock(&idx->lock);
    368                                 if (rc != EOK) {
    369                                         (void) block_put(b);
    370                                         return rc;
    371                                 }
    372                                 *rfn = FS_NODE(nodep);
    373662                                rc = block_put(b);
    374                                 if (rc != EOK)
    375                                         (void) fat_node_put(*rfn);
    376                                 return rc;
     663                                assert(rc == EOK);
     664                                return FS_NODE(nodep);
    377665                        }
    378666                }
    379667                rc = block_put(b);
    380                 if (rc != EOK) {
    381                         fibril_mutex_unlock(&parentp->idx->lock);
    382                         return rc;
    383                 }
     668                assert(rc == EOK);
    384669        }
    385670
    386671        fibril_mutex_unlock(&parentp->idx->lock);
    387         *rfn = NULL;
    388         return EOK;
    389 }
    390 
    391 /** Instantiate a FAT in-core node. */
    392 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
    393 {
    394         fat_node_t *nodep;
    395         fat_idx_t *idxp;
    396         int rc;
    397 
    398         idxp = fat_idx_get_by_index(dev_handle, index);
    399         if (!idxp) {
    400                 *rfn = NULL;
    401                 return EOK;
    402         }
    403         /* idxp->lock held */
    404         rc = fat_node_get_core(&nodep, idxp);
    405         fibril_mutex_unlock(&idxp->lock);
    406         if (rc == EOK)
    407                 *rfn = FS_NODE(nodep);
    408         return rc;
    409 }
    410 
    411 int fat_node_open(fs_node_t *fn)
    412 {
    413         /*
    414          * Opening a file is stateless, nothing
    415          * to be done here.
    416          */
    417         return EOK;
    418 }
    419 
    420 int fat_node_put(fs_node_t *fn)
    421 {
    422         fat_node_t *nodep = FAT_NODE(fn);
    423         bool destroy = false;
    424 
    425         fibril_mutex_lock(&nodep->lock);
    426         if (!--nodep->refcnt) {
    427                 if (nodep->idx) {
    428                         fibril_mutex_lock(&ffn_mutex);
    429                         list_append(&nodep->ffn_link, &ffn_head);
    430                         fibril_mutex_unlock(&ffn_mutex);
    431                 } else {
    432                         /*
    433                          * The node does not have any index structure associated
    434                          * with itself. This can only mean that we are releasing
    435                          * the node after a failed attempt to allocate the index
    436                          * structure for it.
    437                          */
    438                         destroy = true;
    439                 }
    440         }
    441         fibril_mutex_unlock(&nodep->lock);
    442         if (destroy) {
    443                 free(nodep->bp);
    444                 free(nodep);
    445         }
    446         return EOK;
    447 }
    448 
    449 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags)
    450 {
    451         fat_idx_t *idxp;
    452         fat_node_t *nodep;
    453         fat_bs_t *bs;
    454         fat_cluster_t mcl, lcl;
    455         uint16_t bps;
    456         int rc;
    457 
    458         bs = block_bb_get(dev_handle);
    459         bps = uint16_t_le2host(bs->bps);
    460         if (flags & L_DIRECTORY) {
    461                 /* allocate a cluster */
    462                 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl);
    463                 if (rc != EOK)
    464                         return rc;
    465                 /* populate the new cluster with unused dentries */
    466                 rc = fat_zero_cluster(bs, dev_handle, mcl);
    467                 if (rc != EOK) {
    468                         (void) fat_free_clusters(bs, dev_handle, mcl);
    469                         return rc;
    470                 }
    471         }
    472 
    473         rc = fat_node_get_new(&nodep);
    474         if (rc != EOK) {
    475                 (void) fat_free_clusters(bs, dev_handle, mcl);
    476                 return rc;
    477         }
    478         rc = fat_idx_get_new(&idxp, dev_handle);
    479         if (rc != EOK) {
    480                 (void) fat_free_clusters(bs, dev_handle, mcl); 
    481                 (void) fat_node_put(FS_NODE(nodep));
    482                 return rc;
    483         }
    484         /* idxp->lock held */
    485         if (flags & L_DIRECTORY) {
    486                 nodep->type = FAT_DIRECTORY;
    487                 nodep->firstc = mcl;
    488                 nodep->size = bps * bs->spc;
    489         } else {
    490                 nodep->type = FAT_FILE;
    491                 nodep->firstc = FAT_CLST_RES0;
    492                 nodep->size = 0;
    493         }
    494         nodep->lnkcnt = 0;      /* not linked anywhere */
    495         nodep->refcnt = 1;
    496         nodep->dirty = true;
    497 
    498         nodep->idx = idxp;
    499         idxp->nodep = nodep;
    500 
    501         fibril_mutex_unlock(&idxp->lock);
    502         *rfn = FS_NODE(nodep);
    503         return EOK;
    504 }
    505 
    506 int fat_destroy_node(fs_node_t *fn)
    507 {
    508         fat_node_t *nodep = FAT_NODE(fn);
    509         fat_bs_t *bs;
    510         bool has_children;
    511         int rc;
    512 
    513         /*
    514          * The node is not reachable from the file system. This means that the
    515          * link count should be zero and that the index structure cannot be
    516          * found in the position hash. Obviously, we don't need to lock the node
    517          * nor its index structure.
    518          */
    519         assert(nodep->lnkcnt == 0);
    520 
    521         /*
    522          * The node may not have any children.
    523          */
    524         rc = fat_has_children(&has_children, fn);
    525         if (rc != EOK)
    526                 return rc;
    527         assert(!has_children);
    528 
    529         bs = block_bb_get(nodep->idx->dev_handle);
    530         if (nodep->firstc != FAT_CLST_RES0) {
    531                 assert(nodep->size);
    532                 /* Free all clusters allocated to the node. */
    533                 rc = fat_free_clusters(bs, nodep->idx->dev_handle,
    534                     nodep->firstc);
    535         }
    536 
    537         fat_idx_destroy(nodep->idx);
    538         free(nodep->bp);
    539         free(nodep);
    540         return rc;
    541 }
    542 
    543 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
    544 {
    545         fat_node_t *parentp = FAT_NODE(pfn);
    546         fat_node_t *childp = FAT_NODE(cfn);
    547         fat_dentry_t *d;
    548         fat_bs_t *bs;
    549         block_t *b;
    550         unsigned i, j;
    551         uint16_t bps;
    552         unsigned dps;
    553         unsigned blocks;
    554         fat_cluster_t mcl, lcl;
    555         int rc;
    556 
    557         fibril_mutex_lock(&childp->lock);
    558         if (childp->lnkcnt == 1) {
    559                 /*
    560                  * On FAT, we don't support multiple hard links.
    561                  */
    562                 fibril_mutex_unlock(&childp->lock);
    563                 return EMLINK;
    564         }
    565         assert(childp->lnkcnt == 0);
    566         fibril_mutex_unlock(&childp->lock);
    567 
    568         if (!fat_dentry_name_verify(name)) {
    569                 /*
    570                  * Attempt to create unsupported name.
    571                  */
    572                 return ENOTSUP;
    573         }
    574 
    575         /*
    576          * Get us an unused parent node's dentry or grow the parent and allocate
    577          * a new one.
    578          */
    579        
    580         fibril_mutex_lock(&parentp->idx->lock);
    581         bs = block_bb_get(parentp->idx->dev_handle);
    582         bps = uint16_t_le2host(bs->bps);
    583         dps = bps / sizeof(fat_dentry_t);
    584 
    585         blocks = parentp->size / bps;
    586 
    587         for (i = 0; i < blocks; i++) {
    588                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    589                 if (rc != EOK) {
    590                         fibril_mutex_unlock(&parentp->idx->lock);
    591                         return rc;
    592                 }
    593                 for (j = 0; j < dps; j++) {
    594                         d = ((fat_dentry_t *)b->data) + j;
    595                         switch (fat_classify_dentry(d)) {
    596                         case FAT_DENTRY_SKIP:
    597                         case FAT_DENTRY_VALID:
    598                                 /* skipping used and meta entries */
    599                                 continue;
    600                         case FAT_DENTRY_FREE:
    601                         case FAT_DENTRY_LAST:
    602                                 /* found an empty slot */
    603                                 goto hit;
    604                         }
    605                 }
    606                 rc = block_put(b);
    607                 if (rc != EOK) {
    608                         fibril_mutex_unlock(&parentp->idx->lock);
    609                         return rc;
    610                 }
    611         }
    612         j = 0;
    613        
    614         /*
    615          * We need to grow the parent in order to create a new unused dentry.
    616          */
    617         if (parentp->firstc == FAT_CLST_ROOT) {
    618                 /* Can't grow the root directory. */
    619                 fibril_mutex_unlock(&parentp->idx->lock);
    620                 return ENOSPC;
    621         }
    622         rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl);
    623         if (rc != EOK) {
    624                 fibril_mutex_unlock(&parentp->idx->lock);
    625                 return rc;
    626         }
    627         rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl);
    628         if (rc != EOK) {
    629                 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
    630                 fibril_mutex_unlock(&parentp->idx->lock);
    631                 return rc;
    632         }
    633         rc = fat_append_clusters(bs, parentp, mcl);
    634         if (rc != EOK) {
    635                 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl);
    636                 fibril_mutex_unlock(&parentp->idx->lock);
    637                 return rc;
    638         }
    639         parentp->size += bps * bs->spc;
    640         parentp->dirty = true;          /* need to sync node */
    641         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    642         if (rc != EOK) {
    643                 fibril_mutex_unlock(&parentp->idx->lock);
    644                 return rc;
    645         }
    646         d = (fat_dentry_t *)b->data;
    647 
    648 hit:
    649         /*
    650          * At this point we only establish the link between the parent and the
    651          * child.  The dentry, except of the name and the extension, will remain
    652          * uninitialized until the corresponding node is synced. Thus the valid
    653          * dentry data is kept in the child node structure.
    654          */
    655         memset(d, 0, sizeof(fat_dentry_t));
    656         fat_dentry_name_set(d, name);
    657         b->dirty = true;                /* need to sync block */
    658         rc = block_put(b);
    659         fibril_mutex_unlock(&parentp->idx->lock);
    660         if (rc != EOK)
    661                 return rc;
    662 
    663         fibril_mutex_lock(&childp->idx->lock);
    664        
    665         /*
    666          * If possible, create the Sub-directory Identifier Entry and the
    667          * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries
    668          * are not mandatory according to Standard ECMA-107 and HelenOS VFS does
    669          * not use them anyway, so this is rather a sign of our good will.
    670          */
    671         rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE);
    672         if (rc != EOK) {
    673                 /*
    674                  * Rather than returning an error, simply skip the creation of
    675                  * these two entries.
    676                  */
    677                 goto skip_dots;
    678         }
    679         d = (fat_dentry_t *)b->data;
    680         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    681             str_cmp(d->name, FAT_NAME_DOT) == 0) {
    682                 memset(d, 0, sizeof(fat_dentry_t));
    683                 str_cpy(d->name, 8, FAT_NAME_DOT);
    684                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    685                 d->attr = FAT_ATTR_SUBDIR;
    686                 d->firstc = host2uint16_t_le(childp->firstc);
    687                 /* TODO: initialize also the date/time members. */
    688         }
    689         d++;
    690         if (fat_classify_dentry(d) == FAT_DENTRY_LAST ||
    691             str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) {
    692                 memset(d, 0, sizeof(fat_dentry_t));
    693                 str_cpy(d->name, 8, FAT_NAME_DOT_DOT);
    694                 str_cpy(d->ext, 3, FAT_EXT_PAD);
    695                 d->attr = FAT_ATTR_SUBDIR;
    696                 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    697                     host2uint16_t_le(FAT_CLST_RES0) :
    698                     host2uint16_t_le(parentp->firstc);
    699                 /* TODO: initialize also the date/time members. */
    700         }
    701         b->dirty = true;                /* need to sync block */
    702         /*
    703          * Ignore the return value as we would have fallen through on error
    704          * anyway.
    705          */
    706         (void) block_put(b);
    707 skip_dots:
    708 
    709         childp->idx->pfc = parentp->firstc;
    710         childp->idx->pdi = i * dps + j;
    711         fibril_mutex_unlock(&childp->idx->lock);
    712 
    713         fibril_mutex_lock(&childp->lock);
    714         childp->lnkcnt = 1;
    715         childp->dirty = true;           /* need to sync node */
    716         fibril_mutex_unlock(&childp->lock);
    717 
    718         /*
    719          * Hash in the index structure into the position hash.
    720          */
    721         fat_idx_hashin(childp->idx);
    722 
    723         return EOK;
    724 }
    725 
    726 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    727 {
    728         fat_node_t *parentp = FAT_NODE(pfn);
    729         fat_node_t *childp = FAT_NODE(cfn);
    730         fat_bs_t *bs;
    731         fat_dentry_t *d;
    732         uint16_t bps;
    733         block_t *b;
    734         bool has_children;
    735         int rc;
    736 
    737         if (!parentp)
    738                 return EBUSY;
    739        
    740         rc = fat_has_children(&has_children, cfn);
    741         if (rc != EOK)
    742                 return rc;
    743         if (has_children)
    744                 return ENOTEMPTY;
    745 
    746         fibril_mutex_lock(&parentp->lock);
    747         fibril_mutex_lock(&childp->lock);
    748         assert(childp->lnkcnt == 1);
    749         fibril_mutex_lock(&childp->idx->lock);
    750         bs = block_bb_get(childp->idx->dev_handle);
    751         bps = uint16_t_le2host(bs->bps);
    752 
    753         rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc,
    754             (childp->idx->pdi * sizeof(fat_dentry_t)) / bps,
    755             BLOCK_FLAGS_NONE);
    756         if (rc != EOK)
    757                 goto error;
    758         d = (fat_dentry_t *)b->data +
    759             (childp->idx->pdi % (bps / sizeof(fat_dentry_t)));
    760         /* mark the dentry as not-currently-used */
    761         d->name[0] = FAT_DENTRY_ERASED;
    762         b->dirty = true;                /* need to sync block */
    763         rc = block_put(b);
    764         if (rc != EOK)
    765                 goto error;
    766 
    767         /* remove the index structure from the position hash */
    768         fat_idx_hashout(childp->idx);
    769         /* clear position information */
    770         childp->idx->pfc = FAT_CLST_RES0;
    771         childp->idx->pdi = 0;
    772         fibril_mutex_unlock(&childp->idx->lock);
    773         childp->lnkcnt = 0;
    774         childp->dirty = true;
    775         fibril_mutex_unlock(&childp->lock);
    776         fibril_mutex_unlock(&parentp->lock);
    777 
    778         return EOK;
    779 
    780 error:
    781         fibril_mutex_unlock(&parentp->idx->lock);
    782         fibril_mutex_unlock(&childp->lock);
    783         fibril_mutex_unlock(&childp->idx->lock);
    784         return rc;
    785 }
    786 
    787 int fat_has_children(bool *has_children, fs_node_t *fn)
     672        return NULL;
     673}
     674
     675fs_index_t fat_index_get(fs_node_t *fn)
     676{
     677        return FAT_NODE(fn)->idx->index;
     678}
     679
     680size_t fat_size_get(fs_node_t *fn)
     681{
     682        return FAT_NODE(fn)->size;
     683}
     684
     685unsigned fat_lnkcnt_get(fs_node_t *fn)
     686{
     687        return FAT_NODE(fn)->lnkcnt;
     688}
     689
     690bool fat_has_children(fs_node_t *fn)
    788691{
    789692        fat_bs_t *bs;
     
    796699        int rc;
    797700
    798         if (nodep->type != FAT_DIRECTORY) {
    799                 *has_children = false;
    800                 return EOK;
    801         }
     701        if (nodep->type != FAT_DIRECTORY)
     702                return false;
    802703       
    803704        fibril_mutex_lock(&nodep->idx->lock);
     
    812713       
    813714                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    814                 if (rc != EOK) {
    815                         fibril_mutex_unlock(&nodep->idx->lock);
    816                         return rc;
    817                 }
     715                assert(rc == EOK);
    818716                for (j = 0; j < dps; j++) {
    819717                        d = ((fat_dentry_t *)b->data) + j;
     
    824722                        case FAT_DENTRY_LAST:
    825723                                rc = block_put(b);
     724                                assert(rc == EOK);
    826725                                fibril_mutex_unlock(&nodep->idx->lock);
    827                                 *has_children = false;
    828                                 return rc;
     726                                return false;
    829727                        default:
    830728                        case FAT_DENTRY_VALID:
    831729                                rc = block_put(b);
     730                                assert(rc == EOK);
    832731                                fibril_mutex_unlock(&nodep->idx->lock);
    833                                 *has_children = true;
    834                                 return rc;
     732                                return true;
    835733                        }
     734                        rc = block_put(b);
     735                        assert(rc == EOK);
     736                        fibril_mutex_unlock(&nodep->idx->lock);
     737                        return true;
    836738                }
    837739                rc = block_put(b);
    838                 if (rc != EOK) {
    839                         fibril_mutex_unlock(&nodep->idx->lock);
    840                         return rc;     
    841                 }
     740                assert(rc == EOK);
    842741        }
    843742
    844743        fibril_mutex_unlock(&nodep->idx->lock);
    845         *has_children = false;
    846         return EOK;
    847 }
    848 
    849 
    850 fs_index_t fat_index_get(fs_node_t *fn)
    851 {
    852         return FAT_NODE(fn)->idx->index;
    853 }
    854 
    855 size_t fat_size_get(fs_node_t *fn)
    856 {
    857         return FAT_NODE(fn)->size;
    858 }
    859 
    860 unsigned fat_lnkcnt_get(fs_node_t *fn)
    861 {
    862         return FAT_NODE(fn)->lnkcnt;
     744        return false;
     745}
     746
     747fs_node_t *fat_root_get(dev_handle_t dev_handle)
     748{
     749        return fat_node_get(dev_handle, 0);
    863750}
    864751
     
    876763{
    877764        return FAT_NODE(fn)->type == FAT_FILE;
    878 }
    879 
    880 dev_handle_t fat_device_get(fs_node_t *node)
    881 {
    882         return 0;
    883765}
    884766
    885767/** libfs operations */
    886768libfs_ops_t fat_libfs_ops = {
    887         .root_get = fat_root_get,
    888769        .match = fat_match,
    889770        .node_get = fat_node_get,
    890         .node_open = fat_node_open,
    891771        .node_put = fat_node_put,
    892772        .create = fat_create_node,
     
    894774        .link = fat_link,
    895775        .unlink = fat_unlink,
    896         .has_children = fat_has_children,
    897776        .index_get = fat_index_get,
    898777        .size_get = fat_size_get,
    899778        .lnkcnt_get = fat_lnkcnt_get,
    900         .plb_get_char = fat_plb_get_char,
     779        .has_children = fat_has_children,
     780        .root_get = fat_root_get,
     781        .plb_get_char = fat_plb_get_char,
    901782        .is_directory = fat_is_directory,
    902         .is_file = fat_is_file,
    903         .device_get = fat_device_get
     783        .is_file = fat_is_file
    904784};
    905785
     
    920800        ipc_callid_t callid;
    921801        size_t size;
    922         if (!async_data_write_receive(&callid, &size)) {
     802        if (!ipc_data_write_receive(&callid, &size)) {
    923803                ipc_answer_0(callid, EINVAL);
    924804                ipc_answer_0(rid, EINVAL);
     
    931811                return;
    932812        }
    933         ipcarg_t retval = async_data_write_finalize(callid, opts, size);
     813        ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
    934814        if (retval != EOK) {
    935815                ipc_answer_0(rid, retval);
     
    953833
    954834        /* prepare the boot block */
    955         rc = block_bb_read(dev_handle, BS_BLOCK);
     835        rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE);
    956836        if (rc != EOK) {
    957837                block_fini(dev_handle);
     
    1049929        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1050930        off_t pos = (off_t)IPC_GET_ARG3(*request);
    1051         fs_node_t *fn;
     931        fs_node_t *fn = fat_node_get(dev_handle, index);
    1052932        fat_node_t *nodep;
    1053933        fat_bs_t *bs;
     
    1057937        int rc;
    1058938
    1059         rc = fat_node_get(&fn, dev_handle, index);
    1060         if (rc != EOK) {
    1061                 ipc_answer_0(rid, rc);
    1062                 return;
    1063         }
    1064939        if (!fn) {
    1065940                ipc_answer_0(rid, ENOENT);
     
    1070945        ipc_callid_t callid;
    1071946        size_t len;
    1072         if (!async_data_read_receive(&callid, &len)) {
     947        if (!ipc_data_read_receive(&callid, &len)) {
    1073948                fat_node_put(fn);
    1074949                ipc_answer_0(callid, EINVAL);
     
    1089964                        /* reading beyond the EOF */
    1090965                        bytes = 0;
    1091                         (void) async_data_read_finalize(callid, NULL, 0);
     966                        (void) ipc_data_read_finalize(callid, NULL, 0);
    1092967                } else {
    1093968                        bytes = min(len, bps - pos % bps);
     
    1095970                        rc = fat_block_get(&b, bs, nodep, pos / bps,
    1096971                            BLOCK_FLAGS_NONE);
    1097                         if (rc != EOK) {
    1098                                 fat_node_put(fn);
    1099                                 ipc_answer_0(callid, rc);
    1100                                 ipc_answer_0(rid, rc);
    1101                                 return;
    1102                         }
    1103                         (void) async_data_read_finalize(callid, b->data + pos % bps,
     972                        assert(rc == EOK);
     973                        (void) ipc_data_read_finalize(callid, b->data + pos % bps,
    1104974                            bytes);
    1105975                        rc = block_put(b);
    1106                         if (rc != EOK) {
    1107                                 fat_node_put(fn);
    1108                                 ipc_answer_0(rid, rc);
    1109                                 return;
    1110                         }
     976                        assert(rc == EOK);
    1111977                }
    1112978        } else {
     
    1132998                        rc = fat_block_get(&b, bs, nodep, bnum,
    1133999                            BLOCK_FLAGS_NONE);
    1134                         if (rc != EOK)
    1135                                 goto err;
     1000                        assert(rc == EOK);
    11361001                        for (o = pos % (bps / sizeof(fat_dentry_t));
    11371002                            o < bps / sizeof(fat_dentry_t);
     
    11441009                                case FAT_DENTRY_LAST:
    11451010                                        rc = block_put(b);
    1146                                         if (rc != EOK)
    1147                                                 goto err;
     1011                                        assert(rc == EOK);
    11481012                                        goto miss;
    11491013                                default:
    11501014                                case FAT_DENTRY_VALID:
    11511015                                        fat_dentry_name_get(d, name);
    1152                                         rc = block_put(b);
    1153                                         if (rc != EOK)
    1154                                                 goto err;
     1016                                        rc == block_put(b);
     1017                                        assert(rc == EOK);
    11551018                                        goto hit;
    11561019                                }
    11571020                        }
    11581021                        rc = block_put(b);
    1159                         if (rc != EOK)
    1160                                 goto err;
     1022                        assert(rc == EOK);
    11611023                        bnum++;
    11621024                }
    11631025miss:
    1164                 rc = fat_node_put(fn);
    1165                 ipc_answer_0(callid, rc != EOK ? rc : ENOENT);
    1166                 ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
    1167                 return;
    1168 
    1169 err:
    1170                 (void) fat_node_put(fn);
    1171                 ipc_answer_0(callid, rc);
    1172                 ipc_answer_0(rid, rc);
    1173                 return;
    1174 
     1026                fat_node_put(fn);
     1027                ipc_answer_0(callid, ENOENT);
     1028                ipc_answer_1(rid, ENOENT, 0);
     1029                return;
    11751030hit:
    1176                 (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1031                (void) ipc_data_read_finalize(callid, name, str_size(name) + 1);
    11771032                bytes = (pos - spos) + 1;
    11781033        }
    11791034
    1180         rc = fat_node_put(fn);
    1181         ipc_answer_1(rid, rc, (ipcarg_t)bytes);
     1035        fat_node_put(fn);
     1036        ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
    11821037}
    11831038
     
    11871042        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    11881043        off_t pos = (off_t)IPC_GET_ARG3(*request);
    1189         fs_node_t *fn;
     1044        fs_node_t *fn = fat_node_get(dev_handle, index);
    11901045        fat_node_t *nodep;
    11911046        fat_bs_t *bs;
    1192         size_t bytes, size;
     1047        size_t bytes;
    11931048        block_t *b;
    11941049        uint16_t bps;
     
    11991054        int rc;
    12001055       
    1201         rc = fat_node_get(&fn, dev_handle, index);
    1202         if (rc != EOK) {
    1203                 ipc_answer_0(rid, rc);
    1204                 return;
    1205         }
    12061056        if (!fn) {
    12071057                ipc_answer_0(rid, ENOENT);
     
    12121062        ipc_callid_t callid;
    12131063        size_t len;
    1214         if (!async_data_write_receive(&callid, &len)) {
    1215                 (void) fat_node_put(fn);
     1064        if (!ipc_data_write_receive(&callid, &len)) {
     1065                fat_node_put(fn);
    12161066                ipc_answer_0(callid, EINVAL);
    12171067                ipc_answer_0(rid, EINVAL);
     
    12441094                 */
    12451095                rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos);
    1246                 if (rc != EOK) {
    1247                         (void) fat_node_put(fn);
    1248                         ipc_answer_0(callid, rc);
    1249                         ipc_answer_0(rid, rc);
    1250                         return;
    1251                 }
     1096                assert(rc == EOK);
    12521097                rc = fat_block_get(&b, bs, nodep, pos / bps, flags);
    1253                 if (rc != EOK) {
    1254                         (void) fat_node_put(fn);
    1255                         ipc_answer_0(callid, rc);
    1256                         ipc_answer_0(rid, rc);
    1257                         return;
    1258                 }
    1259                 (void) async_data_write_finalize(callid, b->data + pos % bps,
     1098                assert(rc == EOK);
     1099                (void) ipc_data_write_finalize(callid, b->data + pos % bps,
    12601100                    bytes);
    12611101                b->dirty = true;                /* need to sync block */
    12621102                rc = block_put(b);
    1263                 if (rc != EOK) {
    1264                         (void) fat_node_put(fn);
    1265                         ipc_answer_0(rid, rc);
    1266                         return;
    1267                 }
     1103                assert(rc == EOK);
    12681104                if (pos + bytes > nodep->size) {
    12691105                        nodep->size = pos + bytes;
    12701106                        nodep->dirty = true;    /* need to sync node */
    12711107                }
    1272                 size = nodep->size;
    1273                 rc = fat_node_put(fn);
    1274                 ipc_answer_2(rid, rc, bytes, nodep->size);
     1108                ipc_answer_2(rid, EOK, bytes, nodep->size);     
     1109                fat_node_put(fn);
    12751110                return;
    12761111        } else {
     
    12791114                 * clusters for the node and zero them out.
    12801115                 */
     1116                int status;
    12811117                unsigned nclsts;
    12821118                fat_cluster_t mcl, lcl;
     
    12841120                nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc;
    12851121                /* create an independent chain of nclsts clusters in all FATs */
    1286                 rc = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);
    1287                 if (rc != EOK) {
     1122                status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);
     1123                if (status != EOK) {
    12881124                        /* could not allocate a chain of nclsts clusters */
    1289                         (void) fat_node_put(fn);
    1290                         ipc_answer_0(callid, rc);
    1291                         ipc_answer_0(rid, rc);
     1125                        fat_node_put(fn);
     1126                        ipc_answer_0(callid, status);
     1127                        ipc_answer_0(rid, status);
    12921128                        return;
    12931129                }
    12941130                /* zero fill any gaps */
    12951131                rc = fat_fill_gap(bs, nodep, mcl, pos);
    1296                 if (rc != EOK) {
    1297                         (void) fat_free_clusters(bs, dev_handle, mcl);
    1298                         (void) fat_node_put(fn);
    1299                         ipc_answer_0(callid, rc);
    1300                         ipc_answer_0(rid, rc);
    1301                         return;
    1302                 }
     1132                assert(rc == EOK);
    13031133                rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc,
    13041134                    flags);
    1305                 if (rc != EOK) {
    1306                         (void) fat_free_clusters(bs, dev_handle, mcl);
    1307                         (void) fat_node_put(fn);
    1308                         ipc_answer_0(callid, rc);
    1309                         ipc_answer_0(rid, rc);
    1310                         return;
    1311                 }
    1312                 (void) async_data_write_finalize(callid, b->data + pos % bps,
     1135                assert(rc == EOK);
     1136                (void) ipc_data_write_finalize(callid, b->data + pos % bps,
    13131137                    bytes);
    13141138                b->dirty = true;                /* need to sync block */
    13151139                rc = block_put(b);
    1316                 if (rc != EOK) {
    1317                         (void) fat_free_clusters(bs, dev_handle, mcl);
    1318                         (void) fat_node_put(fn);
    1319                         ipc_answer_0(rid, rc);
    1320                         return;
    1321                 }
     1140                assert(rc == EOK);
    13221141                /*
    13231142                 * Append the cluster chain starting in mcl to the end of the
     
    13251144                 */
    13261145                rc = fat_append_clusters(bs, nodep, mcl);
    1327                 if (rc != EOK) {
    1328                         (void) fat_free_clusters(bs, dev_handle, mcl);
    1329                         (void) fat_node_put(fn);
    1330                         ipc_answer_0(rid, rc);
    1331                         return;
    1332                 }
    1333                 nodep->size = size = pos + bytes;
     1146                assert(rc == EOK);
     1147                nodep->size = pos + bytes;
    13341148                nodep->dirty = true;            /* need to sync node */
    1335                 rc = fat_node_put(fn);
    1336                 ipc_answer_2(rid, rc, bytes, size);
     1149                ipc_answer_2(rid, EOK, bytes, nodep->size);
     1150                fat_node_put(fn);
    13371151                return;
    13381152        }
     
    13441158        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    13451159        size_t size = (off_t)IPC_GET_ARG3(*request);
    1346         fs_node_t *fn;
     1160        fs_node_t *fn = fat_node_get(dev_handle, index);
    13471161        fat_node_t *nodep;
    13481162        fat_bs_t *bs;
     
    13521166        int rc;
    13531167
    1354         rc = fat_node_get(&fn, dev_handle, index);
    1355         if (rc != EOK) {
    1356                 ipc_answer_0(rid, rc);
    1357                 return;
    1358         }
    13591168        if (!fn) {
    13601169                ipc_answer_0(rid, ENOENT);
     
    14201229        dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    14211230        fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1422         fs_node_t *fn;
    14231231        int rc;
    14241232
    1425         rc = fat_node_get(&fn, dev_handle, index);
    1426         if (rc != EOK) {
    1427                 ipc_answer_0(rid, rc);
    1428                 return;
    1429         }
     1233        fs_node_t *fn = fat_node_get(dev_handle, index);
    14301234        if (!fn) {
    14311235                ipc_answer_0(rid, ENOENT);
Note: See TracChangeset for help on using the changeset viewer.