Ignore:
File:
1 edited

Legend:

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

    rd260a95 rc7bbf029  
    2929/** @addtogroup fs
    3030 * @{
    31  */
     31 */ 
    3232
    3333/**
     
    4747#include <assert.h>
    4848#include <fibril_synch.h>
     49#include <malloc.h>
    4950#include <mem.h>
    5051
     
    5354 * primitive boot sector members.
    5455 */
     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
    5560#define CLBN2PBN(bs, cl, bn) \
    5661        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     
    6065 * during allocation of clusters. The lock does not have to be held durring
    6166 * deallocation of clusters.
    62  */
     67 */ 
    6368static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6469
     
    7277 * @param numc          If non-NULL, output argument holding the number of
    7378 *                      clusters seen during the walk.
    74  * @param max_clusters  Maximum number of clusters to visit.
     79 * @param max_clusters  Maximum number of clusters to visit.   
    7580 *
    7681 * @return              EOK on success or a negative error code.
    7782 */
    78 int
     83int 
    7984fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    8085    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    8186{
     87        block_t *b;
    8288        uint16_t clusters = 0;
    83         fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
    84         fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
     89        fat_cluster_t clst = firstc;
    8590        int rc;
    8691
     
    9499        }
    95100
    96         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
    97105                assert(clst >= FAT_CLST_FIRST);
    98106                if (lastc)
    99107                        *lastc = clst;  /* remember the last cluster number */
    100 
     108                fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     109                fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    101110                /* read FAT1 */
    102                 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
    103                 if (rc != EOK)
    104                         return rc;
    105 
    106                 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;
    107120                clusters++;
    108121        }
    109122
    110         if (lastc && clst < clst_last1)
     123        if (lastc && clst < FAT_CLST_LAST1)
    111124                *lastc = clst;
    112125        if (numc)
     
    138151                return ELIMIT;
    139152
    140         if (nodep->firstc == FAT_CLST_ROOT)
     153        if (nodep->firstc == FAT_CLST_ROOT) 
    141154                goto fall_through;
    142155
     
    165178        if (rc != EOK)
    166179                return rc;
    167 
     180       
    168181        /*
    169182         * Update the "current" cluster cache.
     
    185198 * @param clp           If not NULL, address where the cluster containing bn
    186199 *                      will be stored.
    187  *                      stored
     200 *                      stored 
    188201 * @param bn            Block number.
    189202 * @param flags         Flags passed to libblock.
     
    262275                        return rc;
    263276        }
    264 
     277       
    265278        if (o >= pos)
    266279                return EOK;
    267 
     280       
    268281        /* zero out the initial part of the new cluster chain */
    269282        for (o = boundary; o < pos; o += BPS(bs)) {
     
    295308    fat_cluster_t clst, fat_cluster_t *value)
    296309{
    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));
     310        block_t *b;
     311        fat_cluster_t *cp;
     312        int rc;
    307313
    308314        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    309             offset / BPS(bs), BLOCK_FLAGS_NONE);
     315            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    310316        if (rc != EOK)
    311317                return rc;
    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);
     318        cp = (fat_cluster_t *)b->data +
     319            clst % (BPS(bs) / sizeof(fat_cluster_t));
     320        *value = uint16_t_le2host(*cp);
    354321        rc = block_put(b);
    355 
     322       
    356323        return rc;
    357324}
     
    371338    fat_cluster_t clst, fat_cluster_t value)
    372339{
    373         block_t *b, *b1;
    374         aoff64_t offset;
    375         fat_cluster_t *cp, temp;
    376         int rc;
    377         int spans = 0;
     340        block_t *b;
     341        fat_cluster_t *cp;
     342        int rc;
    378343
    379344        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 
    386345        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    387             offset / BPS(bs), BLOCK_FLAGS_NONE);
     346            (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    388347        if (rc != EOK)
    389348                return rc;
    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 */
     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 */
    448353        rc = block_put(b);
    449354        return rc;
     
    464369        uint8_t fatno;
    465370        unsigned c;
    466         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    467371        int rc;
    468372
     
    470374                for (c = 0; c < nclsts; c++) {
    471375                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    472                             c == 0 ? clst_last1 : lifo[c - 1]);
     376                            c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
    473377                        if (rc != EOK)
    474378                                return rc;
     
    500404    fat_cluster_t *mcl, fat_cluster_t *lcl)
    501405{
    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;
     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;
    506411
    507412        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    508413        if (!lifo)
    509414                return ENOMEM;
     415       
    510416        /*
    511417         * Search FAT1 for unused clusters.
    512418         */
    513419        fibril_mutex_lock(&fat_alloc_lock);
    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++;
     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                        }
    531470                }
    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];
     471                rc = block_put(blk);
     472                if (rc != EOK) {
     473error:
     474                        fibril_mutex_unlock(&fat_alloc_lock);
    539475                        free(lifo);
    540                         fibril_mutex_unlock(&fat_alloc_lock);
    541                         return EOK;
     476                        return rc;
    542477                }
    543478        }
    544 
    545         /* If something wrong - free the clusters */
    546         if (found > 0) {
    547                 while (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--) {
    548487                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    549488                    FAT_CLST_RES0);
     489                if (rc != EOK) {
     490                        free(lifo);
     491                        return rc;
    550492                }
    551493        }
    552 
     494       
    553495        free(lifo);
    554         fibril_mutex_unlock(&fat_alloc_lock);
    555496        return ENOSPC;
    556497}
     
    568509{
    569510        unsigned fatno;
    570         fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
     511        fat_cluster_t nextc;
    571512        int rc;
    572513
    573514        /* Mark all clusters in the chain as free in all copies of FAT. */
    574         while (firstc < FAT_CLST_LAST1(bs)) {
    575                 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     515        while (firstc < FAT_CLST_LAST1) {
     516                assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    576517                rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    577518                if (rc != EOK)
     
    624565
    625566                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    626                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle,
    627                             fatno, lastc, mcl);
     567                        rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
     568                            lastc, mcl);
    628569                        if (rc != EOK)
    629570                                return rc;
     
    649590int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    650591{
    651         fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    652592        int rc;
    653593        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     
    678618                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    679619                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    680                             clst_last1);
     620                            FAT_CLST_LAST1);
    681621                        if (rc != EOK)
    682622                                return rc;
     
    737677
    738678        /* Check total number of sectors. */
     679
    739680        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    740681                return ENOTSUP;
    741682
    742683        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    743             bs->totsec16 != bs->totsec32)
     684            bs->totsec16 != bs->totsec32) 
    744685                return ENOTSUP;
    745686
     
    764705
    765706        /* Check signature of each FAT. */
     707
    766708        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    767709                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     
    781723                 * set to one.
    782724                 */
    783                 if (!FAT_IS_FAT12(bs) && ((e0 >> 8) != 0xff || e1 != 0xffff))
     725                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    784726                        return ENOTSUP;
    785727        }
     
    790732/**
    791733 * @}
    792  */
     734 */ 
Note: See TracChangeset for help on using the changeset viewer.