Changeset fc35e98 in mainline for uspace/srv/fs/fat/fat_fat.c


Ignore:
Timestamp:
2011-04-07T19:14:33Z (14 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
97bc3ee
Parents:
ccca251
Message:

Basic support for FAT12 file system. With many limitations of course.

File:
1 edited

Legend:

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

    rccca251 rfc35e98  
    8484    fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    8585{
    86         block_t *b;
    8786        uint16_t clusters = 0;
    8887        fat_cluster_t clst = firstc;
    8988        int rc;
     89        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 : FAT12_CLST_LAST1;
     90        uint16_t clst_bad   = FATTYPE(bs) == 16 ? FAT16_CLST_BAD : FAT12_CLST_BAD;
    9091
    9192        if (firstc == FAT_CLST_RES0) {
     
    9899        }
    99100
    100         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    101                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    102                 unsigned fidx;  /* FAT1 entry index */
    103 
     101        while (clst < clst_last1 && clusters < max_clusters) {
    104102                assert(clst >= FAT_CLST_FIRST);
    105103                if (lastc)
    106104                        *lastc = clst;  /* remember the last cluster number */
    107                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    108                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
    109                 /* read FAT1 */
    110                 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
    111                     BLOCK_FLAGS_NONE);
    112                 if (rc != EOK)
    113                         return rc;
    114                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    115                 assert(clst != FAT_CLST_BAD);
    116                 rc = block_put(b);
    117                 if (rc != EOK)
    118                         return rc;
    119                 clusters++;
    120         }
    121 
    122         if (lastc && clst < FAT_CLST_LAST1)
     105
     106                /* read FAT1 */
     107                /* We should use fat_get_cluster instead */
     108                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
     109                if (rc != EOK)
     110                        return rc;
     111
     112                assert(clst != clst_bad);
     113
     114                clusters++;
     115        }
     116
     117        if (lastc && clst < clst_last1)
    123118                *lastc = clst;
    124119        if (numc)
     
    309304        block_t *b;
    310305        fat_cluster_t *cp;
    311         int rc;
    312 
    313         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    314             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    315         if (rc != EOK)
    316                 return rc;
    317         cp = (fat_cluster_t *)b->data +
    318             clst % (BPS(bs) / sizeof(fat_cluster_t));
    319         *value = uint16_t_le2host(*cp);
     306        aoff64_t fsec;  /* sector offset relative to FAT */
     307        unsigned fidx;  /* entry index */
     308        int rc;
     309
     310        assert(fatno < FATCNT(bs));
     311
     312
     313        if (FATTYPE(bs) == 16)
     314        {
     315            fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     316            fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     317        }
     318        else
     319        {
     320            fsec = (clst + clst/2) / BPS(bs);
     321            fidx = clst % (2 * BPS(bs) / 3 );
     322        }
     323
     324        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     325                       fsec, BLOCK_FLAGS_NONE);
     326        if (rc != EOK)
     327                return rc;
     328
     329        if (FATTYPE(bs) == 16)
     330            cp = &((fat_cluster_t *)b->data)[fidx];
     331        else
     332            cp = (fat_cluster_t *)(b->data + fidx);
     333
     334        *value = *cp;
     335
     336        if (FATTYPE(bs) == 12)
     337        {
     338            if (clst & 0x0001)
     339                *value = (*value) >> 4;
     340            else
     341                *value = (*value) & 0x0fff;
     342        }
     343
     344        *value = uint16_t_le2host(*value);
    320345        rc = block_put(b);
    321346       
     
    340365        fat_cluster_t *cp;
    341366        int rc;
    342 
    343         assert(fatno < FATCNT(bs));
    344         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    345             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     367        aoff64_t fsec;  /* sector offset relative to FAT */
     368        unsigned fidx;  /* entry index */
     369
     370        assert(fatno < FATCNT(bs));
     371
     372        if (FATTYPE(bs) == 16)
     373        {
     374            fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
     375            fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     376        }
     377        else
     378        {
     379            fsec = (clst + clst/2) / BPS(bs);
     380            fidx = clst % (2 * BPS(bs) / 3 );
     381        }
     382
     383        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     384                       fsec, BLOCK_FLAGS_NONE);
    346385        if (rc != EOK)
    347386                return rc;
    348         cp = (fat_cluster_t *)b->data +
    349             clst % (BPS(bs) / sizeof(fat_cluster_t));
    350         *cp = host2uint16_t_le(value);
    351         b->dirty = true;                /* need to sync block */
     387
     388        if (FATTYPE(bs) == 12)
     389        {
     390            cp = (fat_cluster_t *)(b->data + fidx);
     391            if (clst & 0x0001)
     392            {
     393                *cp &= 0x000f;
     394                *cp |= host2uint16_t_le(value) << 4;
     395            }
     396            else
     397            {
     398                *cp &= 0xf000;
     399                *cp |= host2uint16_t_le(value) & 0x0fff;
     400            }
     401        }
     402        else
     403        {
     404            cp = &((fat_cluster_t *)b->data)[fidx];
     405            *cp = host2uint16_t_le(value);
     406        }
     407
     408        b->dirty = true;                /* need to sync block */
    352409        rc = block_put(b);
    353410        return rc;
     
    369426        unsigned c;
    370427        int rc;
     428        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
     429                                                  FAT12_CLST_LAST1;
    371430
    372431        for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
    373432                for (c = 0; c < nclsts; c++) {
    374433                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    375                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     434                            c == 0 ? clst_last1 : lifo[c - 1]);
    376435                        if (rc != EOK)
    377436                                return rc;
     
    403462    fat_cluster_t *mcl, fat_cluster_t *lcl)
    404463{
    405         block_t *blk;
    406         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    407         unsigned found = 0;     /* top of the free cluster number stack */
    408         unsigned b, c, cl;
    409         int rc;
    410 
    411         lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    412         if (!lifo)
    413                 return ENOMEM;
    414        
    415         /*
    416          * Search FAT1 for unused clusters.
    417          */
    418         fibril_mutex_lock(&fat_alloc_lock);
    419         for (b = 0, cl = 0; b < SF(bs); b++) {
    420                 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
    421                     BLOCK_FLAGS_NONE);
    422                 if (rc != EOK)
    423                         goto error;
    424                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
    425                         /*
    426                          * Check if the entire cluster is physically there.
    427                          * This check becomes necessary when the file system is
    428                          * created with fewer total sectors than how many is
    429                          * inferred from the size of the file allocation table
    430                          * or when the last cluster ends beyond the end of the
    431                          * device.
    432                          */
    433                         if ((cl >= FAT_CLST_FIRST) &&
    434                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    435                                 rc = block_put(blk);
    436                                 if (rc != EOK)
    437                                         goto error;
    438                                 goto out;
    439                         }
    440 
    441                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    442                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    443                                 /*
    444                                  * The cluster is free. Put it into our stack
    445                                  * of found clusters and mark it as non-free.
    446                                  */
    447                                 lifo[found] = cl;
    448                                 *clst = (found == 0) ?
    449                                     host2uint16_t_le(FAT_CLST_LAST1) :
    450                                     host2uint16_t_le(lifo[found - 1]);
    451                                 blk->dirty = true;      /* need to sync block */
    452                                 if (++found == nclsts) {
    453                                         /* we are almost done */
    454                                         rc = block_put(blk);
    455                                         if (rc != EOK)
    456                                                 goto error;
    457                                         /* update the shadow copies of FAT */
    458                                         rc = fat_alloc_shadow_clusters(bs,
    459                                             devmap_handle, lifo, nclsts);
    460                                         if (rc != EOK)
    461                                                 goto error;
    462                                         *mcl = lifo[found - 1];
    463                                         *lcl = lifo[0];
    464                                         free(lifo);
    465                                         fibril_mutex_unlock(&fat_alloc_lock);
    466                                         return EOK;
    467                                 }
    468                         }
    469                 }
    470                 rc = block_put(blk);
    471                 if (rc != EOK) {
    472 error:
    473                         fibril_mutex_unlock(&fat_alloc_lock);
    474                         free(lifo);
    475                         return rc;
    476                 }
    477         }
    478 out:
    479         fibril_mutex_unlock(&fat_alloc_lock);
    480 
    481         /*
    482          * We could not find enough clusters. Now we need to free the clusters
    483          * we have allocated so far.
    484          */
    485         while (found--) {
    486                 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    487                     FAT_CLST_RES0);
    488                 if (rc != EOK) {
    489                         free(lifo);
    490                         return rc;
    491                 }
    492         }
    493        
    494         free(lifo);
    495         return ENOSPC;
     464        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     465        unsigned found = 0;     /* top of the free cluster number stack */
     466        fat_cluster_t clst, max_clst, value;
     467        int rc = EOK;
     468        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
     469                                                  FAT12_CLST_LAST1;
     470
     471
     472        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     473        if (!lifo)
     474                return ENOMEM;
     475
     476        /*
     477         * Search FAT1 for unused clusters.
     478         */
     479
     480        if (FATTYPE(bs) == 16)
     481            max_clst = SF(bs) * BPS(bs) / sizeof(fat_cluster_t);
     482        else
     483            max_clst = 2 *SF(bs) * BPS(bs) / 3;
     484
     485        fibril_mutex_lock(&fat_alloc_lock);
     486        for (clst=0; clst < max_clst && found < nclsts; clst++)
     487        {
     488            rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
     489            if (rc != EOK)
     490                break;
     491            /*
     492            * Check if the entire cluster is physically there.
     493            * This check becomes necessary when the file system is
     494            * created with fewer total sectors than how many is
     495            * inferred from the size of the file allocation table
     496            * or when the last cluster ends beyond the end of the
     497            * device.
     498            */
     499            if ((clst >= FAT_CLST_FIRST) &&
     500                CLBN2PBN(bs, clst, SPC(bs) - 1) >= TS(bs)) {
     501                    rc = EIO;
     502                    break;
     503            }
     504            if (value == FAT_CLST_RES0) {
     505                /*
     506                * The cluster is free. Put it into our stack
     507                * of found clusters and mark it as non-free.
     508                */
     509                lifo[found] = clst;
     510                rc = fat_set_cluster(bs, devmap_handle, FAT1, clst,
     511                                     (found == 0) ? clst_last1 :
     512                                                    lifo[found - 1]);
     513                if (rc != EOK)
     514                    break;
     515
     516                found++;
     517            }
     518        }
     519
     520        if (rc == EOK && found == nclsts)
     521        {
     522            rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
     523            if (rc == EOK)
     524            {
     525                *mcl = lifo[found - 1];
     526                *lcl = lifo[0];
     527                free(lifo);
     528                fibril_mutex_unlock(&fat_alloc_lock);
     529                return EOK;
     530            }
     531        }
     532
     533        /* If something wrong - free the clusters */
     534        if (found > 0)
     535        {
     536            while (found--) {
     537                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
     538                                     FAT_CLST_RES0);
     539            }
     540        }
     541
     542        free(lifo);
     543        fibril_mutex_unlock(&fat_alloc_lock);
     544        return ENOSPC;
    496545}
    497546
     
    510559        fat_cluster_t nextc;
    511560        int rc;
     561        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
     562                                                  FAT12_CLST_LAST1;
     563        uint16_t clst_bad =   FATTYPE(bs) == 16 ? FAT16_CLST_BAD :
     564                                                  FAT12_CLST_BAD;
    512565
    513566        /* Mark all clusters in the chain as free in all copies of FAT. */
    514         while (firstc < FAT_CLST_LAST1) {
    515                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
     567        while (firstc < clst_last1) {
     568                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
    516569                rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    517570                if (rc != EOK)
     
    591644        int rc;
    592645        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     646        uint16_t clst_last1 = FATTYPE(bs) == 16 ? FAT16_CLST_LAST1 :
     647                                                  FAT12_CLST_LAST1;
    593648
    594649        /*
     
    617672                for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    618673                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    619                             FAT_CLST_LAST1);
     674                            clst_last1);
    620675                        if (rc != EOK)
    621676                                return rc;
     
    676731
    677732        /* Check total number of sectors. */
    678 
    679733        if (bs->totsec16 == 0 && bs->totsec32 == 0)
    680734                return ENOTSUP;
     
    704758
    705759        /* Check signature of each FAT. */
    706 
    707760        for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    708761                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     
    722775                 * set to one.
    723776                 */
    724                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     777                /* Disabled for testing FAT12
     778                if ((e0 >> 8) != 0xff || e1 != 0xffff)
    725779                        return ENOTSUP;
     780                */
    726781        }
    727782
Note: See TracChangeset for help on using the changeset viewer.