Ignore:
File:
1 edited

Legend:

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

    rc7bbf029 rdc6b148  
    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/**
     
    5051#include <mem.h>
    5152
    52 /*
    53  * Convenience macros for computing some frequently used values from the
    54  * primitive boot sector members.
    55  */
    56 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    57                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    58 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    59 
    60 #define CLBN2PBN(bs, cl, bn) \
    61         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     53#define IS_ODD(number)  (number & 0x1)
    6254
    6355/**
     
    6557 * during allocation of clusters. The lock does not have to be held durring
    6658 * deallocation of clusters.
    67  */ 
     59 */
    6860static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6961
     
    7163 *
    7264 * @param bs            Buffer holding the boot sector for the file.
    73  * @param devmap_handle Device handle of the device with the file.
     65 * @param service_id    Service ID of the device with the file.
    7466 * @param firstc        First cluster to start the walk with.
    7567 * @param lastc         If non-NULL, output argument hodling the last cluster
     
    7769 * @param numc          If non-NULL, output argument holding the number of
    7870 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     71 * @param max_clusters  Maximum number of clusters to visit.
    8072 *
    8173 * @return              EOK on success or a negative error code.
    8274 */
    83 int 
    84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    85     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    86 {
    87         block_t *b;
    88         uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     75int
     76fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
     77    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
     78{
     79        uint32_t clusters = 0;
     80        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     81        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9082        int rc;
    9183
     
    9991        }
    10092
    101         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    102                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    103                 unsigned fidx;  /* FAT1 entry index */
    104 
     93        while (clst < clst_last1 && clusters < max_clusters) {
    10594                assert(clst >= FAT_CLST_FIRST);
    10695                if (lastc)
    10796                        *lastc = clst;  /* remember the last cluster number */
    108                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    109                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     97
    11098                /* read FAT1 */
    111                 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
    112                     BLOCK_FLAGS_NONE);
    113                 if (rc != EOK)
    114                         return rc;
    115                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    116                 assert(clst != FAT_CLST_BAD);
    117                 rc = block_put(b);
    118                 if (rc != EOK)
    119                         return rc;
     99                rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
     100                if (rc != EOK)
     101                        return rc;
     102
     103                assert(clst != clst_bad);
    120104                clusters++;
    121105        }
    122106
    123         if (lastc && clst < FAT_CLST_LAST1)
     107        if (lastc && clst < clst_last1)
    124108                *lastc = clst;
    125109        if (numc)
     
    151135                return ELIMIT;
    152136
    153         if (nodep->firstc == FAT_CLST_ROOT)
     137        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
    154138                goto fall_through;
    155139
     
    160144                 * when fortunately we have the last cluster number cached.
    161145                 */
    162                 return block_get(block, nodep->idx->devmap_handle,
     146                return block_get(block, nodep->idx->service_id,
    163147                    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
    164148        }
     
    174158
    175159fall_through:
    176         rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
     160        rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
    177161            &currc, relbn, flags);
    178162        if (rc != EOK)
    179163                return rc;
    180        
     164
    181165        /*
    182166         * Update the "current" cluster cache.
     
    193177 * @param block         Pointer to a block pointer for storing result.
    194178 * @param bs            Buffer holding the boot sector of the file system.
    195  * @param devmap_handle Device handle of the file system.
     179 * @param service_id    Service ID handle of the file system.
    196180 * @param fcl           First cluster used by the file. Can be zero if the file
    197181 *                      is empty.
    198182 * @param clp           If not NULL, address where the cluster containing bn
    199183 *                      will be stored.
    200  *                      stored 
     184 *                      stored
    201185 * @param bn            Block number.
    202186 * @param flags         Flags passed to libblock.
     
    205189 */
    206190int
    207 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
     191_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
    208192    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    209193{
    210         uint16_t clusters;
    211         unsigned max_clusters;
     194        uint32_t clusters;
     195        uint32_t max_clusters;
    212196        fat_cluster_t c;
    213197        int rc;
     
    219203                return ELIMIT;
    220204
    221         if (fcl == FAT_CLST_ROOT) {
     205        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
    222206                /* root directory special case */
    223207                assert(bn < RDS(bs));
    224                 rc = block_get(block, devmap_handle,
     208                rc = block_get(block, service_id,
    225209                    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
    226210                return rc;
     
    228212
    229213        max_clusters = bn / SPC(bs);
    230         rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
     214        rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
    231215        if (rc != EOK)
    232216                return rc;
    233217        assert(clusters == max_clusters);
    234218
    235         rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
     219        rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
    236220
    237221        if (clp)
     
    253237 * @return              EOK on success or a negative error code.
    254238 */
    255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     239int
     240fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    256241{
    257242        block_t *b;
     
    275260                        return rc;
    276261        }
    277        
     262
    278263        if (o >= pos)
    279264                return EOK;
    280        
     265
    281266        /* zero out the initial part of the new cluster chain */
    282267        for (o = boundary; o < pos; o += BPS(bs)) {
    283                 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
     268                rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
    284269                    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
    285270                if (rc != EOK)
     
    298283 *
    299284 * @param bs            Buffer holding the boot sector for the file system.
    300  * @param devmap_handle Device handle for the file system.
     285 * @param service_id    Service ID for the file system.
    301286 * @param clst          Cluster which to get.
    302287 * @param value         Output argument holding the value of the cluster.
     
    304289 * @return              EOK or a negative error code.
    305290 */
    306 int
    307 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     291static int
     292fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    308293    fat_cluster_t clst, fat_cluster_t *value)
    309294{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
    313 
    314         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     295        block_t *b, *b1;
     296        uint16_t byte1, byte2;
     297        aoff64_t offset;
     298        int rc;
     299
     300        offset = (clst + clst / 2);
     301        if (offset / BPS(bs) >= SF(bs))
     302                return ERANGE;
     303
     304        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     305            offset / BPS(bs), BLOCK_FLAGS_NONE);
    316306        if (rc != EOK)
    317307                return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
     308
     309        byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
     310        /* This cluster access spans a sector boundary. Check only for FAT12 */
     311        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     312                /* Is this the last sector of FAT? */
     313                if (offset / BPS(bs) < SF(bs)) {
     314                        /* No, read the next sector */
     315                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     316                            SF(bs) * fatno + offset / BPS(bs),
     317                            BLOCK_FLAGS_NONE);
     318                        if (rc != EOK) {
     319                                block_put(b);
     320                                return rc;
     321                        }
     322                        /*
     323                        * Combining value with last byte of current sector and
     324                        * first byte of next sector
     325                        */
     326                        byte2 = ((uint8_t*) b1->data)[0];
     327
     328                        rc = block_put(b1);
     329                        if (rc != EOK) {
     330                                block_put(b);
     331                                return rc;
     332                        }
     333                } else {
     334                        /* Yes. This is the last sector of FAT */
     335                        block_put(b);
     336                        return ERANGE;
     337                }
     338        } else
     339                byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
     340
     341        *value = uint16_t_le2host(byte1 | (byte2 << 8));
     342        if (IS_ODD(clst))
     343                *value = (*value) >> 4;
     344        else
     345                *value = (*value) & FAT12_MASK;
     346       
    321347        rc = block_put(b);
    322        
     348
    323349        return rc;
    324350}
    325351
     352/** Get cluster from the first FAT.
     353 *
     354 * @param bs            Buffer holding the boot sector for the file system.
     355 * @param service_id    Service ID for the file system.
     356 * @param clst          Cluster which to get.
     357 * @param value         Output argument holding the value of the cluster.
     358 *
     359 * @return              EOK or a negative error code.
     360 */
     361static int
     362fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     363    fat_cluster_t clst, fat_cluster_t *value)
     364{
     365        block_t *b;
     366        aoff64_t offset;
     367        int rc;
     368
     369        offset = (clst * FAT16_CLST_SIZE);
     370
     371        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     372            offset / BPS(bs), BLOCK_FLAGS_NONE);
     373        if (rc != EOK)
     374                return rc;
     375
     376        *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
     377
     378        rc = block_put(b);
     379
     380        return rc;
     381}
     382
     383/** Get cluster from the first FAT.
     384 *
     385 * @param bs            Buffer holding the boot sector for the file system.
     386 * @param service_id    Service ID for the file system.
     387 * @param clst          Cluster which to get.
     388 * @param value         Output argument holding the value of the cluster.
     389 *
     390 * @return              EOK or a negative error code.
     391 */
     392static int
     393fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     394    fat_cluster_t clst, fat_cluster_t *value)
     395{
     396        block_t *b;
     397        aoff64_t offset;
     398        int rc;
     399
     400        offset = (clst * FAT32_CLST_SIZE);
     401
     402        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     403            offset / BPS(bs), BLOCK_FLAGS_NONE);
     404        if (rc != EOK)
     405                return rc;
     406
     407        *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
     408            FAT32_MASK;
     409
     410        rc = block_put(b);
     411
     412        return rc;
     413}
     414
     415
     416/** Get cluster from the first FAT.
     417 *
     418 * @param bs            Buffer holding the boot sector for the file system.
     419 * @param service_id    Service ID for the file system.
     420 * @param clst          Cluster which to get.
     421 * @param value         Output argument holding the value of the cluster.
     422 *
     423 * @return              EOK or a negative error code.
     424 */
     425int
     426fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     427    fat_cluster_t clst, fat_cluster_t *value)
     428{
     429        int rc;
     430
     431        assert(fatno < FATCNT(bs));
     432
     433        if (FAT_IS_FAT12(bs))
     434                rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
     435        else if (FAT_IS_FAT16(bs))
     436                rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
     437        else
     438                rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
     439
     440        return rc;
     441}
     442
    326443/** Set cluster in one instance of FAT.
    327444 *
    328445 * @param bs            Buffer holding the boot sector for the file system.
    329  * @param devmap_handle Device handle for the file system.
     446 * @param service_id    Service ID for the file system.
    330447 * @param fatno         Number of the FAT instance where to make the change.
    331448 * @param clst          Cluster which is to be set.
     
    334451 * @return              EOK on success or a negative error code.
    335452 */
    336 int
    337 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     453static int
     454fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    338455    fat_cluster_t clst, fat_cluster_t value)
    339456{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342         int rc;
    343 
    344         assert(fatno < FATCNT(bs));
    345         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     457        block_t *b, *b1 = NULL;
     458        aoff64_t offset;
     459        uint16_t byte1, byte2;
     460        int rc;
     461
     462        offset = (clst + clst / 2);
     463        if (offset / BPS(bs) >= SF(bs))
     464                return ERANGE;
     465       
     466        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     467            offset / BPS(bs), BLOCK_FLAGS_NONE);
    347468        if (rc != EOK)
    348469                return rc;
    349         cp = (fat_cluster_t *)b->data +
    350             clst % (BPS(bs) / sizeof(fat_cluster_t));
    351         *cp = host2uint16_t_le(value);
    352         b->dirty = true;                /* need to sync block */
     470
     471        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     472        bool border = false;
     473        /* This cluster access spans a sector boundary. */
     474        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     475                /* Is it the last sector of FAT? */
     476                if (offset / BPS(bs) < SF(bs)) {
     477                        /* No, read the next sector */
     478                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     479                            SF(bs) * fatno + offset / BPS(bs),
     480                            BLOCK_FLAGS_NONE);
     481                        if (rc != EOK) {
     482                                block_put(b);
     483                                return rc;
     484                        }
     485                        /*
     486                         * Combining value with last byte of current sector and
     487                         * first byte of next sector
     488                         */
     489                        byte2 = ((uint8_t *) b1->data)[0];
     490                        border = true;
     491                } else {
     492                        /* Yes. This is the last sector of FAT */
     493                        block_put(b);
     494                        return ERANGE;
     495                }
     496        } else
     497                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
     498
     499        if (IS_ODD(clst)) {
     500                byte1 &= 0x0f;
     501                byte2 = 0;
     502                value = (value << 4);
     503        } else {
     504                byte1 = 0;
     505                byte2 &= 0xf0;
     506                value &= FAT12_MASK;
     507        }
     508
     509        byte1 = byte1 | (value & 0xff);
     510        byte2 = byte2 | (value >> 8);
     511
     512        ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
     513        if (border) {
     514                ((uint8_t *) b1->data)[0] = byte2;
     515
     516                b1->dirty = true;
     517                rc = block_put(b1);
     518                if (rc != EOK) {
     519                        block_put(b);
     520                        return rc;
     521                }
     522        } else
     523                ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
     524
     525        b->dirty = true;        /* need to sync block */
    353526        rc = block_put(b);
     527
    354528        return rc;
    355529}
    356530
     531/** Set cluster in one instance of FAT.
     532 *
     533 * @param bs            Buffer holding the boot sector for the file system.
     534 * @param service_id    Service ID for the file system.
     535 * @param fatno         Number of the FAT instance where to make the change.
     536 * @param clst          Cluster which is to be set.
     537 * @param value         Value to set the cluster with.
     538 *
     539 * @return              EOK on success or a negative error code.
     540 */
     541static int
     542fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     543    fat_cluster_t clst, fat_cluster_t value)
     544{
     545        block_t *b;
     546        aoff64_t offset;
     547        int rc;
     548
     549        offset = (clst * FAT16_CLST_SIZE);
     550
     551        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     552            offset / BPS(bs), BLOCK_FLAGS_NONE);
     553        if (rc != EOK)
     554                return rc;
     555
     556        *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
     557
     558        b->dirty = true;        /* need to sync block */
     559        rc = block_put(b);
     560
     561        return rc;
     562}
     563
     564/** Set cluster in one instance of FAT.
     565 *
     566 * @param bs            Buffer holding the boot sector for the file system.
     567 * @param service_id    Service ID for the file system.
     568 * @param fatno         Number of the FAT instance where to make the change.
     569 * @param clst          Cluster which is to be set.
     570 * @param value         Value to set the cluster with.
     571 *
     572 * @return              EOK on success or a negative error code.
     573 */
     574static int
     575fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     576    fat_cluster_t clst, fat_cluster_t value)
     577{
     578        block_t *b;
     579        aoff64_t offset;
     580        int rc;
     581        fat_cluster_t temp;
     582
     583        offset = (clst * FAT32_CLST_SIZE);
     584
     585        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     586            offset / BPS(bs), BLOCK_FLAGS_NONE);
     587        if (rc != EOK)
     588                return rc;
     589
     590        temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
     591        temp &= 0xf0000000;
     592        temp |= (value & FAT32_MASK);
     593        *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
     594
     595        b->dirty = true;        /* need to sync block */
     596        rc = block_put(b);
     597
     598        return rc;
     599}
     600
     601/** Set cluster in one instance of FAT.
     602 *
     603 * @param bs            Buffer holding the boot sector for the file system.
     604 * @param service_id    Device service ID for the file system.
     605 * @param fatno         Number of the FAT instance where to make the change.
     606 * @param clst          Cluster which is to be set.
     607 * @param value         Value to set the cluster with.
     608 *
     609 * @return              EOK on success or a negative error code.
     610 */
     611int
     612fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     613    fat_cluster_t clst, fat_cluster_t value)
     614{
     615        int rc;
     616
     617        assert(fatno < FATCNT(bs));
     618
     619        if (FAT_IS_FAT12(bs))
     620                rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
     621        else if (FAT_IS_FAT16(bs))
     622                rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
     623        else
     624                rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
     625
     626        return rc;
     627}
     628
    357629/** Replay the allocatoin of clusters in all shadow instances of FAT.
    358630 *
    359631 * @param bs            Buffer holding the boot sector of the file system.
    360  * @param devmap_handle Device handle of the file system.
     632 * @param service_id    Service ID of the file system.
    361633 * @param lifo          Chain of allocated clusters.
    362634 * @param nclsts        Number of clusters in the lifo chain.
     
    364636 * @return              EOK on success or a negative error code.
    365637 */
    366 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
     638int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
    367639    fat_cluster_t *lifo, unsigned nclsts)
    368640{
    369641        uint8_t fatno;
    370642        unsigned c;
    371         int rc;
    372 
    373         for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
     643        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     644        int rc;
     645
     646        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
    374647                for (c = 0; c < nclsts; c++) {
    375                         rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     648                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
     649                            c == 0 ? clst_last1 : lifo[c - 1]);
    377650                        if (rc != EOK)
    378651                                return rc;
     
    391664 *
    392665 * @param bs            Buffer holding the boot sector of the file system.
    393  * @param devmap_handle Device handle of the file system.
     666 * @param service_id    Device service ID of the file system.
    394667 * @param nclsts        Number of clusters to allocate.
    395668 * @param mcl           Output parameter where the first cluster in the chain
     
    401674 */
    402675int
    403 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
     676fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
    404677    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405678{
    406         block_t *blk;
    407         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    408         unsigned found = 0;     /* top of the free cluster number stack */
    409         unsigned b, c, cl;
    410         int rc;
     679        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     680        unsigned found = 0;     /* top of the free cluster number stack */
     681        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     682        int rc = EOK;
    411683
    412684        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    418690         */
    419691        fibril_mutex_lock(&fat_alloc_lock);
    420         for (b = 0, cl = 0; b < SF(bs); b++) {
    421                 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
    422                     BLOCK_FLAGS_NONE);
    423                 if (rc != EOK)
    424                         goto error;
    425                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
     692        for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
     693            clst++) {
     694                rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
     695                if (rc != EOK)
     696                        break;
     697
     698                if (value == FAT_CLST_RES0) {
    426699                        /*
    427                          * Check if the entire cluster is physically there.
    428                          * This check becomes necessary when the file system is
    429                          * created with fewer total sectors than how many is
    430                          * inferred from the size of the file allocation table
    431                          * or when the last cluster ends beyond the end of the
    432                          * device.
     700                         * The cluster is free. Put it into our stack
     701                         * of found clusters and mark it as non-free.
    433702                         */
    434                         if ((cl >= FAT_CLST_FIRST) &&
    435                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    436                                 rc = block_put(blk);
    437                                 if (rc != EOK)
    438                                         goto error;
    439                                 goto out;
    440                         }
    441 
    442                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    443                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    444                                 /*
    445                                  * The cluster is free. Put it into our stack
    446                                  * of found clusters and mark it as non-free.
    447                                  */
    448                                 lifo[found] = cl;
    449                                 *clst = (found == 0) ?
    450                                     host2uint16_t_le(FAT_CLST_LAST1) :
    451                                     host2uint16_t_le(lifo[found - 1]);
    452                                 blk->dirty = true;      /* need to sync block */
    453                                 if (++found == nclsts) {
    454                                         /* we are almost done */
    455                                         rc = block_put(blk);
    456                                         if (rc != EOK)
    457                                                 goto error;
    458                                         /* update the shadow copies of FAT */
    459                                         rc = fat_alloc_shadow_clusters(bs,
    460                                             devmap_handle, lifo, nclsts);
    461                                         if (rc != EOK)
    462                                                 goto error;
    463                                         *mcl = lifo[found - 1];
    464                                         *lcl = lifo[0];
    465                                         free(lifo);
    466                                         fibril_mutex_unlock(&fat_alloc_lock);
    467                                         return EOK;
    468                                 }
    469                         }
     703                        lifo[found] = clst;
     704                        rc = fat_set_cluster(bs, service_id, FAT1, clst,
     705                            (found == 0) ?  clst_last1 : lifo[found - 1]);
     706                        if (rc != EOK)
     707                                break;
     708
     709                        found++;
    470710                }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     711        }
     712
     713        if (rc == EOK && found == nclsts) {
     714                rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
     715                if (rc == EOK) {
     716                        *mcl = lifo[found - 1];
     717                        *lcl = lifo[0];
     718                        free(lifo);
    474719                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
     720                        return EOK;
    477721                }
    478722        }
    479 out:
     723
     724        /* If something wrong - free the clusters */
     725        while (found--) {
     726                (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     727                    FAT_CLST_RES0);
     728        }
     729
     730        free(lifo);
    480731        fibril_mutex_unlock(&fat_alloc_lock);
    481732
    482         /*
    483          * We could not find enough clusters. Now we need to free the clusters
    484          * we have allocated so far.
    485          */
    486         while (found--) {
    487                 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    488                     FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
    495         free(lifo);
    496733        return ENOSPC;
    497734}
     
    500737 *
    501738 * @param bs            Buffer hodling the boot sector of the file system.
    502  * @param devmap_handle Device handle of the file system.
     739 * @param service_id    Device service ID of the file system.
    503740 * @param firstc        First cluster in the chain which is to be freed.
    504741 *
     
    506743 */
    507744int
    508 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
     745fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
    509746{
    510747        unsigned fatno;
    511         fat_cluster_t nextc;
     748        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512749        int rc;
    513750
    514751        /* Mark all clusters in the chain as free in all copies of FAT. */
    515         while (firstc < FAT_CLST_LAST1) {
    516                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    517                 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    518                 if (rc != EOK)
    519                         return rc;
    520                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    521                         rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
     752        while (firstc < FAT_CLST_LAST1(bs)) {
     753                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     754
     755                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
     756                if (rc != EOK)
     757                        return rc;
     758
     759                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     760                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    522761                            FAT_CLST_RES0);
    523762                        if (rc != EOK)
     
    540779 * @return              EOK on success or a negative error code.
    541780 */
    542 int
    543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     781int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    544782    fat_cluster_t lcl)
    545783{
    546         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     784        service_id_t service_id = nodep->idx->service_id;
    547785        fat_cluster_t lastc;
    548786        uint8_t fatno;
     
    558796                        nodep->lastc_cached_valid = false;
    559797                } else {
    560                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
    561                             &lastc, NULL, (uint16_t) -1);
     798                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
     799                            &lastc, NULL, (uint32_t) -1);
    562800                        if (rc != EOK)
    563801                                return rc;
    564802                }
    565803
    566                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
    568                             lastc, mcl);
     804                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     805                        rc = fat_set_cluster(bs, nodep->idx->service_id,
     806                            fatno, lastc, mcl);
    569807                        if (rc != EOK)
    570808                                return rc;
     
    590828int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591829{
    592         int rc;
    593         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     830        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     831        int rc;
     832        service_id_t service_id = nodep->idx->service_id;
    594833
    595834        /*
     
    602841        if (lcl == FAT_CLST_RES0) {
    603842                /* The node will have zero size and no clusters allocated. */
    604                 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
     843                rc = fat_free_clusters(bs, service_id, nodep->firstc);
    605844                if (rc != EOK)
    606845                        return rc;
     
    611850                unsigned fatno;
    612851
    613                 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
     852                rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
    614853                if (rc != EOK)
    615854                        return rc;
    616855
    617856                /* Terminate the cluster chain in all copies of FAT. */
    618                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    619                         rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    620                             FAT_CLST_LAST1);
     857                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     858                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
     859                            clst_last1);
    621860                        if (rc != EOK)
    622861                                return rc;
     
    624863
    625864                /* Free all following clusters. */
    626                 rc = fat_free_clusters(bs, devmap_handle, nextc);
     865                rc = fat_free_clusters(bs, service_id, nextc);
    627866                if (rc != EOK)
    628867                        return rc;
     
    639878
    640879int
    641 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
     880fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
    642881{
    643882        int i;
     
    646885
    647886        for (i = 0; i < SPC(bs); i++) {
    648                 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
     887                rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
    649888                    BLOCK_FLAGS_NOREAD);
    650889                if (rc != EOK)
     
    666905 * does not contain a fat file system.
    667906 */
    668 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
     907int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
    669908{
    670909        fat_cluster_t e0, e1;
     
    673912
    674913        /* Check number of FATs. */
    675         if (bs->fatcnt == 0)
     914        if (FATCNT(bs) == 0)
    676915                return ENOTSUP;
    677916
    678917        /* Check total number of sectors. */
    679 
    680         if (bs->totsec16 == 0 && bs->totsec32 == 0)
     918        if (TS(bs) == 0)
    681919                return ENOTSUP;
    682920
    683921        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     922            bs->totsec16 != bs->totsec32)
    685923                return ENOTSUP;
    686924
     
    690928
    691929        /* Check number of sectors per FAT. */
    692         if (bs->sec_per_fat == 0)
     930        if (SF(bs) == 0)
    693931                return ENOTSUP;
    694932
     
    700938         * sanitized to support file systems with this property.
    701939         */
    702         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    703             uint16_t_le2host(bs->bps) != 0)
     940        if (!FAT_IS_FAT32(bs) &&
     941            (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
    704942                return ENOTSUP;
    705943
    706944        /* Check signature of each FAT. */
    707 
    708         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    709                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     945        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
     946                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    710947                if (rc != EOK)
    711948                        return EIO;
    712949
    713                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
     950                rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
    714951                if (rc != EOK)
    715952                        return EIO;
    716953
    717                 /* Check that first byte of FAT contains the media descriptor. */
     954                /*
     955                 * Check that first byte of FAT contains the media descriptor.
     956                 */
    718957                if ((e0 & 0xff) != bs->mdesc)
    719958                        return ENOTSUP;
     
    723962                 * set to one.
    724963                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     964                if (!FAT_IS_FAT12(bs) &&
     965                    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
    726966                        return ENOTSUP;
    727967        }
     
    732972/**
    733973 * @}
    734  */ 
     974 */
Note: See TracChangeset for help on using the changeset viewer.