Ignore:
File:
1 edited

Legend:

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

    rd963742 r15f3c3f  
    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/**
     
    5554 * primitive boot sector members.
    5655 */
     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
    5760#define CLBN2PBN(bs, cl, bn) \
    5861        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
    59 
    60 #define IS_ODD(number)  (number & 0x1)
    6162
    6263/**
     
    6465 * during allocation of clusters. The lock does not have to be held durring
    6566 * deallocation of clusters.
    66  */
     67 */ 
    6768static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6869
     
    7071 *
    7172 * @param bs            Buffer holding the boot sector for the file.
    72  * @param devmap_handle Device handle of the device with the file.
     73 * @param service_id    Service ID of the device with the file.
    7374 * @param firstc        First cluster to start the walk with.
    7475 * @param lastc         If non-NULL, output argument hodling the last cluster
     
    7677 * @param numc          If non-NULL, output argument holding the number of
    7778 *                      clusters seen during the walk.
    78  * @param max_clusters  Maximum number of clusters to visit.
     79 * @param max_clusters  Maximum number of clusters to visit.   
    7980 *
    8081 * @return              EOK on success or a negative error code.
    8182 */
    82 int
    83 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    84     fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
    85 {
    86         uint32_t clusters = 0;
    87         fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
    88         fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
     83int 
     84fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, 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;
    8990        int rc;
    9091
     
    9899        }
    99100
    100         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
    101105                assert(clst >= FAT_CLST_FIRST);
    102106                if (lastc)
    103107                        *lastc = clst;  /* remember the last cluster number */
    104 
     108                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     109                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    105110                /* read FAT1 */
    106                 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
    107                 if (rc != EOK)
    108                         return rc;
    109 
    110                 assert(clst != clst_bad);
     111                rc = block_get(&b, service_id, 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;
    111120                clusters++;
    112121        }
    113122
    114         if (lastc && clst < clst_last1)
     123        if (lastc && clst < FAT_CLST_LAST1)
    115124                *lastc = clst;
    116125        if (numc)
     
    142151                return ELIMIT;
    143152
    144         if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
     153        if (nodep->firstc == FAT_CLST_ROOT)
    145154                goto fall_through;
    146155
     
    151160                 * when fortunately we have the last cluster number cached.
    152161                 */
    153                 return block_get(block, nodep->idx->devmap_handle,
     162                return block_get(block, nodep->idx->service_id,
    154163                    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
    155164        }
     
    165174
    166175fall_through:
    167         rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
     176        rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
    168177            &currc, relbn, flags);
    169178        if (rc != EOK)
    170179                return rc;
    171 
     180       
    172181        /*
    173182         * Update the "current" cluster cache.
     
    184193 * @param block         Pointer to a block pointer for storing result.
    185194 * @param bs            Buffer holding the boot sector of the file system.
    186  * @param devmap_handle Device handle of the file system.
     195 * @param service_id    Service ID handle of the file system.
    187196 * @param fcl           First cluster used by the file. Can be zero if the file
    188197 *                      is empty.
    189198 * @param clp           If not NULL, address where the cluster containing bn
    190199 *                      will be stored.
    191  *                      stored
     200 *                      stored 
    192201 * @param bn            Block number.
    193202 * @param flags         Flags passed to libblock.
     
    196205 */
    197206int
    198 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
     207_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
    199208    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    200209{
    201         uint32_t clusters;
    202         uint32_t max_clusters;
     210        uint16_t clusters;
     211        unsigned max_clusters;
    203212        fat_cluster_t c;
    204213        int rc;
     
    210219                return ELIMIT;
    211220
    212         if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
     221        if (fcl == FAT_CLST_ROOT) {
    213222                /* root directory special case */
    214223                assert(bn < RDS(bs));
    215                 rc = block_get(block, devmap_handle,
     224                rc = block_get(block, service_id,
    216225                    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
    217226                return rc;
     
    219228
    220229        max_clusters = bn / SPC(bs);
    221         rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
     230        rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
    222231        if (rc != EOK)
    223232                return rc;
    224233        assert(clusters == max_clusters);
    225234
    226         rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
     235        rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
    227236
    228237        if (clp)
     
    266275                        return rc;
    267276        }
    268 
     277       
    269278        if (o >= pos)
    270279                return EOK;
    271 
     280       
    272281        /* zero out the initial part of the new cluster chain */
    273282        for (o = boundary; o < pos; o += BPS(bs)) {
    274                 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
     283                rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
    275284                    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
    276285                if (rc != EOK)
     
    286295}
    287296
    288 /** Get cluster from the first FAT. FAT12 version
     297/** Get cluster from the first FAT.
    289298 *
    290299 * @param bs            Buffer holding the boot sector for the file system.
    291  * @param devmap_handle Device handle for the file system.
     300 * @param service_id    Service ID for the file system.
    292301 * @param clst          Cluster which to get.
    293302 * @param value         Output argument holding the value of the cluster.
     
    296305 */
    297306int
    298 fat_get_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     307fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    299308    fat_cluster_t clst, fat_cluster_t *value)
    300309{
    301         block_t *b, *b1;
    302         uint16_t byte1, byte2;
    303         aoff64_t offset;
    304         int rc;
    305 
    306         offset = (clst + clst/2);
    307         if (offset / BPS(bs) >= SF(bs))
    308                 return ERANGE;
    309 
    310         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    311             offset / BPS(bs), BLOCK_FLAGS_NONE);
     310        block_t *b;
     311        fat_cluster_t *cp;
     312        int rc;
     313
     314        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     315            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    312316        if (rc != EOK)
    313317                return rc;
    314 
    315         byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
    316         /* This cluster access spans a sector boundary. Check only for FAT12 */
    317         if ((offset % BPS(bs)) + 1 == BPS(bs)) {
    318                 /* Is it last sector of FAT? */
    319                 if (offset / BPS(bs) < SF(bs)) {
    320                         /* No. Reading next sector */
    321                         rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
    322                                 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
    323                         if (rc != EOK) {
    324                                 block_put(b);
    325                                 return rc;
    326                         }
    327                         /*
    328                         * Combining value with last byte of current sector and
    329                         * first byte of next sector
    330                         */
    331                         byte2 = ((uint8_t*) b1->data)[0];
    332 
    333                         rc = block_put(b1);
    334                         if (rc != EOK) {
    335                                 block_put(b);
    336                                 return rc;
    337                         }
    338                 }
    339                 else {
    340                         /* Yes. It is last sector of FAT */
    341                         block_put(b);
    342                         return ERANGE;
    343                 }
    344         }
    345         else
    346                 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
    347 
    348         *value = uint16_t_le2host(byte1 | (byte2 << 8));
    349         if (IS_ODD(clst))
    350                 *value = (*value) >> 4;
    351         else
    352                 *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);
    353322       
    354         rc = block_put(b);
    355323        return rc;
    356324}
    357325
    358 /** Get cluster from the first FAT. FAT16 version
     326/** Set cluster in one instance of FAT.
    359327 *
    360328 * @param bs            Buffer holding the boot sector for the file system.
    361  * @param devmap_handle Device handle for the file system.
    362  * @param clst          Cluster which to get.
    363  * @param value         Output argument holding the value of the cluster.
    364  *
    365  * @return              EOK or a negative error code.
    366  */
    367 int
    368 fat_get_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    369     fat_cluster_t clst, fat_cluster_t *value)
    370 {
    371         block_t *b;
    372         aoff64_t offset;
    373         int rc;
    374 
    375         offset = (clst * FAT16_CLST_SIZE);
    376 
    377         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    378             offset / BPS(bs), BLOCK_FLAGS_NONE);
    379         if (rc != EOK)
    380                 return rc;
    381 
    382         *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
    383 
    384         rc = block_put(b);
    385 
    386         return rc;
    387 }
    388 
    389 /** Get cluster from the first FAT. FAT32 version
    390  *
    391  * @param bs            Buffer holding the boot sector for the file system.
    392  * @param devmap_handle Device handle for the file system.
    393  * @param clst          Cluster which to get.
    394  * @param value         Output argument holding the value of the cluster.
    395  *
    396  * @return              EOK or a negative error code.
    397  */
    398 int
    399 fat_get_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    400     fat_cluster_t clst, fat_cluster_t *value)
    401 {
    402         block_t *b;
    403         aoff64_t offset;
    404         int rc;
    405 
    406         offset = (clst * FAT32_CLST_SIZE);
    407 
    408         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    409             offset / BPS(bs), BLOCK_FLAGS_NONE);
    410         if (rc != EOK)
    411                 return rc;
    412 
    413         *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & FAT32_MASK;
    414 
    415         rc = block_put(b);
    416 
    417         return rc;
    418 }
    419 
    420 
    421 /** Get cluster from the first FAT.
    422  *
    423  * @param bs            Buffer holding the boot sector for the file system.
    424  * @param devmap_handle Device handle for the file system.
    425  * @param clst          Cluster which to get.
    426  * @param value         Output argument holding the value of the cluster.
    427  *
    428  * @return              EOK or a negative error code.
    429  */
    430 int
    431 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    432     fat_cluster_t clst, fat_cluster_t *value)
    433 {
    434         int rc;
    435 
    436         assert(fatno < FATCNT(bs));
    437 
    438         if (FAT_IS_FAT12(bs)) {
    439                 rc = fat_get_cluster_fat12(bs, devmap_handle, fatno, clst, value);
    440         }
    441         else {
    442                 if (FAT_IS_FAT32(bs))
    443                         rc = fat_get_cluster_fat32(bs, devmap_handle, fatno, clst, value);
    444                 else
    445                         rc = fat_get_cluster_fat16(bs, devmap_handle, fatno, clst, value);
    446         }
    447 
    448         return rc;
    449 }
    450 
    451 /** Set cluster in one instance of FAT. FAT12 version.
    452  *
    453  * @param bs            Buffer holding the boot sector for the file system.
    454  * @param devmap_handle Device handle for the file system.
     329 * @param service_id    Device service ID for the file system.
    455330 * @param fatno         Number of the FAT instance where to make the change.
    456331 * @param clst          Cluster which is to be set.
     
    460335 */
    461336int
    462 fat_set_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     337fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    463338    fat_cluster_t clst, fat_cluster_t value)
    464339{
    465         block_t *b, *b1=NULL;
    466         aoff64_t offset;
    467         uint16_t byte1, byte2;
    468         int rc;
    469 
    470         offset = (clst + clst/2);
    471         if (offset / BPS(bs) >= SF(bs))
    472                 return ERANGE;
    473        
    474         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    475             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, service_id, RSCNT(bs) + SF(bs) * fatno +
     346            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    476347        if (rc != EOK)
    477348                return rc;
    478 
    479         byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
    480         bool border = false;
    481         /* This cluster access spans a sector boundary. Check only for FAT12 */
    482         if ((offset % BPS(bs))+1 == BPS(bs)) {
    483                 /* Is it last sector of FAT? */
    484                 if (offset / BPS(bs) < SF(bs)) {
    485                         /* No. Reading next sector */
    486                         rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
    487                                 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
    488                         if (rc != EOK) {
    489                                 block_put(b);
    490                                 return rc;
    491                         }
    492                         /*
    493                          * Combining value with last byte of current sector and
    494                          * first byte of next sector
    495                          */
    496                         byte2 = ((uint8_t*) b1->data)[0];
    497                         border = true;
    498                 }
    499                 else {
    500                         /* Yes. It is last sector of fat */
    501                         block_put(b);
    502                         return ERANGE;
    503                 }
    504         }
    505         else
    506                 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
    507 
    508         if (IS_ODD(clst)) {
    509                 byte1 &= 0x0f;
    510                 byte2 = 0;
    511                 value = (value << 4);
    512         } else {
    513                 byte1 = 0;
    514                 byte2 &= 0xf0;
    515                 value &= FAT12_MASK;
    516         }
    517 
    518         byte1 = byte1 | (value & 0xff);
    519         byte2 = byte2 | (value >> 8);
    520 
    521         ((uint8_t*) b->data)[(offset % BPS(bs))] = byte1;
    522         if (border) {
    523                 ((uint8_t*) b1->data)[0] = byte2;
    524 
    525                 b1->dirty = true;
    526                 rc = block_put(b1);
    527                 if (rc != EOK) {
    528                         block_put(b);
    529                         return rc;
    530                 }
    531         } else
    532                 ((uint8_t*) b->data)[(offset % BPS(bs))+1] = byte2;
    533 
    534         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 */
    535353        rc = block_put(b);
    536354        return rc;
    537355}
    538356
    539 /** Set cluster in one instance of FAT. FAT16 version.
    540  *
    541  * @param bs            Buffer holding the boot sector for the file system.
    542  * @param devmap_handle Device handle for the file system.
    543  * @param fatno         Number of the FAT instance where to make the change.
    544  * @param clst          Cluster which is to be set.
    545  * @param value         Value to set the cluster with.
    546  *
    547  * @return              EOK on success or a negative error code.
    548  */
    549 int
    550 fat_set_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    551     fat_cluster_t clst, fat_cluster_t value)
    552 {
    553         block_t *b;
    554         aoff64_t offset;
    555         int rc;
    556 
    557         offset = (clst * FAT16_CLST_SIZE);
    558 
    559         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    560             offset / BPS(bs), BLOCK_FLAGS_NONE);
    561         if (rc != EOK)
    562                 return rc;
    563 
    564         *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
    565 
    566         b->dirty = true;        /* need to sync block */
    567         rc = block_put(b);
    568         return rc;
    569 }
    570 
    571 /** Set cluster in one instance of FAT. FAT32 version.
    572  *
    573  * @param bs            Buffer holding the boot sector for the file system.
    574  * @param devmap_handle Device handle for the file system.
    575  * @param fatno         Number of the FAT instance where to make the change.
    576  * @param clst          Cluster which is to be set.
    577  * @param value         Value to set the cluster with.
    578  *
    579  * @return              EOK on success or a negative error code.
    580  */
    581 int
    582 fat_set_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    583     fat_cluster_t clst, fat_cluster_t value)
    584 {
    585         block_t *b;
    586         aoff64_t offset;
    587         int rc;
    588         fat_cluster_t temp;
    589 
    590         offset = (clst * FAT32_CLST_SIZE);
    591 
    592         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    593             offset / BPS(bs), BLOCK_FLAGS_NONE);
    594         if (rc != EOK)
    595                 return rc;
    596 
    597         temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
    598         temp &= 0xf0000000;
    599         temp |= (value & FAT32_MASK);
    600         *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
    601 
    602         b->dirty = true;        /* need to sync block */
    603         rc = block_put(b);
    604         return rc;
    605 }
    606 
    607 /** Set cluster in one instance of FAT.
    608  *
    609  * @param bs            Buffer holding the boot sector for the file system.
    610  * @param devmap_handle Device handle for the file system.
    611  * @param fatno         Number of the FAT instance where to make the change.
    612  * @param clst          Cluster which is to be set.
    613  * @param value         Value to set the cluster with.
    614  *
    615  * @return              EOK on success or a negative error code.
    616  */
    617 int
    618 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    619     fat_cluster_t clst, fat_cluster_t value)
    620 {
    621         int rc;
    622 
    623         assert(fatno < FATCNT(bs));
    624 
    625         if (FAT_IS_FAT12(bs))
    626                 rc = fat_set_cluster_fat12(bs, devmap_handle, fatno, clst, value);
    627         else if (FAT_IS_FAT32(bs))
    628                 rc = fat_set_cluster_fat32(bs, devmap_handle, fatno, clst, value);
    629         else
    630                 rc = fat_set_cluster_fat16(bs, devmap_handle, fatno, clst, value);
    631 
    632         return rc;
    633 }
    634 
    635357/** Replay the allocatoin of clusters in all shadow instances of FAT.
    636358 *
    637359 * @param bs            Buffer holding the boot sector of the file system.
    638  * @param devmap_handle Device handle of the file system.
     360 * @param service_id    Service ID of the file system.
    639361 * @param lifo          Chain of allocated clusters.
    640362 * @param nclsts        Number of clusters in the lifo chain.
     
    642364 * @return              EOK on success or a negative error code.
    643365 */
    644 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
     366int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
    645367    fat_cluster_t *lifo, unsigned nclsts)
    646368{
    647369        uint8_t fatno;
    648370        unsigned c;
    649         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    650         int rc;
    651 
    652         for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
     371        int rc;
     372
     373        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    653374                for (c = 0; c < nclsts; c++) {
    654                         rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    655                             c == 0 ? clst_last1 : lifo[c - 1]);
     375                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
     376                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    656377                        if (rc != EOK)
    657378                                return rc;
     
    670391 *
    671392 * @param bs            Buffer holding the boot sector of the file system.
    672  * @param devmap_handle Device handle of the file system.
     393 * @param service_id    Device service ID of the file system.
    673394 * @param nclsts        Number of clusters to allocate.
    674395 * @param mcl           Output parameter where the first cluster in the chain
     
    680401 */
    681402int
    682 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
     403fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
    683404    fat_cluster_t *mcl, fat_cluster_t *lcl)
    684405{
    685         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    686         unsigned found = 0;     /* top of the free cluster number stack */
    687         fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
    688         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;
    689411
    690412        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    691413        if (!lifo)
    692414                return ENOMEM;
     415       
    693416        /*
    694417         * Search FAT1 for unused clusters.
    695418         */
    696419        fibril_mutex_lock(&fat_alloc_lock);
    697         for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
    698                 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
    699                 if (rc != EOK)
    700                 break;
    701 
    702                 if (value == FAT_CLST_RES0) {
    703                 /*
    704                  * The cluster is free. Put it into our stack
    705                  * of found clusters and mark it as non-free.
    706                  */
    707                 lifo[found] = clst;
    708                 rc = fat_set_cluster(bs, devmap_handle, FAT1, clst,
    709                     (found == 0) ?  clst_last1 : lifo[found - 1]);
    710                 if (rc != EOK)
    711                         break;
    712 
    713                 found++;
     420        for (b = 0, cl = 0; b < SF(bs); b++) {
     421                rc = block_get(&blk, service_id, 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++) {
     426                        /*
     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.
     433                         */
     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                                            service_id, 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                        }
    714470                }
    715         }
    716 
    717         if (rc == EOK && found == nclsts) {
    718                 rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
    719                 if (rc == EOK) {
    720                         *mcl = lifo[found - 1];
    721                         *lcl = lifo[0];
     471                rc = block_put(blk);
     472                if (rc != EOK) {
     473error:
     474                        fibril_mutex_unlock(&fat_alloc_lock);
    722475                        free(lifo);
    723                         fibril_mutex_unlock(&fat_alloc_lock);
    724                         return EOK;
     476                        return rc;
    725477                }
    726478        }
    727 
    728         /* If something wrong - free the clusters */
    729         if (found > 0) {
    730                 while (found--) {
    731                 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
     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         */
     486        while (found--) {
     487                rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
    732488                    FAT_CLST_RES0);
     489                if (rc != EOK) {
     490                        free(lifo);
     491                        return rc;
    733492                }
    734493        }
    735 
     494       
    736495        free(lifo);
    737         fibril_mutex_unlock(&fat_alloc_lock);
    738496        return ENOSPC;
    739497}
     
    742500 *
    743501 * @param bs            Buffer hodling the boot sector of the file system.
    744  * @param devmap_handle Device handle of the file system.
     502 * @param service_id    Device service ID of the file system.
    745503 * @param firstc        First cluster in the chain which is to be freed.
    746504 *
     
    748506 */
    749507int
    750 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
     508fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
    751509{
    752510        unsigned fatno;
    753         fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
     511        fat_cluster_t nextc;
    754512        int rc;
    755513
    756514        /* Mark all clusters in the chain as free in all copies of FAT. */
    757         while (firstc < FAT_CLST_LAST1(bs)) {
    758                 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
    759                 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    760                 if (rc != EOK)
    761                         return rc;
    762                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    763                         rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
     515        while (firstc < FAT_CLST_LAST1) {
     516                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
     517                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
     518                if (rc != EOK)
     519                        return rc;
     520                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     521                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    764522                            FAT_CLST_RES0);
    765523                        if (rc != EOK)
     
    786544    fat_cluster_t lcl)
    787545{
    788         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     546        service_id_t service_id = nodep->idx->service_id;
    789547        fat_cluster_t lastc;
    790548        uint8_t fatno;
     
    800558                        nodep->lastc_cached_valid = false;
    801559                } else {
    802                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
     560                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    803561                            &lastc, NULL, (uint16_t) -1);
    804562                        if (rc != EOK)
     
    806564                }
    807565
    808                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    809                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle,
    810                             fatno, lastc, mcl);
     566                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     567                        rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
     568                            lastc, mcl);
    811569                        if (rc != EOK)
    812570                                return rc;
     
    832590int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    833591{
    834         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    835         int rc;
    836         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     592        int rc;
     593        service_id_t service_id = nodep->idx->service_id;
    837594
    838595        /*
     
    845602        if (lcl == FAT_CLST_RES0) {
    846603                /* The node will have zero size and no clusters allocated. */
    847                 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
     604                rc = fat_free_clusters(bs, service_id, nodep->firstc);
    848605                if (rc != EOK)
    849606                        return rc;
     
    854611                unsigned fatno;
    855612
    856                 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
     613                rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
    857614                if (rc != EOK)
    858615                        return rc;
    859616
    860617                /* Terminate the cluster chain in all copies of FAT. */
    861                 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    862                         rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    863                             clst_last1);
     618                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     619                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
     620                            FAT_CLST_LAST1);
    864621                        if (rc != EOK)
    865622                                return rc;
     
    867624
    868625                /* Free all following clusters. */
    869                 rc = fat_free_clusters(bs, devmap_handle, nextc);
     626                rc = fat_free_clusters(bs, service_id, nextc);
    870627                if (rc != EOK)
    871628                        return rc;
     
    882639
    883640int
    884 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
     641fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
    885642{
    886643        int i;
     
    889646
    890647        for (i = 0; i < SPC(bs); i++) {
    891                 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
     648                rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
    892649                    BLOCK_FLAGS_NOREAD);
    893650                if (rc != EOK)
     
    909666 * does not contain a fat file system.
    910667 */
    911 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
     668int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
    912669{
    913670        fat_cluster_t e0, e1;
     
    916673
    917674        /* Check number of FATs. */
    918         if (FATCNT(bs) == 0)
     675        if (bs->fatcnt == 0)
    919676                return ENOTSUP;
    920677
    921678        /* Check total number of sectors. */
    922         if (TS(bs) == 0)
     679
     680        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    923681                return ENOTSUP;
    924682
    925683        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    926             bs->totsec16 != bs->totsec32)
     684            bs->totsec16 != bs->totsec32) 
    927685                return ENOTSUP;
    928686
     
    932690
    933691        /* Check number of sectors per FAT. */
    934         if (SF(bs) == 0)
     692        if (bs->sec_per_fat == 0)
    935693                return ENOTSUP;
    936694
     
    942700         * sanitized to support file systems with this property.
    943701         */
    944         if (!FAT_IS_FAT32(bs) && (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)
    945704                return ENOTSUP;
    946705
    947706        /* Check signature of each FAT. */
    948         for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
    949                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     707
     708        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
     709                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    950710                if (rc != EOK)
    951711                        return EIO;
    952712
    953                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
     713                rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
    954714                if (rc != EOK)
    955715                        return EIO;
     
    963723                 * set to one.
    964724                 */
    965                 if (!FAT_IS_FAT12(bs) &&
    966                         ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
     725                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    967726                        return ENOTSUP;
    968727        }
     
    973732/**
    974733 * @}
    975  */
     734 */ 
Note: See TracChangeset for help on using the changeset viewer.