Changeset 869e546 in mainline


Ignore:
Timestamp:
2008-04-20T22:37:13Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
297f1197
Parents:
34f62f8
Message:

Introduce the foundation for unique and stable FAT VFS node indices.

The first two reserved FAT entries are physically present in each FAT, so fix
the code to be aware of this.

Location:
uspace/srv/fs/fat
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat.h

    r34f62f8 r869e546  
    140140} __attribute__ ((packed)) fat_dentry_t;
    141141
     142typedef uint16_t fat_cluster_t;
     143
    142144typedef enum {
    143145        FAT_INVALID,
     
    146148} fat_node_type_t;
    147149
     150struct fat_node;
     151
     152/** FAT index structure.
     153 *
     154 * This structure exists to help us to overcome certain limitations of the FAT
     155 * file system design.  The problem with FAT is that it is hard to find
     156 * an entity which could represent a VFS index.  There are two candidates:
     157 *
     158 * a) number of the node's first cluster
     159 * b) the pair of the parent directory's first cluster and the dentry index
     160 *    within the parent directory
     161 *
     162 * We need VFS indices to be:
     163 * A) unique
     164 * B) stable in time, at least until the next mount
     165 *
     166 * Unfortunately a) does not meet the A) criterion because zero-length files
     167 * will have the first cluster field cleared.  And b) does not meet the B)
     168 * criterion because unlink() and rename() will both free up the original
     169 * dentry, which contains all the essential info about the file.
     170 *
     171 * Therefore, a completely opaque indices are used and the FAT server maintains
     172 * a mapping between them and otherwise nice b) variant.  On rename(), the VFS
     173 * index stays unaltered, while the internal FAT "physical tree address"
     174 * changes.  The unlink case is also handled this way thanks to an in-core node
     175 * pointer embedded in the index structure.
     176 */
     177typedef struct {
     178        dev_handle_t    dev_handle;
     179        fs_index_t      index;
     180        /**
     181         * Parent first cluster.
     182         * Zero is used if this node is not linked, in which case nodep must
     183         * contain a pointer to the in-core node structure.
     184         * One is used when the parent is the root directory.
     185         */
     186        fat_cluster_t   pfc;
     187        /** Parent directory entry index. */
     188        unsigned        pdi;
     189        /** Pointer to in-core node instance. */
     190        struct fat_node *nodep;
     191} fat_idx_t;
     192
    148193/** FAT in-core node. */
    149 typedef struct {
    150         /** Protects an instance of this type. */
    151         futex_t                 lock;
     194typedef struct fat_node {
    152195        fat_node_type_t         type;
    153         /** VFS index is the node's first allocated cluster. */
    154         fs_index_t              index;
    155         /** VFS index of the parent node. */
    156         fs_index_t              pindex;
    157         dev_handle_t            dev_handle;
     196        fat_idx_t               *idx;
     197        /**
     198         *  Node's first cluster.
     199         *  Zero is used for zero-length nodes.
     200         *  One is used to mark root directory.
     201         */
     202        fat_cluster_t           firstc;
    158203        /** FAT in-core node hash table link. */
    159204        link_t                  fin_link;
  • uspace/srv/fs/fat/fat_ops.c

    r34f62f8 r869e546  
    5454#define FIN_KEY_INDEX           1
    5555
    56 /** Futex protecting both fin_hash and ffn_head. */
    57 futex_t fin_futex = FUTEX_INITIALIZER;
    58 
    5956/** Hash table of FAT in-core nodes. */
    6057hash_table_t fin_hash;
     
    116113}
    117114
     115static fat_idx_t *fat_idx_map(fat_cluster_t pfc, unsigned pdi)
     116{
     117        return NULL;    /* TODO */
     118}
    118119
    119120#define FAT_BS(b)               ((fat_bs_t *)((b)->data))
    120121
     122#define FAT_CLST_RES0   0x0000
     123#define FAT_CLST_RES1   0x0001  /* internally used to mark root directory */
    121124#define FAT_CLST_FIRST  0x0002
    122125#define FAT_CLST_BAD    0xfff7
     
    124127#define FAT_CLST_LAST8  0xffff
    125128
    126 /** Convert cluster number to an index within a FAT.
    127  *
    128  * Format Identifier and cluster numbering is considered.
    129  */
    130 #define C2FAT_IDX(c)    (1 + (c) - FAT_CLST_FIRST)
    131 
    132 static block_t *fat_block_get(dev_handle_t dev_handle, fs_index_t index,
    133     off_t offset)
     129static block_t *fat_block_get(fat_node_t *nodep, off_t offset)
    134130{
    135131        block_t *bb;
     
    144140        unsigned ssa;           /* size of the system area */
    145141        unsigned clusters;
    146         unsigned clst = index;
     142        fat_cluster_t clst = nodep->firstc;
    147143        unsigned i;
    148144
    149         bb = block_get(dev_handle, BS_BLOCK);
     145        bb = block_get(nodep->idx->dev_handle, BS_BLOCK);
    150146        bps = uint16_t_le2host(FAT_BS(bb)->bps);
    151147        spc = FAT_BS(bb)->spc;
     
    160156        ssa = rscnt + fatcnt * sf + rds;
    161157
    162         if (!index) {
     158        if (nodep->idx->index == FAT_CLST_RES1) {
    163159                /* root directory special case */
    164160                assert(offset < rds);
    165                 b = block_get(dev_handle, rscnt + fatcnt * sf + offset);
     161                b = block_get(nodep->idx->dev_handle,
     162                    rscnt + fatcnt * sf + offset);
    166163                return b;
    167164        }
     
    173170
    174171                assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD);
    175                 fsec = (C2FAT_IDX(clst) * sizeof(uint16_t)) / bps;
    176                 fidx = C2FAT_IDX(clst) % (bps / sizeof(uint16_t));
     172                fsec = (clst * sizeof(fat_cluster_t)) / bps;
     173                fidx = clst % (bps / sizeof(fat_cluster_t));
    177174                /* read FAT1 */
    178                 b = block_get(dev_handle, rscnt + fsec);
    179                 clst = uint16_t_le2host(((uint16_t *)b->data)[fidx]);
     175                b = block_get(nodep->idx->dev_handle, rscnt + fsec);
     176                clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    180177                assert(clst != FAT_CLST_BAD);
    181178                assert(clst < FAT_CLST_LAST1);
     
    183180        }
    184181
    185         b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +
    186             offset % spc);
     182        b = block_get(nodep->idx->dev_handle, ssa +
     183            (clst - FAT_CLST_FIRST) * spc + offset % spc);
    187184
    188185        return b;
     
    191188static void fat_node_initialize(fat_node_t *node)
    192189{
    193         futex_initialize(&node->lock, 1);
     190        node->idx = NULL;
    194191        node->type = 0;
    195         node->index = 0;
    196         node->pindex = 0;
    197         node->dev_handle = 0;
    198192        link_initialize(&node->fin_link);
    199193        link_initialize(&node->ffn_link);
     
    295289        block_t *b;
    296290
    297         bps = fat_bps_get(parentp->dev_handle);
     291        bps = fat_bps_get(parentp->idx->dev_handle);
    298292        dps = bps / sizeof(fat_dentry_t);
    299293        blocks = parentp->size / bps + (parentp->size % bps != 0);
     
    301295                unsigned dentries;
    302296               
    303                 b = fat_block_get(parentp->dev_handle, parentp->index, i);
     297                b = fat_block_get(parentp, i);
    304298                dentries = (i == blocks - 1) ?
    305299                    parentp->size % sizeof(fat_dentry_t) :
     
    320314                        if (strcmp(name, component) == 0) {
    321315                                /* hit */
    322                                 void *node = fat_node_get(parentp->dev_handle,
    323                                     (fs_index_t)uint16_t_le2host(d->firstc));
     316                                fat_idx_t *idx = fat_idx_map(parentp->firstc,
     317                                    i * dps + j);
     318                                void *node = fat_node_get(idx->dev_handle,
     319                                    idx->index);
    324320                                block_put(b);
    325321                                return node;
     
    337333        if (!fnodep)
    338334                return 0;
    339         return fnodep->index;
     335        return fnodep->idx->index;
    340336}
    341337
     
    362358                return false;
    363359
    364         bps = fat_bps_get(nodep->dev_handle);
     360        bps = fat_bps_get(nodep->idx->dev_handle);
    365361        dps = bps / sizeof(fat_dentry_t);
    366362
     
    371367                fat_dentry_t *d;
    372368       
    373                 b = fat_block_get(nodep->dev_handle, nodep->index, i);
     369                b = fat_block_get(nodep, i);
    374370                dentries = (i == blocks - 1) ?
    375371                    nodep->size % sizeof(fat_dentry_t) :
     
    399395static void *fat_root_get(dev_handle_t dev_handle)
    400396{
    401         return fat_node_get(dev_handle, 0);     
     397        return fat_node_get(dev_handle, FAT_CLST_RES1);
    402398}
    403399
Note: See TracChangeset for help on using the changeset viewer.