Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f3d4cd35 in mainline for uspace/srv/fs/exfat/exfat_fat.c


Ignore:
Timestamp:
2011-08-14T07:06:33Z (10 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master
Children:
998a78f
Parents:
7f0c08c
Message:

exFAT: functions for managing clusters chain and skeleton for
bitmap operations

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/exfat/exfat_fat.c

    r7f0c08c rf3d4cd35  
    5656 * deallocation of clusters.
    5757 */
    58 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
     58static FIBRIL_MUTEX_INITIALIZE(exfat_alloc_lock);
    5959
    6060/** Walk the cluster chain.
     
    7272 */
    7373int
    74 fat_cluster_walk(exfat_bs_t *bs, devmap_handle_t devmap_handle,
     74exfat_cluster_walk(exfat_bs_t *bs, devmap_handle_t devmap_handle,
    7575    exfat_cluster_t firstc, exfat_cluster_t *lastc, uint32_t *numc,
    7676    uint32_t max_clusters)
     
    8989        }
    9090
    91         while (clst <= EXFAT_CLST_LAST && clusters < max_clusters) {
     91        while (clst != EXFAT_CLST_EOF && clusters < max_clusters) {
    9292                assert(clst >= EXFAT_CLST_FIRST);
    9393                if (lastc)
    9494                        *lastc = clst;  /* remember the last cluster number */
    9595
    96                 rc = fat_get_cluster(bs, devmap_handle, clst, &clst);
     96                rc = exfat_get_cluster(bs, devmap_handle, clst, &clst);
    9797                if (rc != EOK)
    9898                        return rc;
     
    102102        }
    103103
    104         if (lastc && clst <= EXFAT_CLST_LAST)
     104        if (lastc && clst != EXFAT_CLST_EOF)
    105105                *lastc = clst;
    106106        if (numc)
     
    202202        } else {
    203203                max_clusters = bn / SPC(bs);
    204                 rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
     204                rc = exfat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
    205205                if (rc != EOK)
    206206                        return rc;
     
    228228 */
    229229int
    230 fat_get_cluster(exfat_bs_t *bs, devmap_handle_t devmap_handle,
     230exfat_get_cluster(exfat_bs_t *bs, devmap_handle_t devmap_handle,
    231231    exfat_cluster_t clst, exfat_cluster_t *value)
    232232{
     
    258258 */
    259259int
    260 fat_set_cluster(exfat_bs_t *bs, devmap_handle_t devmap_handle,
     260exfat_set_cluster(exfat_bs_t *bs, devmap_handle_t devmap_handle,
    261261    exfat_cluster_t clst, exfat_cluster_t value)
    262262{
     
    278278}
    279279
     280/** Allocate clusters in FAT.
     281 *
     282 * This function will attempt to allocate the requested number of clusters in
     283 * the FAT.  The FAT will be altered so that the allocated
     284 * clusters form an independent chain (i.e. a chain which does not belong to any
     285 * file yet).
     286 *
     287 * @param bs            Buffer holding the boot sector of the file system.
     288 * @param devmap_handle Device handle of the file system.
     289 * @param nclsts        Number of clusters to allocate.
     290 * @param mcl           Output parameter where the first cluster in the chain
     291 *                      will be returned.
     292 * @param lcl           Output parameter where the last cluster in the chain
     293 *                      will be returned.
     294 *
     295 * @return              EOK on success, a negative error code otherwise.
     296 */
     297int
     298exfat_alloc_clusters(exfat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
     299    exfat_cluster_t *mcl, exfat_cluster_t *lcl)
     300{
     301        exfat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     302        unsigned found = 0;     /* top of the free cluster number stack */
     303        exfat_cluster_t clst, value;
     304        int rc = EOK;
     305
     306        lifo = (exfat_cluster_t *) malloc(nclsts * sizeof(exfat_cluster_t));
     307        if (!lifo)
     308                return ENOMEM;
     309
     310        fibril_mutex_lock(&exfat_alloc_lock);
     311        for (clst=EXFAT_CLST_FIRST; clst < DATA_CNT(bs)+2 && found < nclsts; clst++) {
     312                rc = exfat_get_cluster(bs, devmap_handle, clst, &value);
     313                if (rc != EOK)
     314                        break;
     315
     316                if (value == 0) {
     317                   /*
     318                        * The cluster is free. Put it into our stack
     319                        * of found clusters and mark it as non-free.
     320                        */
     321                        lifo[found] = clst;
     322                        rc = exfat_set_cluster(bs, devmap_handle, clst,
     323                                (found == 0) ?  EXFAT_CLST_EOF : lifo[found - 1]);
     324                        if (rc != EOK)
     325                                break;
     326
     327                        found++;
     328                }
     329        }
     330
     331        if (rc == EOK && found == nclsts) {
     332                *mcl = lifo[found - 1];
     333                *lcl = lifo[0];
     334                free(lifo);
     335                fibril_mutex_unlock(&exfat_alloc_lock);
     336                return EOK;
     337        }
     338
     339        /* If something wrong - free the clusters */
     340        if (found > 0) {
     341                while (found--)
     342                        rc = exfat_set_cluster(bs, devmap_handle, lifo[found], 0);
     343        }
     344
     345        free(lifo);
     346        fibril_mutex_unlock(&exfat_alloc_lock);
     347        return ENOSPC;
     348}
     349
     350/** Free clusters forming a cluster chain in FAT.
     351 *
     352 * @param bs            Buffer hodling the boot sector of the file system.
     353 * @param devmap_handle Device handle of the file system.
     354 * @param firstc        First cluster in the chain which is to be freed.
     355 *
     356 * @return              EOK on success or a negative return code.
     357 */
     358int
     359exfat_free_clusters(exfat_bs_t *bs, devmap_handle_t devmap_handle, exfat_cluster_t firstc)
     360{
     361        exfat_cluster_t nextc;
     362        int rc;
     363
     364        /* Mark all clusters in the chain as free */
     365        while (firstc != EXFAT_CLST_EOF) {
     366                assert(firstc >= EXFAT_CLST_FIRST && firstc < EXFAT_CLST_BAD);
     367                rc = exfat_get_cluster(bs, devmap_handle, firstc, &nextc);
     368                if (rc != EOK)
     369                        return rc;
     370                rc = exfat_set_cluster(bs, devmap_handle, firstc, 0);
     371                if (rc != EOK)
     372                        return rc;
     373                firstc = nextc;
     374        }
     375
     376        return EOK;
     377}
     378
     379/** Append a cluster chain to the last file cluster in FAT.
     380 *
     381 * @param bs            Buffer holding the boot sector of the file system.
     382 * @param nodep         Node representing the file.
     383 * @param mcl           First cluster of the cluster chain to append.
     384 * @param lcl           Last cluster of the cluster chain to append.
     385 *
     386 * @return              EOK on success or a negative error code.
     387 */
     388int
     389exfat_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep, exfat_cluster_t mcl,
     390    exfat_cluster_t lcl)
     391{
     392        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     393        exfat_cluster_t lastc;
     394        int rc;
     395
     396        if (nodep->firstc == 0) {
     397                /* No clusters allocated to the node yet. */
     398                nodep->firstc = mcl;
     399                nodep->dirty = true;    /* need to sync node */
     400        } else {
     401                if (nodep->lastc_cached_valid) {
     402                        lastc = nodep->lastc_cached_value;
     403                        nodep->lastc_cached_valid = false;
     404                } else {
     405                        rc = exfat_cluster_walk(bs, devmap_handle, nodep->firstc,
     406                            &lastc, NULL, (uint16_t) -1);
     407                        if (rc != EOK)
     408                                return rc;
     409                }
     410
     411                rc = exfat_set_cluster(bs, nodep->idx->devmap_handle, lastc, mcl);
     412                if (rc != EOK)
     413                        return rc;
     414        }
     415
     416        nodep->lastc_cached_valid = true;
     417        nodep->lastc_cached_value = lcl;
     418
     419        return EOK;
     420}
     421
     422/** Chop off node clusters in FAT.
     423 *
     424 * @param bs            Buffer holding the boot sector of the file system.
     425 * @param nodep         FAT node where the chopping will take place.
     426 * @param lcl           Last cluster which will remain in the node. If this
     427 *                      argument is FAT_CLST_RES0, then all clusters will
     428 *                      be chopped off.
     429 *
     430 * @return              EOK on success or a negative return code.
     431 */
     432int exfat_chop_clusters(exfat_bs_t *bs, exfat_node_t *nodep, exfat_cluster_t lcl)
     433{
     434        int rc;
     435        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     436
     437        /*
     438         * Invalidate cached cluster numbers.
     439         */
     440        nodep->lastc_cached_valid = false;
     441        if (nodep->currc_cached_value != lcl)
     442                nodep->currc_cached_valid = false;
     443
     444        if (lcl == 0) {
     445                /* The node will have zero size and no clusters allocated. */
     446                rc = exfat_free_clusters(bs, devmap_handle, nodep->firstc);
     447                if (rc != EOK)
     448                        return rc;
     449                nodep->firstc = 0;
     450                nodep->dirty = true;            /* need to sync node */
     451        } else {
     452                exfat_cluster_t nextc;
     453
     454                rc = exfat_get_cluster(bs, devmap_handle, lcl, &nextc);
     455                if (rc != EOK)
     456                        return rc;
     457
     458                /* Terminate the cluster chain */
     459                rc = exfat_set_cluster(bs, devmap_handle, lcl, EXFAT_CLST_EOF);
     460                if (rc != EOK)
     461                        return rc;
     462
     463                /* Free all following clusters. */
     464                rc = exfat_free_clusters(bs, devmap_handle, nextc);
     465                if (rc != EOK)
     466                        return rc;
     467        }
     468
     469        /*
     470         * Update and re-enable the last cluster cache.
     471         */
     472        nodep->lastc_cached_valid = true;
     473        nodep->lastc_cached_value = lcl;
     474
     475        return EOK;
     476}
     477
     478int bitmap_alloc_clusters(exfat_bs_t *bs, devmap_handle_t devmap_handle,
     479    exfat_cluster_t *firstc, exfat_cluster_t count)
     480{
     481        /* TODO */
     482        return EOK;
     483}
     484
     485
     486int bitmap_append_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
     487    exfat_cluster_t count)
     488{
     489        /* TODO */
     490        return EOK;
     491}
     492
     493
     494int bitmap_free_clusters(exfat_bs_t *bs, exfat_node_t *nodep,
     495    exfat_cluster_t count)
     496{
     497        /* TODO */
     498        return EOK;
     499}
     500
     501
     502int bitmap_replicate_clusters(exfat_bs_t *bs, exfat_node_t *nodep)
     503{
     504        /* TODO */
     505        return EOK;
     506}
     507
     508
     509
    280510/** Perform basic sanity checks on the file system.
    281511 *
Note: See TracChangeset for help on using the changeset viewer.