Changes in / [f5af635:bbf88db] in mainline


Ignore:
Location:
uspace/srv/fs/fat
Files:
3 edited

Legend:

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

    rf5af635 rbbf88db  
    215215extern void fat_sync(ipc_callid_t, ipc_call_t *);
    216216
    217 extern int fat_idx_get_new(fat_idx_t **, dev_handle_t);
     217extern fat_idx_t *fat_idx_get_new(dev_handle_t);
    218218extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
    219219extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
  • uspace/srv/fs/fat/fat_idx.c

    rf5af635 rbbf88db  
    339339}
    340340
    341 static int fat_idx_create(fat_idx_t **fidxp, dev_handle_t dev_handle)
     341static fat_idx_t *fat_idx_create(dev_handle_t dev_handle)
    342342{
    343343        fat_idx_t *fidx;
     
    345345        fidx = (fat_idx_t *) malloc(sizeof(fat_idx_t));
    346346        if (!fidx)
    347                 return ENOMEM;
     347                return NULL;
    348348        if (!fat_index_alloc(dev_handle, &fidx->index)) {
    349349                free(fidx);
    350                 return ENOSPC;
     350                return NULL;
    351351        }
    352352               
     
    359359        fidx->nodep = NULL;
    360360
    361         *fidxp = fidx;
    362         return EOK;
    363 }
    364 
    365 int fat_idx_get_new(fat_idx_t **fidxp, dev_handle_t dev_handle)
     361        return fidx;
     362}
     363
     364fat_idx_t *fat_idx_get_new(dev_handle_t dev_handle)
    366365{
    367366        fat_idx_t *fidx;
    368         int rc;
    369367
    370368        fibril_mutex_lock(&used_lock);
    371         rc = fat_idx_create(&fidx, dev_handle);
    372         if (rc != EOK) {
     369        fidx = fat_idx_create(dev_handle);
     370        if (!fidx) {
    373371                fibril_mutex_unlock(&used_lock);
    374                 return rc;
     372                return NULL;
    375373        }
    376374               
     
    384382        fibril_mutex_unlock(&used_lock);
    385383
    386         *fidxp = fidx;
    387         return EOK;
     384        return fidx;
    388385}
    389386
     
    404401                fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
    405402        } else {
    406                 int rc;
    407 
    408                 rc = fat_idx_create(&fidx, dev_handle);
    409                 if (rc != EOK) {
     403                fidx = fat_idx_create(dev_handle);
     404                if (!fidx) {
    410405                        fibril_mutex_unlock(&used_lock);
    411406                        return NULL;
  • uspace/srv/fs/fat/fat_ops.c

    rf5af635 rbbf88db  
    6565static LIST_INITIALIZE(ffn_head);
    6666
     67static 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
     80static 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
     117static fat_node_t *fat_node_get_new(void)
     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                        assert(rc == EOK);
     140                }
     141                idxp_tmp->nodep = NULL;
     142                fibril_mutex_unlock(&nodep->lock);
     143                fibril_mutex_unlock(&idxp_tmp->lock);
     144                fn = FS_NODE(nodep);
     145        } else {
     146skip_cache:
     147                /* Try to allocate a new node structure. */
     148                fibril_mutex_unlock(&ffn_mutex);
     149                fn = (fs_node_t *)malloc(sizeof(fs_node_t));
     150                if (!fn)
     151                        return NULL;
     152                nodep = (fat_node_t *)malloc(sizeof(fat_node_t));
     153                if (!nodep) {
     154                        free(fn);
     155                        return NULL;
     156                }
     157        }
     158        fat_node_initialize(nodep);
     159        fs_node_initialize(fn);
     160        fn->data = nodep;
     161        nodep->bp = fn;
     162       
     163        return nodep;
     164}
     165
     166/** Internal version of fat_node_get().
     167 *
     168 * @param idxp          Locked index structure.
     169 */
     170static fat_node_t *fat_node_get_core(fat_idx_t *idxp)
     171{
     172        block_t *b;
     173        fat_bs_t *bs;
     174        fat_dentry_t *d;
     175        fat_node_t *nodep = NULL;
     176        unsigned bps;
     177        unsigned spc;
     178        unsigned dps;
     179        int rc;
     180
     181        if (idxp->nodep) {
     182                /*
     183                 * We are lucky.
     184                 * The node is already instantiated in memory.
     185                 */
     186                fibril_mutex_lock(&idxp->nodep->lock);
     187                if (!idxp->nodep->refcnt++)
     188                        list_remove(&idxp->nodep->ffn_link);
     189                fibril_mutex_unlock(&idxp->nodep->lock);
     190                return idxp->nodep;
     191        }
     192
     193        /*
     194         * We must instantiate the node from the file system.
     195         */
     196       
     197        assert(idxp->pfc);
     198
     199        nodep = fat_node_get_new();
     200        if (!nodep)
     201                return NULL;
     202
     203        bs = block_bb_get(idxp->dev_handle);
     204        bps = uint16_t_le2host(bs->bps);
     205        spc = bs->spc;
     206        dps = bps / sizeof(fat_dentry_t);
     207
     208        /* Read the block that contains the dentry of interest. */
     209        rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc,
     210            (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE);
     211        assert(rc == EOK);
     212
     213        d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps);
     214        if (d->attr & FAT_ATTR_SUBDIR) {
     215                /*
     216                 * The only directory which does not have this bit set is the
     217                 * root directory itself. The root directory node is handled
     218                 * and initialized elsewhere.
     219                 */
     220                nodep->type = FAT_DIRECTORY;
     221                /*
     222                 * Unfortunately, the 'size' field of the FAT dentry is not
     223                 * defined for the directory entry type. We must determine the
     224                 * size of the directory by walking the FAT.
     225                 */
     226                uint16_t clusters;
     227                rc = fat_clusters_get(&clusters, bs, idxp->dev_handle,
     228                    uint16_t_le2host(d->firstc));
     229                assert(rc == EOK);
     230                nodep->size = bps * spc * clusters;
     231        } else {
     232                nodep->type = FAT_FILE;
     233                nodep->size = uint32_t_le2host(d->size);
     234        }
     235        nodep->firstc = uint16_t_le2host(d->firstc);
     236        nodep->lnkcnt = 1;
     237        nodep->refcnt = 1;
     238
     239        rc = block_put(b);
     240        assert(rc == EOK);
     241
     242        /* Link the idx structure with the node structure. */
     243        nodep->idx = idxp;
     244        idxp->nodep = nodep;
     245
     246        return nodep;
     247}
     248
    67249/*
    68250 * Forward declarations of FAT libfs operations.
     
    85267
    86268/*
    87  * Helper functions.
    88  */
    89 static 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 
    102 static 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 
    139 static 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 {
    175 skip_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  */
    200 static 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 }
    292 
    293 /*
    294269 * FAT libfs operations.
    295270 */
     
    331306                                continue;
    332307                        case FAT_DENTRY_LAST:
    333                                 /* miss */
    334308                                rc = block_put(b);
     309                                /* expect EOK as b was not dirty */
     310                                assert(rc == EOK);     
    335311                                fibril_mutex_unlock(&parentp->idx->lock);
    336312                                *rfn = NULL;
    337                                 return rc;
     313                                return EOK;
    338314                        default:
    339315                        case FAT_DENTRY_VALID:
     
    360336                                         */
    361337                                        rc = block_put(b);
    362                                         return (rc == EOK) ? ENOMEM : rc;
     338                                        /* expect EOK as b was not dirty */
     339                                        assert(rc == EOK);     
     340                                        return ENOMEM;
    363341                                }
    364                                 rc = fat_node_get_core(&nodep, idx);
     342                                nodep = fat_node_get_core(idx);
     343                                fibril_mutex_unlock(&idx->lock);
     344                                rc = block_put(b);
     345                                /* expect EOK as b was not dirty */
    365346                                assert(rc == EOK);
    366                                 fibril_mutex_unlock(&idx->lock);
    367                                 (void) block_put(b);
    368347                                *rfn = FS_NODE(nodep);
    369348                                return EOK;
     
    371350                }
    372351                rc = block_put(b);
    373                 if (rc != EOK) {
    374                         fibril_mutex_unlock(&parentp->idx->lock);
    375                         return rc;
    376                 }
     352                assert(rc == EOK);      /* expect EOK as b was not dirty */
    377353        }
    378354
     
    387363        fat_node_t *nodep;
    388364        fat_idx_t *idxp;
    389         int rc;
    390365
    391366        idxp = fat_idx_get_by_index(dev_handle, index);
     
    395370        }
    396371        /* idxp->lock held */
    397         rc = fat_node_get_core(&nodep, idxp);
     372        nodep = fat_node_get_core(idxp);
    398373        fibril_mutex_unlock(&idxp->lock);
    399         if (rc == EOK)
    400                 *rfn = FS_NODE(nodep);
    401         return rc;
     374        *rfn = FS_NODE(nodep);
     375        return EOK;
    402376}
    403377
     
    455429        }
    456430
    457         rc = fat_node_get_new(&nodep);
    458         if (rc != EOK) {
     431        nodep = fat_node_get_new();
     432        if (!nodep) {
    459433                (void) fat_free_clusters(bs, dev_handle, mcl);
    460                 return rc;
    461         }
    462         rc = fat_idx_get_new(&idxp, dev_handle);
    463         if (rc != EOK) {
     434                return ENOMEM;  /* FIXME: determine the true error code */
     435        }
     436        idxp = fat_idx_get_new(dev_handle);
     437        if (!idxp) {
    464438                (void) fat_free_clusters(bs, dev_handle, mcl); 
    465439                (void) fat_node_put(FS_NODE(nodep));
    466                 return rc;
     440                return ENOMEM;  /* FIXME: determine the true error code */
    467441        }
    468442        /* idxp->lock held */
     
    808782                        case FAT_DENTRY_LAST:
    809783                                rc = block_put(b);
     784                                /* expect EOK as b was not dirty */
     785                                assert(rc == EOK);
    810786                                fibril_mutex_unlock(&nodep->idx->lock);
    811787                                *has_children = false;
    812                                 return rc;
     788                                return EOK;
    813789                        default:
    814790                        case FAT_DENTRY_VALID:
    815791                                rc = block_put(b);
     792                                /* expect EOK as b was not dirty */
     793                                assert(rc == EOK);
    816794                                fibril_mutex_unlock(&nodep->idx->lock);
    817795                                *has_children = true;
    818                                 return rc;
     796                                return EOK;
    819797                        }
    820798                }
    821799                rc = block_put(b);
    822                 if (rc != EOK) {
    823                         fibril_mutex_unlock(&nodep->idx->lock);
    824                         return rc;     
    825                 }
     800                assert(rc == EOK);      /* expect EOK as b was not dirty */
    826801        }
    827802
Note: See TracChangeset for help on using the changeset viewer.