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


Ignore:
Timestamp:
2011-07-14T11:33:54Z (13 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4dd9395
Parents:
e584623
Message:

exFAT: functions for FAT.

  1. fat_cluster_walk
  2. exfat_block_get
  3. exfat_block_get_by_clst
File:
1 edited

Legend:

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

    re584623 rc223ee2  
    5858static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    5959
     60/** Walk the cluster chain.
     61 *
     62 * @param bs            Buffer holding the boot sector for the file.
     63 * @param devmap_handle Device handle of the device with the file.
     64 * @param firstc        First cluster to start the walk with.
     65 * @param lastc         If non-NULL, output argument hodling the last cluster
     66 *                      number visited.
     67 * @param numc          If non-NULL, output argument holding the number of
     68 *                      clusters seen during the walk.
     69 * @param max_clusters  Maximum number of clusters to visit.
     70 *
     71 * @return              EOK on success or a negative error code.
     72 */
     73int
     74fat_cluster_walk(exfat_bs_t *bs, devmap_handle_t devmap_handle,
     75    exfat_cluster_t firstc, exfat_cluster_t *lastc, uint32_t *numc,
     76    uint32_t max_clusters)
     77{
     78        uint32_t clusters = 0;
     79        exfat_cluster_t clst = firstc;
     80        int rc;
     81
     82        if (firstc < EXFAT_CLST_FIRST) {
     83                /* No space allocated to the file. */
     84                if (lastc)
     85                        *lastc = firstc;
     86                if (numc)
     87                        *numc = 0;
     88                return EOK;
     89        }
     90
     91        while (clst <= EXFAT_CLST_LAST && clusters < max_clusters) {
     92                assert(clst >= EXFAT_CLST_FIRST);
     93                if (lastc)
     94                        *lastc = clst;  /* remember the last cluster number */
     95
     96                rc = fat_get_cluster(bs, devmap_handle, clst, &clst);
     97                if (rc != EOK)
     98                        return rc;
     99
     100                assert(clst != EXFAT_CLST_BAD);
     101                clusters++;
     102        }
     103
     104        if (lastc && clst <= EXFAT_CLST_LAST)
     105                *lastc = clst;
     106        if (numc)
     107                *numc = clusters;
     108
     109        return EOK;
     110}
     111
     112/** Read block from file located on a exFAT file system.
     113 *
     114 * @param block         Pointer to a block pointer for storing result.
     115 * @param bs            Buffer holding the boot sector of the file system.
     116 * @param nodep         FAT node.
     117 * @param bn            Block number.
     118 * @param flags         Flags passed to libblock.
     119 *
     120 * @return              EOK on success or a negative error code.
     121 */
     122int
     123exfat_block_get(block_t **block, exfat_bs_t *bs, exfat_node_t *nodep,
     124    aoff64_t bn, int flags)
     125{
     126        exfat_cluster_t firstc = nodep->firstc;
     127        exfat_cluster_t currc;
     128        aoff64_t relbn = bn;
     129        int rc;
     130
     131        if (!nodep->size)
     132                return ELIMIT;
     133
     134        if (nodep->fragmented) {
     135                if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
     136                        nodep->lastc_cached_valid) {
     137                                /*
     138                        * This is a request to read a block within the last cluster
     139                        * when fortunately we have the last cluster number cached.
     140                        */
     141                        return block_get(block, nodep->idx->devmap_handle, DATA_FS(bs) +
     142                        (nodep->lastc_cached_value-EXFAT_CLST_FIRST)*SPC(bs) +
     143                            (bn % SPC(bs)), flags);
     144                }
     145
     146                if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
     147                        /*
     148                        * We can start with the cluster cached by the previous call to
     149                        * fat_block_get().
     150                        */
     151                        firstc = nodep->currc_cached_value;
     152                        relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
     153                }
     154        }
     155
     156        rc = exfat_block_get_by_clst(block, bs, nodep->idx->devmap_handle,
     157            nodep->fragmented, firstc, &currc, relbn, flags);
     158        if (rc != EOK)
     159                return rc;
     160
     161        /*
     162         * Update the "current" cluster cache.
     163         */
     164        nodep->currc_cached_valid = true;
     165        nodep->currc_cached_bn = bn;
     166        nodep->currc_cached_value = currc;
     167
     168        return rc;
     169}
     170
     171/** Read block from file located on a FAT file system.
     172 *
     173 * @param block         Pointer to a block pointer for storing result.
     174 * @param bs            Buffer holding the boot sector of the file system.
     175 * @param devmap_handle Device handle of the file system.
     176 * @param fcl           First cluster used by the file. Can be zero if the file
     177 *                      is empty.
     178 * @param clp           If not NULL, address where the cluster containing bn
     179 *                      will be stored.
     180 *                      stored
     181 * @param bn            Block number.
     182 * @param flags         Flags passed to libblock.
     183 *
     184 * @return              EOK on success or a negative error code.
     185 */
     186int
     187exfat_block_get_by_clst(block_t **block, exfat_bs_t *bs,
     188    devmap_handle_t devmap_handle, bool fragmented, exfat_cluster_t fcl,
     189    exfat_cluster_t *clp, aoff64_t bn, int flags)
     190{
     191        uint32_t clusters;
     192        uint32_t max_clusters;
     193        exfat_cluster_t c;
     194        int rc;
     195
     196        if (fcl < EXFAT_CLST_FIRST)
     197                return ELIMIT;
     198
     199        if (!fragmented) {
     200                rc = block_get(block, devmap_handle, DATA_FS(bs) +
     201                    (fcl-EXFAT_CLST_FIRST)*SPC(bs) + bn, flags);
     202        } else {
     203                max_clusters = bn / SPC(bs);
     204                rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
     205                if (rc != EOK)
     206                        return rc;
     207                assert(clusters == max_clusters);
     208
     209                rc = block_get(block, devmap_handle, DATA_FS(bs) +
     210                    (c-EXFAT_CLST_FIRST)*SPC(bs) + (bn % SPC(bs)), flags);
     211
     212                if (clp)
     213                        *clp = c;
     214        }
     215
     216        return rc;
     217}
     218
    60219
    61220/** Get cluster from the FAT.
Note: See TracChangeset for help on using the changeset viewer.