Changeset 1787e527 in mainline for uspace/srv/fs/fat/fat_fat.c


Ignore:
Timestamp:
2009-11-16T21:22:54Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5ebdf94
Parents:
fcbd1be (diff), 9c70ed6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merged with head (unstable)

File:
1 edited

Legend:

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

    rfcbd1be r1787e527  
    6161 * @param dev_handle    Device handle of the device with the file.
    6262 * @param firstc        First cluster to start the walk with.
    63  * @param lastc         If non-NULL, output argument hodling the last cluster number visited.
     63 * @param lastc         If non-NULL, output argument hodling the last cluster
     64 *                      number visited.
     65 * @param numc          If non-NULL, output argument holding the number of
     66 *                      clusters seen during the walk.
    6467 * @param max_clusters  Maximum number of clusters to visit.   
    6568 *
    66  * @return              Number of clusters seen during the walk.
    67  */
    68 uint16_t
     69 * @return              EOK on success or a negative error code.
     70 */
     71int
    6972fat_cluster_walk(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
    70     fat_cluster_t *lastc, uint16_t max_clusters)
     73    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    7174{
    7275        block_t *b;
     
    7578        uint16_t clusters = 0;
    7679        fat_cluster_t clst = firstc;
     80        int rc;
    7781
    7882        bps = uint16_t_le2host(bs->bps);
     
    8387                if (lastc)
    8488                        *lastc = firstc;
    85                 return 0;
     89                if (numc)
     90                        *numc = 0;
     91                return EOK;
    8692        }
    8793
     
    96102                fidx = clst % (bps / sizeof(fat_cluster_t));
    97103                /* read FAT1 */
    98                 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     104                rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE);
     105                if (rc != EOK)
     106                        return rc;
    99107                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    100108                assert(clst != FAT_CLST_BAD);
    101                 block_put(b);
     109                rc = block_put(b);
     110                if (rc != EOK)
     111                        return rc;
    102112                clusters++;
    103113        }
     
    105115        if (lastc && clst < FAT_CLST_LAST1)
    106116                *lastc = clst;
    107 
    108         return clusters;
     117        if (numc)
     118                *numc = clusters;
     119
     120        return EOK;
    109121}
    110122
    111123/** Read block from file located on a FAT file system.
    112124 *
     125 * @param block         Pointer to a block pointer for storing result.
    113126 * @param bs            Buffer holding the boot sector of the file system.
    114127 * @param dev_handle    Device handle of the file system.
     
    118131 * @param flags         Flags passed to libblock.
    119132 *
    120  * @return              Block structure holding the requested block.
    121  */
    122 block_t *
    123 _fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc,
    124     bn_t bn, int flags)
    125 {
    126         block_t *b;
     133 * @return              EOK on success or a negative error code.
     134 */
     135int
     136_fat_block_get(block_t **block, fat_bs_t *bs, dev_handle_t dev_handle,
     137    fat_cluster_t firstc, bn_t bn, int flags)
     138{
    127139        unsigned bps;
    128140        unsigned rscnt;         /* block address of the first FAT */
     
    131143        unsigned sf;
    132144        unsigned ssa;           /* size of the system area */
    133         unsigned clusters, max_clusters;
     145        uint16_t clusters;
     146        unsigned max_clusters;
    134147        fat_cluster_t lastc;
     148        int rc;
    135149
    136150        bps = uint16_t_le2host(bs->bps);
     
    146160                /* root directory special case */
    147161                assert(bn < rds);
    148                 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags);
    149                 return b;
     162                rc = block_get(block, dev_handle, rscnt + bs->fatcnt * sf + bn,
     163                    flags);
     164                return rc;
    150165        }
    151166
    152167        max_clusters = bn / bs->spc;
    153         clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc,
     168        rc = fat_cluster_walk(bs, dev_handle, firstc, &lastc, &clusters,
    154169            max_clusters);
     170        if (rc != EOK)
     171                return rc;
    155172        assert(clusters == max_clusters);
    156173
    157         b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc +
    158             bn % bs->spc, flags);
    159 
    160         return b;
     174        rc = block_get(block, dev_handle,
     175            ssa + (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags);
     176
     177        return rc;
    161178}
    162179
     
    170187 *                      this argument is ignored.
    171188 * @param pos           Position in the last node block.
    172  */
    173 void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
     189 *
     190 * @return              EOK on success or a negative error code.
     191 */
     192int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos)
    174193{
    175194        uint16_t bps;
     
    177196        block_t *b;
    178197        off_t o, boundary;
     198        int rc;
    179199
    180200        bps = uint16_t_le2host(bs->bps);
     
    188208                int flags = (o % bps == 0) ?
    189209                    BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
    190                 b = fat_block_get(bs, nodep, o / bps, flags);
     210                rc = fat_block_get(&b, bs, nodep, o / bps, flags);
     211                if (rc != EOK)
     212                        return rc;
    191213                memset(b->data + o % bps, 0, bps - o % bps);
    192214                b->dirty = true;                /* need to sync node */
    193                 block_put(b);
     215                rc = block_put(b);
     216                if (rc != EOK)
     217                        return rc;
    194218        }
    195219       
    196220        if (o >= pos)
    197                 return;
     221                return EOK;
    198222       
    199223        /* zero out the initial part of the new cluster chain */
    200224        for (o = boundary; o < pos; o += bps) {
    201                 b = _fat_block_get(bs, nodep->idx->dev_handle, mcl,
     225                rc = _fat_block_get(&b, bs, nodep->idx->dev_handle, mcl,
    202226                    (o - boundary) / bps, BLOCK_FLAGS_NOREAD);
     227                if (rc != EOK)
     228                        return rc;
    203229                memset(b->data, 0, min(bps, pos - o));
    204230                b->dirty = true;                /* need to sync node */
    205                 block_put(b);
    206         }
     231                rc = block_put(b);
     232                if (rc != EOK)
     233                        return rc;
     234        }
     235
     236        return EOK;
    207237}
    208238
     
    212242 * @param dev_handle    Device handle for the file system.
    213243 * @param clst          Cluster which to get.
    214  *
    215  * @return              Value found in the cluster.
    216  */
    217 fat_cluster_t
    218 fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst)
     244 * @param value         Output argument holding the value of the cluster.
     245 *
     246 * @return              EOK or a negative error code.
     247 */
     248int
     249fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst,
     250    fat_cluster_t *value)
    219251{
    220252        block_t *b;
    221253        uint16_t bps;
    222254        uint16_t rscnt;
    223         fat_cluster_t *cp, value;
     255        fat_cluster_t *cp;
     256        int rc;
    224257
    225258        bps = uint16_t_le2host(bs->bps);
    226259        rscnt = uint16_t_le2host(bs->rscnt);
    227260
    228         b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps,
    229             BLOCK_FLAGS_NONE);
     261        rc = block_get(&b, dev_handle, rscnt +
     262            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     263        if (rc != EOK)
     264                return rc;
    230265        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    231         value = uint16_t_le2host(*cp);
    232         block_put(b);
    233        
    234         return value;
     266        *value = uint16_t_le2host(*cp);
     267        rc = block_put(b);
     268       
     269        return rc;
    235270}
    236271
     
    242277 * @param clst          Cluster which is to be set.
    243278 * @param value         Value to set the cluster with.
    244  */
    245 void
     279 *
     280 * @return              EOK on success or a negative error code.
     281 */
     282int
    246283fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno,
    247284    fat_cluster_t clst, fat_cluster_t value)
     
    252289        uint16_t sf;
    253290        fat_cluster_t *cp;
     291        int rc;
    254292
    255293        bps = uint16_t_le2host(bs->bps);
     
    258296
    259297        assert(fatno < bs->fatcnt);
    260         b = block_get(dev_handle, rscnt + sf * fatno +
     298        rc = block_get(&b, dev_handle, rscnt + sf * fatno +
    261299            (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);
     300        if (rc != EOK)
     301                return rc;
    262302        cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t));
    263303        *cp = host2uint16_t_le(value);
    264304        b->dirty = true;                /* need to sync block */
    265         block_put(b);
     305        rc = block_put(b);
     306        return rc;
    266307}
    267308
     
    272313 * @param lifo          Chain of allocated clusters.
    273314 * @param nclsts        Number of clusters in the lifo chain.
    274  */
    275 void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
     315 *
     316 * @return              EOK on success or a negative error code.
     317 */
     318int fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle,
    276319    fat_cluster_t *lifo, unsigned nclsts)
    277320{
    278321        uint8_t fatno;
    279322        unsigned c;
     323        int rc;
    280324
    281325        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    282326                for (c = 0; c < nclsts; c++) {
    283                         fat_set_cluster(bs, dev_handle, fatno, lifo[c],
     327                        rc = fat_set_cluster(bs, dev_handle, fatno, lifo[c],
    284328                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     329                        if (rc != EOK)
     330                                return rc;
    285331                }
    286332        }
     333
     334        return EOK;
    287335}
    288336
     
    311359        uint16_t rscnt;
    312360        uint16_t sf;
     361        uint16_t ts;
     362        unsigned rde;
     363        unsigned rds;
     364        unsigned ssa;
    313365        block_t *blk;
    314366        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    315367        unsigned found = 0;     /* top of the free cluster number stack */
    316368        unsigned b, c, cl;
     369        int rc;
    317370
    318371        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    323376        rscnt = uint16_t_le2host(bs->rscnt);
    324377        sf = uint16_t_le2host(bs->sec_per_fat);
     378        rde = uint16_t_le2host(bs->root_ent_max);
     379        ts = uint16_t_le2host(bs->totsec16);
     380
     381        rds = (sizeof(fat_dentry_t) * rde) / bps;
     382        rds += ((sizeof(fat_dentry_t) * rde) % bps != 0);
     383        ssa = rscnt + bs->fatcnt * sf + rds;
    325384       
    326385        /*
     
    329388        fibril_mutex_lock(&fat_alloc_lock);
    330389        for (b = 0, cl = 0; b < sf; b++) {
    331                 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     390                rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE);
     391                if (rc != EOK)
     392                        goto error;
    332393                for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) {
     394                        /*
     395                         * Check if the cluster is physically there. This check
     396                         * becomes necessary when the file system is created
     397                         * with fewer total sectors than how many is inferred
     398                         * from the size of the file allocation table.
     399                         */
     400                        if ((cl - 2) * bs->spc + ssa >= ts) {
     401                                rc = block_put(blk);
     402                                if (rc != EOK)
     403                                        goto error;
     404                                goto out;
     405                        }
     406
    333407                        fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    334408                        if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
     
    344418                                if (++found == nclsts) {
    345419                                        /* we are almost done */
    346                                         block_put(blk);
     420                                        rc = block_put(blk);
     421                                        if (rc != EOK)
     422                                                goto error;
    347423                                        /* update the shadow copies of FAT */
    348                                         fat_alloc_shadow_clusters(bs,
     424                                        rc = fat_alloc_shadow_clusters(bs,
    349425                                            dev_handle, lifo, nclsts);
     426                                        if (rc != EOK)
     427                                                goto error;
    350428                                        *mcl = lifo[found - 1];
    351429                                        *lcl = lifo[0];
     
    356434                        }
    357435                }
    358                 block_put(blk);
    359         }
     436                rc = block_put(blk);
     437                if (rc != EOK) {
     438error:
     439                        fibril_mutex_unlock(&fat_alloc_lock);
     440                        free(lifo);
     441                        return rc;
     442                }
     443        }
     444out:
    360445        fibril_mutex_unlock(&fat_alloc_lock);
    361446
     
    365450         */
    366451        while (found--) {
    367                 fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
     452                rc = fat_set_cluster(bs, dev_handle, FAT1, lifo[found],
    368453                    FAT_CLST_RES0);
     454                if (rc != EOK) {
     455                        free(lifo);
     456                        return rc;
     457                }
    369458        }
    370459       
     
    378467 * @param dev_handle    Device handle of the file system.
    379468 * @param firstc        First cluster in the chain which is to be freed.
    380  */
    381 void
     469 *
     470 * @return              EOK on success or a negative return code.
     471 */
     472int
    382473fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc)
    383474{
    384475        unsigned fatno;
    385476        fat_cluster_t nextc;
     477        int rc;
    386478
    387479        /* Mark all clusters in the chain as free in all copies of FAT. */
    388480        while (firstc < FAT_CLST_LAST1) {
    389481                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    390                 nextc = fat_get_cluster(bs, dev_handle, firstc);
    391                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    392                         fat_set_cluster(bs, dev_handle, fatno, firstc,
     482                rc = fat_get_cluster(bs, dev_handle, firstc, &nextc);
     483                if (rc != EOK)
     484                        return rc;
     485                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     486                        rc = fat_set_cluster(bs, dev_handle, fatno, firstc,
    393487                            FAT_CLST_RES0);
     488                        if (rc != EOK)
     489                                return rc;
     490                }
     491
    394492                firstc = nextc;
    395493        }
     494
     495        return EOK;
    396496}
    397497
     
    401501 * @param nodep         Node representing the file.
    402502 * @param mcl           First cluster of the cluster chain to append.
    403  */
    404 void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
     503 *
     504 * @return              EOK on success or a negative error code.
     505 */
     506int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl)
    405507{
    406508        dev_handle_t dev_handle = nodep->idx->dev_handle;
    407509        fat_cluster_t lcl;
     510        uint16_t numc;
    408511        uint8_t fatno;
    409 
    410         if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl,
    411             (uint16_t) -1) == 0) {
     512        int rc;
     513
     514        rc = fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, &numc,
     515            (uint16_t) -1);
     516        if (rc != EOK)
     517                return rc;
     518
     519        if (numc == 0) {
    412520                /* No clusters allocated to the node yet. */
    413521                nodep->firstc = mcl;
    414522                nodep->dirty = true;            /* need to sync node */
    415                 return;
    416         }
    417 
    418         for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    419                 fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl);
     523                return EOK;
     524        }
     525
     526        for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     527                rc = fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl,
     528                    mcl);
     529                if (rc != EOK)
     530                        return rc;
     531        }
     532
     533        return EOK;
    420534}
    421535
     
    427541 *                      argument is FAT_CLST_RES0, then all clusters will
    428542 *                      be chopped off.
    429  */
    430 void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
    431 {
     543 *
     544 * @return              EOK on success or a negative return code.
     545 */
     546int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc)
     547{
     548        int rc;
     549
    432550        dev_handle_t dev_handle = nodep->idx->dev_handle;
    433551        if (lastc == FAT_CLST_RES0) {
    434552                /* The node will have zero size and no clusters allocated. */
    435                 fat_free_clusters(bs, dev_handle, nodep->firstc);
     553                rc = fat_free_clusters(bs, dev_handle, nodep->firstc);
     554                if (rc != EOK)
     555                        return rc;
    436556                nodep->firstc = FAT_CLST_RES0;
    437557                nodep->dirty = true;            /* need to sync node */
     
    440560                unsigned fatno;
    441561
    442                 nextc = fat_get_cluster(bs, dev_handle, lastc);
     562                rc = fat_get_cluster(bs, dev_handle, lastc, &nextc);
     563                if (rc != EOK)
     564                        return rc;
    443565
    444566                /* Terminate the cluster chain in all copies of FAT. */
    445                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++)
    446                         fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1);
     567                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     568                        rc = fat_set_cluster(bs, dev_handle, fatno, lastc,
     569                            FAT_CLST_LAST1);
     570                        if (rc != EOK)
     571                                return rc;
     572                }
    447573
    448574                /* Free all following clusters. */
    449                 fat_free_clusters(bs, dev_handle, nextc);
    450         }
    451 }
    452 
    453 void
     575                rc = fat_free_clusters(bs, dev_handle, nextc);
     576                if (rc != EOK)
     577                        return rc;
     578        }
     579
     580        return EOK;
     581}
     582
     583int
    454584fat_zero_cluster(struct fat_bs *bs, dev_handle_t dev_handle, fat_cluster_t c)
    455585{
     
    457587        block_t *b;
    458588        unsigned bps;
     589        int rc;
    459590
    460591        bps = uint16_t_le2host(bs->bps);
    461592       
    462593        for (i = 0; i < bs->spc; i++) {
    463                 b = _fat_block_get(bs, dev_handle, c, i, BLOCK_FLAGS_NOREAD);
     594                rc = _fat_block_get(&b, bs, dev_handle, c, i,
     595                    BLOCK_FLAGS_NOREAD);
     596                if (rc != EOK)
     597                        return rc;
    464598                memset(b->data, 0, bps);
    465599                b->dirty = true;
    466                 block_put(b);
    467         }
     600                rc = block_put(b);
     601                if (rc != EOK)
     602                        return rc;
     603        }
     604
     605        return EOK;
    468606}
    469607
Note: See TracChangeset for help on using the changeset viewer.