Ignore:
File:
1 edited

Legend:

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

    rdc6b148 rc7bbf029  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    3029/** @addtogroup fs
    3130 * @{
    32  */
     31 */ 
    3332
    3433/**
     
    5150#include <mem.h>
    5251
    53 #define IS_ODD(number)  (number & 0x1)
     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)))
    5462
    5563/**
     
    5765 * during allocation of clusters. The lock does not have to be held durring
    5866 * deallocation of clusters.
    59  */
     67 */ 
    6068static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6169
     
    6371 *
    6472 * @param bs            Buffer holding the boot sector for the file.
    65  * @param service_id    Service ID of the device with the file.
     73 * @param devmap_handle Device handle of the device with the file.
    6674 * @param firstc        First cluster to start the walk with.
    6775 * @param lastc         If non-NULL, output argument hodling the last cluster
     
    6977 * @param numc          If non-NULL, output argument holding the number of
    7078 *                      clusters seen during the walk.
    71  * @param max_clusters  Maximum number of clusters to visit.
     79 * @param max_clusters  Maximum number of clusters to visit.   
    7280 *
    7381 * @return              EOK on success or a negative error code.
    7482 */
    75 int
    76 fat_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);
     83int 
     84fat_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;
    8290        int rc;
    8391
     
    9199        }
    92100
    93         while (clst < clst_last1 && clusters < max_clusters) {
     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
    94105                assert(clst >= FAT_CLST_FIRST);
    95106                if (lastc)
    96107                        *lastc = clst;  /* remember the last cluster number */
    97 
     108                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     109                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    98110                /* read FAT1 */
    99                 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
    100                 if (rc != EOK)
    101                         return rc;
    102 
    103                 assert(clst != clst_bad);
     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;
    104120                clusters++;
    105121        }
    106122
    107         if (lastc && clst < clst_last1)
     123        if (lastc && clst < FAT_CLST_LAST1)
    108124                *lastc = clst;
    109125        if (numc)
     
    135151                return ELIMIT;
    136152
    137         if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
     153        if (nodep->firstc == FAT_CLST_ROOT)
    138154                goto fall_through;
    139155
     
    144160                 * when fortunately we have the last cluster number cached.
    145161                 */
    146                 return block_get(block, nodep->idx->service_id,
     162                return block_get(block, nodep->idx->devmap_handle,
    147163                    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
    148164        }
     
    158174
    159175fall_through:
    160         rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
     176        rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
    161177            &currc, relbn, flags);
    162178        if (rc != EOK)
    163179                return rc;
    164 
     180       
    165181        /*
    166182         * Update the "current" cluster cache.
     
    177193 * @param block         Pointer to a block pointer for storing result.
    178194 * @param bs            Buffer holding the boot sector of the file system.
    179  * @param service_id    Service ID handle of the file system.
     195 * @param devmap_handle Device handle of the file system.
    180196 * @param fcl           First cluster used by the file. Can be zero if the file
    181197 *                      is empty.
    182198 * @param clp           If not NULL, address where the cluster containing bn
    183199 *                      will be stored.
    184  *                      stored
     200 *                      stored 
    185201 * @param bn            Block number.
    186202 * @param flags         Flags passed to libblock.
     
    189205 */
    190206int
    191 _fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
     207_fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
    192208    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    193209{
    194         uint32_t clusters;
    195         uint32_t max_clusters;
     210        uint16_t clusters;
     211        unsigned max_clusters;
    196212        fat_cluster_t c;
    197213        int rc;
     
    203219                return ELIMIT;
    204220
    205         if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
     221        if (fcl == FAT_CLST_ROOT) {
    206222                /* root directory special case */
    207223                assert(bn < RDS(bs));
    208                 rc = block_get(block, service_id,
     224                rc = block_get(block, devmap_handle,
    209225                    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
    210226                return rc;
     
    212228
    213229        max_clusters = bn / SPC(bs);
    214         rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
     230        rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
    215231        if (rc != EOK)
    216232                return rc;
    217233        assert(clusters == max_clusters);
    218234
    219         rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
     235        rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
    220236
    221237        if (clp)
     
    237253 * @return              EOK on success or a negative error code.
    238254 */
    239 int
    240 fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     255int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    241256{
    242257        block_t *b;
     
    260275                        return rc;
    261276        }
    262 
     277       
    263278        if (o >= pos)
    264279                return EOK;
    265 
     280       
    266281        /* zero out the initial part of the new cluster chain */
    267282        for (o = boundary; o < pos; o += BPS(bs)) {
    268                 rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
     283                rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
    269284                    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
    270285                if (rc != EOK)
     
    283298 *
    284299 * @param bs            Buffer holding the boot sector for the file system.
    285  * @param service_id    Service ID for the file system.
     300 * @param devmap_handle Device handle for the file system.
    286301 * @param clst          Cluster which to get.
    287302 * @param value         Output argument holding the value of the cluster.
     
    289304 * @return              EOK or a negative error code.
    290305 */
    291 static int
    292 fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     306int
     307fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    293308    fat_cluster_t clst, fat_cluster_t *value)
    294309{
    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);
     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);
    306316        if (rc != EOK)
    307317                return rc;
    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;
     318        cp = (fat_cluster_t *)b->data +
     319            clst % (BPS(bs) / sizeof(fat_cluster_t));
     320        *value = uint16_t_le2host(*cp);
     321        rc = block_put(b);
    346322       
    347         rc = block_put(b);
    348 
    349323        return rc;
    350324}
    351325
    352 /** Get cluster from the first FAT.
     326/** Set cluster in one instance of FAT.
    353327 *
    354328 * @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  */
    361 static int
    362 fat_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  */
    392 static int
    393 fat_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  */
    425 int
    426 fat_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 
    443 /** Set cluster in one instance of FAT.
    444  *
    445  * @param bs            Buffer holding the boot sector for the file system.
    446  * @param service_id    Service ID for the file system.
     329 * @param devmap_handle Device handle for the file system.
    447330 * @param fatno         Number of the FAT instance where to make the change.
    448331 * @param clst          Cluster which is to be set.
     
    451334 * @return              EOK on success or a negative error code.
    452335 */
    453 static int
    454 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     336int
     337fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    455338    fat_cluster_t clst, fat_cluster_t value)
    456339{
    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);
     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);
    468347        if (rc != EOK)
    469348                return rc;
    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 */
     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 */
    526353        rc = block_put(b);
    527 
    528354        return rc;
    529355}
    530356
    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  */
    541 static int
    542 fat_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  */
    574 static int
    575 fat_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  */
    611 int
    612 fat_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 
    629357/** Replay the allocatoin of clusters in all shadow instances of FAT.
    630358 *
    631359 * @param bs            Buffer holding the boot sector of the file system.
    632  * @param service_id    Service ID of the file system.
     360 * @param devmap_handle Device handle of the file system.
    633361 * @param lifo          Chain of allocated clusters.
    634362 * @param nclsts        Number of clusters in the lifo chain.
     
    636364 * @return              EOK on success or a negative error code.
    637365 */
    638 int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
     366int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
    639367    fat_cluster_t *lifo, unsigned nclsts)
    640368{
    641369        uint8_t fatno;
    642370        unsigned c;
    643         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    644         int rc;
    645 
    646         for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
     371        int rc;
     372
     373        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    647374                for (c = 0; c < nclsts; c++) {
    648                         rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
    649                             c == 0 ? clst_last1 : lifo[c - 1]);
     375                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
     376                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    650377                        if (rc != EOK)
    651378                                return rc;
     
    664391 *
    665392 * @param bs            Buffer holding the boot sector of the file system.
    666  * @param service_id    Device service ID of the file system.
     393 * @param devmap_handle Device handle of the file system.
    667394 * @param nclsts        Number of clusters to allocate.
    668395 * @param mcl           Output parameter where the first cluster in the chain
     
    674401 */
    675402int
    676 fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
     403fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
    677404    fat_cluster_t *mcl, fat_cluster_t *lcl)
    678405{
    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;
     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;
    683411
    684412        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    690418         */
    691419        fibril_mutex_lock(&fat_alloc_lock);
    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) {
     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++) {
    699426                        /*
    700                          * The cluster is free. Put it into our stack
    701                          * of found clusters and mark it as non-free.
     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.
    702433                         */
    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++;
     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                        }
    710470                }
    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];
     471                rc = block_put(blk);
     472                if (rc != EOK) {
     473error:
     474                        fibril_mutex_unlock(&fat_alloc_lock);
    718475                        free(lifo);
    719                         fibril_mutex_unlock(&fat_alloc_lock);
    720                         return EOK;
     476                        return rc;
    721477                }
    722478        }
    723 
    724         /* If something wrong - free the clusters */
     479out:
     480        fibril_mutex_unlock(&fat_alloc_lock);
     481
     482        /*
     483         * We could not find enough clusters. Now we need to free the clusters
     484         * we have allocated so far.
     485         */
    725486        while (found--) {
    726                 (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     487                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    727488                    FAT_CLST_RES0);
    728         }
    729 
     489                if (rc != EOK) {
     490                        free(lifo);
     491                        return rc;
     492                }
     493        }
     494       
    730495        free(lifo);
    731         fibril_mutex_unlock(&fat_alloc_lock);
    732 
    733496        return ENOSPC;
    734497}
     
    737500 *
    738501 * @param bs            Buffer hodling the boot sector of the file system.
    739  * @param service_id    Device service ID of the file system.
     502 * @param devmap_handle Device handle of the file system.
    740503 * @param firstc        First cluster in the chain which is to be freed.
    741504 *
     
    743506 */
    744507int
    745 fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
     508fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
    746509{
    747510        unsigned fatno;
    748         fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
     511        fat_cluster_t nextc;
    749512        int rc;
    750513
    751514        /* Mark all clusters in the chain as free in all copies of FAT. */
    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,
     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,
    761522                            FAT_CLST_RES0);
    762523                        if (rc != EOK)
     
    779540 * @return              EOK on success or a negative error code.
    780541 */
    781 int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     542int
     543fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    782544    fat_cluster_t lcl)
    783545{
    784         service_id_t service_id = nodep->idx->service_id;
     546        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
    785547        fat_cluster_t lastc;
    786548        uint8_t fatno;
     
    796558                        nodep->lastc_cached_valid = false;
    797559                } else {
    798                         rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    799                             &lastc, NULL, (uint32_t) -1);
     560                        rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
     561                            &lastc, NULL, (uint16_t) -1);
    800562                        if (rc != EOK)
    801563                                return rc;
    802564                }
    803565
    804                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    805                         rc = fat_set_cluster(bs, nodep->idx->service_id,
    806                             fatno, lastc, mcl);
     566                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     567                        rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
     568                            lastc, mcl);
    807569                        if (rc != EOK)
    808570                                return rc;
     
    828590int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    829591{
    830         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    831         int rc;
    832         service_id_t service_id = nodep->idx->service_id;
     592        int rc;
     593        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
    833594
    834595        /*
     
    841602        if (lcl == FAT_CLST_RES0) {
    842603                /* The node will have zero size and no clusters allocated. */
    843                 rc = fat_free_clusters(bs, service_id, nodep->firstc);
     604                rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
    844605                if (rc != EOK)
    845606                        return rc;
     
    850611                unsigned fatno;
    851612
    852                 rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
     613                rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
    853614                if (rc != EOK)
    854615                        return rc;
    855616
    856617                /* Terminate the cluster chain in all copies of FAT. */
    857                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    858                         rc = fat_set_cluster(bs, service_id, fatno, lcl,
    859                             clst_last1);
     618                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     619                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
     620                            FAT_CLST_LAST1);
    860621                        if (rc != EOK)
    861622                                return rc;
     
    863624
    864625                /* Free all following clusters. */
    865                 rc = fat_free_clusters(bs, service_id, nextc);
     626                rc = fat_free_clusters(bs, devmap_handle, nextc);
    866627                if (rc != EOK)
    867628                        return rc;
     
    878639
    879640int
    880 fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
     641fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
    881642{
    882643        int i;
     
    885646
    886647        for (i = 0; i < SPC(bs); i++) {
    887                 rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
     648                rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
    888649                    BLOCK_FLAGS_NOREAD);
    889650                if (rc != EOK)
     
    905666 * does not contain a fat file system.
    906667 */
    907 int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
     668int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
    908669{
    909670        fat_cluster_t e0, e1;
     
    912673
    913674        /* Check number of FATs. */
    914         if (FATCNT(bs) == 0)
     675        if (bs->fatcnt == 0)
    915676                return ENOTSUP;
    916677
    917678        /* Check total number of sectors. */
    918         if (TS(bs) == 0)
     679
     680        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    919681                return ENOTSUP;
    920682
    921683        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    922             bs->totsec16 != bs->totsec32)
     684            bs->totsec16 != bs->totsec32) 
    923685                return ENOTSUP;
    924686
     
    928690
    929691        /* Check number of sectors per FAT. */
    930         if (SF(bs) == 0)
     692        if (bs->sec_per_fat == 0)
    931693                return ENOTSUP;
    932694
     
    938700         * sanitized to support file systems with this property.
    939701         */
    940         if (!FAT_IS_FAT32(bs) &&
    941             (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
     702        if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
     703            uint16_t_le2host(bs->bps) != 0)
    942704                return ENOTSUP;
    943705
    944706        /* Check signature of each FAT. */
    945         for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
    946                 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
     707
     708        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
     709                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
    947710                if (rc != EOK)
    948711                        return EIO;
    949712
    950                 rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
     713                rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
    951714                if (rc != EOK)
    952715                        return EIO;
    953716
    954                 /*
    955                  * Check that first byte of FAT contains the media descriptor.
    956                  */
     717                /* Check that first byte of FAT contains the media descriptor. */
    957718                if ((e0 & 0xff) != bs->mdesc)
    958719                        return ENOTSUP;
     
    962723                 * set to one.
    963724                 */
    964                 if (!FAT_IS_FAT12(bs) &&
    965                     ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
     725                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    966726                        return ENOTSUP;
    967727        }
     
    972732/**
    973733 * @}
    974  */
     734 */ 
Note: See TracChangeset for help on using the changeset viewer.