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

Changeset 0fc1e5d in mainline for uspace/srv/fs/fat/fat_ops.c


Ignore:
Timestamp:
2009-10-01T11:09:38Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
9a15176
Parents:
17bf658
Message:

Make fat_node_get_core() return an error code.

File:
1 edited

Legend:

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

    r17bf658 r0fc1e5d  
    6565static LIST_INITIALIZE(ffn_head);
    6666
    67 static void fat_node_initialize(fat_node_t *node)
    68 {
    69         fibril_mutex_initialize(&node->lock);
    70         node->bp = NULL;
    71         node->idx = NULL;
    72         node->type = 0;
    73         link_initialize(&node->ffn_link);
    74         node->size = 0;
    75         node->lnkcnt = 0;
    76         node->refcnt = 0;
    77         node->dirty = false;
    78 }
    79 
    80 static int fat_node_sync(fat_node_t *node)
    81 {
    82         block_t *b;
    83         fat_bs_t *bs;
    84         fat_dentry_t *d;
    85         uint16_t bps;
    86         unsigned dps;
    87         int rc;
    88        
    89         assert(node->dirty);
    90 
    91         bs = block_bb_get(node->idx->dev_handle);
    92         bps = uint16_t_le2host(bs->bps);
    93         dps = bps / sizeof(fat_dentry_t);
    94        
    95         /* Read the block that contains the dentry of interest. */
    96         rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
    97             (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
    98         if (rc != EOK)
    99                 return rc;
    100 
    101         d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
    102 
    103         d->firstc = host2uint16_t_le(node->firstc);
    104         if (node->type == FAT_FILE) {
    105                 d->size = host2uint32_t_le(node->size);
    106         } else if (node->type == FAT_DIRECTORY) {
    107                 d->attr = FAT_ATTR_SUBDIR;
    108         }
    109        
    110         /* TODO: update other fields? (e.g time fields) */
    111        
    112         b->dirty = true;                /* need to sync block */
    113         rc = block_put(b);
    114         return rc;
    115 }
    116 
    117 static int fat_node_get_new(fat_node_t **nodepp)
    118 {
    119         fs_node_t *fn;
    120         fat_node_t *nodep;
    121         int rc;
    122 
    123         fibril_mutex_lock(&ffn_mutex);
    124         if (!list_empty(&ffn_head)) {
    125                 /* Try to use a cached free node structure. */
    126                 fat_idx_t *idxp_tmp;
    127                 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
    128                 if (!fibril_mutex_trylock(&nodep->lock))
    129                         goto skip_cache;
    130                 idxp_tmp = nodep->idx;
    131                 if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
    132                         fibril_mutex_unlock(&nodep->lock);
    133                         goto skip_cache;
    134                 }
    135                 list_remove(&nodep->ffn_link);
    136                 fibril_mutex_unlock(&ffn_mutex);
    137                 if (nodep->dirty) {
    138                         rc = fat_node_sync(nodep);
    139                         if (rc != EOK) {
    140                                 idxp_tmp->nodep = NULL;
    141                                 fibril_mutex_unlock(&nodep->lock);
    142                                 fibril_mutex_unlock(&idxp_tmp->lock);
    143                                 free(nodep->bp);
    144                                 free(nodep);
    145                                 return rc;
    146                         }
    147                 }
    148                 idxp_tmp->nodep = NULL;
    149                 fibril_mutex_unlock(&nodep->lock);
    150                 fibril_mutex_unlock(&idxp_tmp->lock);
    151                 fn = FS_NODE(nodep);
    152         } else {
    153 skip_cache:
    154                 /* Try to allocate a new node structure. */
    155                 fibril_mutex_unlock(&ffn_mutex);
    156                 fn = (fs_node_t *)malloc(sizeof(fs_node_t));
    157                 if (!fn)
    158                         return ENOMEM;
    159                 nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
    160                 if (!nodep) {
    161                         free(fn);
    162                         return ENOMEM;
    163                 }
    164         }
    165         fat_node_initialize(nodep);
    166         fs_node_initialize(fn);
    167         fn->data = nodep;
    168         nodep->bp = fn;
    169        
    170         *nodepp = nodep;
    171         return EOK;
    172 }
    173 
    174 /** Internal version of fat_node_get().
    175  *
    176  * @param idxp          Locked index structure.
    177  */
    178 static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
    179 {
    180         block_t *b;
    181         fat_bs_t *bs;
    182         fat_dentry_t *d;
    183         fat_node_t *nodep = NULL;
    184         unsigned bps;
    185         unsigned spc;
    186         unsigned dps;
    187         int rc;
    188 
    189         if (idxp->nodep) {
    190                 /*
    191                  * We are lucky.
    192                  * The node is already instantiated in memory.
    193                  */
    194                 fibril_mutex_lock(&idxp->nodep->lock);
    195                 if (!idxp->nodep->refcnt++) {
    196                         fibril_mutex_lock(&ffn_mutex);
    197                         list_remove(&idxp->nodep->ffn_link);
    198                         fibril_mutex_unlock(&ffn_mutex);
    199                 }
    200                 fibril_mutex_unlock(&idxp->nodep->lock);
    201                 return idxp->nodep;
    202         }
    203 
    204         /*
    205          * We must instantiate the node from the file system.
    206          */
    207        
    208         assert(idxp->pfc);
    209 
    210         rc = fat_node_get_new(&nodep);
    211         if (rc != EOK)
    212                 return NULL;
    213 
    214         bs = block_bb_get(idxp->dev_handle);
    215         bps = uint16_t_le2host(bs->bps);
    216         spc = bs->spc;
    217         dps = bps / sizeof(fat_dentry_t);
    218 
    219         /* Read the block that contains the dentry of interest. */
    220         rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
    221             (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
    222         assert(rc == EOK);
    223 
    224         d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
    225         if (d->attr & FAT_ATTR_SUBDIR) {
    226                 /*
    227                  * The only directory which does not have this bit set is the
    228                  * root directory itself. The root directory node is handled
    229                  * and initialized elsewhere.
    230                  */
    231                 nodep->type = FAT_DIRECTORY;
    232                 /*
    233                  * Unfortunately, the 'size' field of the FAT dentry is not
    234                  * defined for the directory entry type. We must determine the
    235                  * size of the directory by walking the FAT.
    236                  */
    237                 uint16_t clusters;
    238                 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
    239                     uint16_t_le2host(d->firstc));
    240                 assert(rc == EOK);
    241                 nodep->size = bps * spc * clusters;
    242         } else {
    243                 nodep->type = FAT_FILE;
    244                 nodep->size = uint32_t_le2host(d->size);
    245         }
    246         nodep->firstc = uint16_t_le2host(d->firstc);
    247         nodep->lnkcnt = 1;
    248         nodep->refcnt = 1;
    249 
    250         rc = block_put(b);
    251         assert(rc == EOK);
    252 
    253         /* Link the idx structure with the node structure. */
    254         nodep->idx = idxp;
    255         idxp->nodep = nodep;
    256 
    257         return nodep;
    258 }
    259 
    26067/*
    26168 * Forward declarations of FAT libfs operations.
     
    27683static bool fat_is_directory(fs_node_t *);
    27784static bool fat_is_file(fs_node_t *node);
     85
     86/*
     87 * Helper functions.
     88 */
     89static void fat_node_initialize(fat_node_t *node)
     90{
     91        fibril_mutex_initialize(&node->lock);
     92        node->bp = NULL;
     93        node->idx = NULL;
     94        node->type = 0;
     95        link_initialize(&node->ffn_link);
     96        node->size = 0;
     97        node->lnkcnt = 0;
     98        node->refcnt = 0;
     99        node->dirty = false;
     100}
     101
     102static int fat_node_sync(fat_node_t *node)
     103{
     104        block_t *b;
     105        fat_bs_t *bs;
     106        fat_dentry_t *d;
     107        uint16_t bps;
     108        unsigned dps;
     109        int rc;
     110       
     111        assert(node->dirty);
     112
     113        bs = block_bb_get(node->idx->dev_handle);
     114        bps = uint16_t_le2host(bs->bps);
     115        dps = bps / sizeof(fat_dentry_t);
     116       
     117        /* Read the block that contains the dentry of interest. */
     118        rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc,
     119            (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
     120        if (rc != EOK)
     121                return rc;
     122
     123        d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps);
     124
     125        d->firstc = host2uint16_t_le(node->firstc);
     126        if (node->type == FAT_FILE) {
     127                d->size = host2uint32_t_le(node->size);
     128        } else if (node->type == FAT_DIRECTORY) {
     129                d->attr = FAT_ATTR_SUBDIR;
     130        }
     131       
     132        /* TODO: update other fields? (e.g time fields) */
     133       
     134        b->dirty = true;                /* need to sync block */
     135        rc = block_put(b);
     136        return rc;
     137}
     138
     139static int fat_node_get_new(fat_node_t **nodepp)
     140{
     141        fs_node_t *fn;
     142        fat_node_t *nodep;
     143        int rc;
     144
     145        fibril_mutex_lock(&ffn_mutex);
     146        if (!list_empty(&ffn_head)) {
     147                /* Try to use a cached free node structure. */
     148                fat_idx_t *idxp_tmp;
     149                nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
     150                if (!fibril_mutex_trylock(&nodep->lock))
     151                        goto skip_cache;
     152                idxp_tmp = nodep->idx;
     153                if (!fibril_mutex_trylock(&idxp_tmp->lock)) {
     154                        fibril_mutex_unlock(&nodep->lock);
     155                        goto skip_cache;
     156                }
     157                list_remove(&nodep->ffn_link);
     158                fibril_mutex_unlock(&ffn_mutex);
     159                if (nodep->dirty) {
     160                        rc = fat_node_sync(nodep);
     161                        if (rc != EOK) {
     162                                idxp_tmp->nodep = NULL;
     163                                fibril_mutex_unlock(&nodep->lock);
     164                                fibril_mutex_unlock(&idxp_tmp->lock);
     165                                free(nodep->bp);
     166                                free(nodep);
     167                                return rc;
     168                        }
     169                }
     170                idxp_tmp->nodep = NULL;
     171                fibril_mutex_unlock(&nodep->lock);
     172                fibril_mutex_unlock(&idxp_tmp->lock);
     173                fn = FS_NODE(nodep);
     174        } else {
     175skip_cache:
     176                /* Try to allocate a new node structure. */
     177                fibril_mutex_unlock(&ffn_mutex);
     178                fn = (fs_node_t *)malloc(sizeof(fs_node_t));
     179                if (!fn)
     180                        return ENOMEM;
     181                nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
     182                if (!nodep) {
     183                        free(fn);
     184                        return ENOMEM;
     185                }
     186        }
     187        fat_node_initialize(nodep);
     188        fs_node_initialize(fn);
     189        fn->data = nodep;
     190        nodep->bp = fn;
     191       
     192        *nodepp = nodep;
     193        return EOK;
     194}
     195
     196/** Internal version of fat_node_get().
     197 *
     198 * @param idxp          Locked index structure.
     199 */
     200static int fat_node_get_core(fat_node_t **nodepp, fat_idx_t *idxp)
     201{
     202        block_t *b;
     203        fat_bs_t *bs;
     204        fat_dentry_t *d;
     205        fat_node_t *nodep = NULL;
     206        unsigned bps;
     207        unsigned spc;
     208        unsigned dps;
     209        int rc;
     210
     211        if (idxp->nodep) {
     212                /*
     213                 * We are lucky.
     214                 * The node is already instantiated in memory.
     215                 */
     216                fibril_mutex_lock(&idxp->nodep->lock);
     217                if (!idxp->nodep->refcnt++) {
     218                        fibril_mutex_lock(&ffn_mutex);
     219                        list_remove(&idxp->nodep->ffn_link);
     220                        fibril_mutex_unlock(&ffn_mutex);
     221                }
     222                fibril_mutex_unlock(&idxp->nodep->lock);
     223                *nodepp = idxp->nodep;
     224                return EOK;
     225        }
     226
     227        /*
     228         * We must instantiate the node from the file system.
     229         */
     230       
     231        assert(idxp->pfc);
     232
     233        rc = fat_node_get_new(&nodep);
     234        if (rc != EOK)
     235                return rc;
     236
     237        bs = block_bb_get(idxp->dev_handle);
     238        bps = uint16_t_le2host(bs->bps);
     239        spc = bs->spc;
     240        dps = bps / sizeof(fat_dentry_t);
     241
     242        /* Read the block that contains the dentry of interest. */
     243        rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
     244            (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
     245        if (rc != EOK) {
     246                (void) fat_node_put(FS_NODE(nodep));
     247                return rc;
     248        }
     249
     250        d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
     251        if (d->attr & FAT_ATTR_SUBDIR) {
     252                /*
     253                 * The only directory which does not have this bit set is the
     254                 * root directory itself. The root directory node is handled
     255                 * and initialized elsewhere.
     256                 */
     257                nodep->type = FAT_DIRECTORY;
     258                /*
     259                 * Unfortunately, the 'size' field of the FAT dentry is not
     260                 * defined for the directory entry type. We must determine the
     261                 * size of the directory by walking the FAT.
     262                 */
     263                uint16_t clusters;
     264                rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
     265                    uint16_t_le2host(d->firstc));
     266                if (rc != EOK) {
     267                        (void) fat_node_put(FS_NODE(nodep));
     268                        return rc;
     269                }
     270                nodep->size = bps * spc * clusters;
     271        } else {
     272                nodep->type = FAT_FILE;
     273                nodep->size = uint32_t_le2host(d->size);
     274        }
     275        nodep->firstc = uint16_t_le2host(d->firstc);
     276        nodep->lnkcnt = 1;
     277        nodep->refcnt = 1;
     278
     279        rc = block_put(b);
     280        if (rc != EOK) {
     281                (void) fat_node_put(FS_NODE(nodep));
     282                return rc;
     283        }
     284
     285        /* Link the idx structure with the node structure. */
     286        nodep->idx = idxp;
     287        idxp->nodep = nodep;
     288
     289        *nodepp = nodep;
     290        return EOK;
     291}
    278292
    279293/*
     
    351365                                        return ENOMEM;
    352366                                }
    353                                 nodep = fat_node_get_core(idx);
     367                                rc = fat_node_get_core(&nodep, idx);
     368                                assert(rc == EOK);
    354369                                fibril_mutex_unlock(&idx->lock);
    355370                                rc = block_put(b);
     
    374389        fat_node_t *nodep;
    375390        fat_idx_t *idxp;
     391        int rc;
    376392
    377393        idxp = fat_idx_get_by_index(dev_handle, index);
     
    381397        }
    382398        /* idxp->lock held */
    383         nodep = fat_node_get_core(idxp);
     399        rc = fat_node_get_core(&nodep, idxp);
    384400        fibril_mutex_unlock(&idxp->lock);
    385         *rfn = FS_NODE(nodep);
    386         return EOK;
     401        if (rc == EOK)
     402                *rfn = FS_NODE(nodep);
     403        return rc;
    387404}
    388405
Note: See TracChangeset for help on using the changeset viewer.