Ignore:
File:
1 edited

Legend:

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

    rc7bbf029 rd260a95  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    4747#include <assert.h>
    4848#include <fibril_synch.h>
    49 #include <malloc.h>
    5049#include <mem.h>
    5150
     
    5453 * primitive boot sector members.
    5554 */
    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 
    6055#define CLBN2PBN(bs, cl, bn) \
    6156        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     
    6560 * during allocation of clusters. The lock does not have to be held durring
    6661 * deallocation of clusters.
    67  */ 
     62 */
    6863static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6964
     
    7772 * @param numc          If non-NULL, output argument holding the number of
    7873 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     74 * @param max_clusters  Maximum number of clusters to visit.
    8075 *
    8176 * @return              EOK on success or a negative error code.
    8277 */
    83 int 
     78int
    8479fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    8580    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    8681{
    87         block_t *b;
    8882        uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     83        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     84        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9085        int rc;
    9186
     
    9994        }
    10095
    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 
     96        while (clst < clst_last1 && clusters < max_clusters) {
    10597                assert(clst >= FAT_CLST_FIRST);
    10698                if (lastc)
    10799                        *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));
     100
    110101                /* 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;
     102                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
     103                if (rc != EOK)
     104                        return rc;
     105
     106                assert(clst != clst_bad);
    120107                clusters++;
    121108        }
    122109
    123         if (lastc && clst < FAT_CLST_LAST1)
     110        if (lastc && clst < clst_last1)
    124111                *lastc = clst;
    125112        if (numc)
     
    151138                return ELIMIT;
    152139
    153         if (nodep->firstc == FAT_CLST_ROOT) 
     140        if (nodep->firstc == FAT_CLST_ROOT)
    154141                goto fall_through;
    155142
     
    178165        if (rc != EOK)
    179166                return rc;
    180        
     167
    181168        /*
    182169         * Update the "current" cluster cache.
     
    198185 * @param clp           If not NULL, address where the cluster containing bn
    199186 *                      will be stored.
    200  *                      stored 
     187 *                      stored
    201188 * @param bn            Block number.
    202189 * @param flags         Flags passed to libblock.
     
    275262                        return rc;
    276263        }
    277        
     264
    278265        if (o >= pos)
    279266                return EOK;
    280        
     267
    281268        /* zero out the initial part of the new cluster chain */
    282269        for (o = boundary; o < pos; o += BPS(bs)) {
     
    308295    fat_cluster_t clst, fat_cluster_t *value)
    309296{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
     297        block_t *b, *b1;
     298        aoff64_t offset;
     299        int rc;
     300
     301        assert(fatno < FATCNT(bs));
     302
     303        if (FAT_IS_FAT12(bs))
     304                offset = (clst + clst/2);
     305        else
     306                offset = (clst * sizeof(fat_cluster_t));
    313307
    314308        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     309            offset / BPS(bs), BLOCK_FLAGS_NONE);
    316310        if (rc != EOK)
    317311                return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
     312
     313        /* This cluster access spans a sector boundary. Check only for FAT12 */
     314        if (FAT_IS_FAT12(bs) && (offset % BPS(bs)+1 == BPS(bs))) {
     315                /* Is it last sector of FAT? */
     316                if (offset / BPS(bs) < SF(bs)) {
     317                        /* No. Reading next sector */
     318                        rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
     319                            SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
     320                        if (rc != EOK) {
     321                                block_put(b);
     322                                return rc;
     323                        }
     324                        /*
     325                         * Combining value with last byte of current sector and
     326                         * first byte of next sector
     327                         */
     328                        *value  = *(uint8_t *)(b->data + BPS(bs) - 1);
     329                        *value |= *(uint8_t *)(b1->data);
     330
     331                        rc = block_put(b1);
     332                        if (rc != EOK) {
     333                                block_put(b);
     334                                return rc;
     335                        }
     336                }
     337                else {
     338                        /* Yes. It is last sector of FAT */
     339                        block_put(b);
     340                        return ERANGE;
     341                }
     342        }
     343        else
     344                *value = *(fat_cluster_t *)(b->data + offset % BPS(bs));
     345
     346        if (FAT_IS_FAT12(bs)) {
     347                if (clst & 0x0001)
     348                *value = (*value) >> 4;
     349                else
     350                *value = (*value) & 0x0fff;
     351        }
     352
     353        *value = uint16_t_le2host(*value);
    321354        rc = block_put(b);
    322        
     355
    323356        return rc;
    324357}
     
    338371    fat_cluster_t clst, fat_cluster_t value)
    339372{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342         int rc;
     373        block_t *b, *b1;
     374        aoff64_t offset;
     375        fat_cluster_t *cp, temp;
     376        int rc;
     377        int spans = 0;
    343378
    344379        assert(fatno < FATCNT(bs));
     380
     381        if (FAT_IS_FAT12(bs))
     382                offset = (clst + clst/2);
     383        else
     384                offset = (clst * sizeof(fat_cluster_t));
     385
    345386        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     387            offset / BPS(bs), BLOCK_FLAGS_NONE);
    347388        if (rc != EOK)
    348389                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 */
     390
     391        /* This cluster access spans a sector boundary. Check only for FAT12 */
     392        if (FAT_IS_FAT12(bs) && (offset % BPS(bs)+1 == BPS(bs))) {
     393                /* Is it last sector of FAT? */
     394                if (offset / BPS(bs) < SF(bs)) {
     395                        /* No. Reading next sector */
     396                        rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
     397                            SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
     398                        if (rc != EOK) {
     399                                block_put(b);
     400                                return rc;
     401                        }
     402                        /*
     403                         * Combining value with last byte of current sector and
     404                         * first byte of next sector
     405                         */
     406                        spans=1;
     407                        cp = &temp;
     408                        *cp  = *(uint8_t *)(b->data + BPS(bs) - 1);
     409                        *cp |= *(uint8_t *)(b1->data);
     410                }
     411                else {
     412                        /* Yes. It is last sector of fat */
     413                        block_put(b);
     414                        return ERANGE;
     415                }
     416        }
     417        else
     418                cp = (fat_cluster_t *)(b->data + offset % BPS(bs));
     419
     420        value = host2uint16_t_le(value);
     421        if (FAT_IS_FAT12(bs)) {
     422                if (clst & 0x0001) {
     423                        *cp &= 0x000f;
     424                        *cp |= value << 4;
     425                }
     426                else {
     427                        *cp &= 0xf000;
     428                        *cp |= value & 0x0fff;
     429                }
     430
     431                if (spans)
     432                {
     433                        *(uint8_t *)(b->data + BPS(bs) - 1) = cp[0];
     434                        *(uint8_t *)(b1->data) = cp[1];
     435
     436                        b1->dirty = true;
     437                        rc = block_put(b1);
     438                        if (rc != EOK) {
     439                                block_put(b);
     440                                return rc;
     441                        }
     442                }
     443        }
     444        else
     445                *cp = value;
     446
     447        b->dirty = true;        /* need to sync block */
    353448        rc = block_put(b);
    354449        return rc;
     
    369464        uint8_t fatno;
    370465        unsigned c;
     466        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    371467        int rc;
    372468
     
    374470                for (c = 0; c < nclsts; c++) {
    375471                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     472                            c == 0 ? clst_last1 : lifo[c - 1]);
    377473                        if (rc != EOK)
    378474                                return rc;
     
    404500    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405501{
    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;
     502        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     503        unsigned found = 0;     /* top of the free cluster number stack */
     504        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     505        int rc = EOK;
    411506
    412507        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    413508        if (!lifo)
    414509                return ENOMEM;
    415        
    416510        /*
    417511         * Search FAT1 for unused clusters.
    418512         */
    419513        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++) {
    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                                             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                         }
    470                 }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     514        for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
     515                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
     516                if (rc != EOK)
     517                break;
     518
     519                if (value == FAT_CLST_RES0) {
     520                /*
     521                 * The cluster is free. Put it into our stack
     522                 * of found clusters and mark it as non-free.
     523                 */
     524                lifo[found] = clst;
     525                rc = fat_set_cluster(bs, devmap_handle, FAT1, clst,
     526                    (found == 0) ?  clst_last1 : lifo[found - 1]);
     527                if (rc != EOK)
     528                        break;
     529
     530                found++;
     531                }
     532        }
     533
     534        if (rc == EOK && found == nclsts) {
     535                rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
     536                if (rc == EOK) {
     537                        *mcl = lifo[found - 1];
     538                        *lcl = lifo[0];
     539                        free(lifo);
    474540                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
    477                 }
    478         }
    479 out:
    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--) {
     541                        return EOK;
     542                }
     543        }
     544
     545        /* If something wrong - free the clusters */
     546        if (found > 0) {
     547                while (found--) {
    487548                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    488549                    FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
     550                }
     551        }
     552
    495553        free(lifo);
     554        fibril_mutex_unlock(&fat_alloc_lock);
    496555        return ENOSPC;
    497556}
     
    509568{
    510569        unsigned fatno;
    511         fat_cluster_t nextc;
     570        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512571        int rc;
    513572
    514573        /* 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);
     574        while (firstc < FAT_CLST_LAST1(bs)) {
     575                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
    517576                rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    518577                if (rc != EOK)
     
    565624
    566625                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
    568                             lastc, mcl);
     626                        rc = fat_set_cluster(bs, nodep->idx->devmap_handle,
     627                            fatno, lastc, mcl);
    569628                        if (rc != EOK)
    570629                                return rc;
     
    590649int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591650{
     651        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    592652        int rc;
    593653        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     
    618678                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    619679                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    620                             FAT_CLST_LAST1);
     680                            clst_last1);
    621681                        if (rc != EOK)
    622682                                return rc;
     
    677737
    678738        /* Check total number of sectors. */
    679 
    680739        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    681740                return ENOTSUP;
    682741
    683742        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     743            bs->totsec16 != bs->totsec32)
    685744                return ENOTSUP;
    686745
     
    705764
    706765        /* Check signature of each FAT. */
    707 
    708766        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    709767                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     
    723781                 * set to one.
    724782                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     783                if (!FAT_IS_FAT12(bs) && ((e0 >> 8) != 0xff || e1 != 0xffff))
    726784                        return ENOTSUP;
    727785        }
     
    732790/**
    733791 * @}
    734  */ 
     792 */
Note: See TracChangeset for help on using the changeset viewer.