Changeset 4c3c4a5 in mainline for uspace/srv/fs/exfat/exfat_ops.c


Ignore:
Timestamp:
2011-06-29T04:04:19Z (14 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2fb88ea
Parents:
fcc3cd8
Message:
  1. Integrate fat_udx.c as exfat_idx.c
  2. Add skeleton for libfs_ops
  3. Improve mount/unmount
File:
1 edited

Legend:

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

    rfcc3cd8 r4c3c4a5  
    3838
    3939#include "exfat.h"
     40#include "exfat_fat.h"
    4041#include "../../vfs/vfs.h"
    4142#include <libfs.h>
     
    5556#include <align.h>
    5657#include <malloc.h>
     58#include <stdio.h>
     59
     60#define EXFAT_NODE(node)        ((node) ? (exfat_node_t *) (node)->data : NULL)
     61#define FS_NODE(node)   ((node) ? (node)->bp : NULL)
     62
     63
     64/** Mutex protecting the list of cached free FAT nodes. */
     65static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
     66
     67/** List of cached free FAT nodes. */
     68static LIST_INITIALIZE(ffn_head);
     69
     70/*
     71 * Forward declarations of FAT libfs operations.
     72 */
     73static int exfat_root_get(fs_node_t **, devmap_handle_t);
     74static int exfat_match(fs_node_t **, fs_node_t *, const char *);
     75static int exfat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
     76static int exfat_node_open(fs_node_t *);
     77static int exfat_node_put(fs_node_t *);
     78static int exfat_create_node(fs_node_t **, devmap_handle_t, int);
     79static int exfat_destroy_node(fs_node_t *);
     80static int exfat_link(fs_node_t *, fs_node_t *, const char *);
     81static int exfat_unlink(fs_node_t *, fs_node_t *, const char *);
     82static int exfat_has_children(bool *, fs_node_t *);
     83static fs_index_t exfat_index_get(fs_node_t *);
     84static aoff64_t exfat_size_get(fs_node_t *);
     85static unsigned exfat_lnkcnt_get(fs_node_t *);
     86static char exfat_plb_get_char(unsigned);
     87static bool exfat_is_directory(fs_node_t *);
     88static bool exfat_is_file(fs_node_t *node);
     89static devmap_handle_t exfat_device_get(fs_node_t *node);
     90
     91/*
     92 * Helper functions.
     93 */
     94static void exfat_node_initialize(exfat_node_t *node)
     95{
     96        fibril_mutex_initialize(&node->lock);
     97        node->bp = NULL;
     98        node->idx = NULL;
     99        node->type = 0;
     100        link_initialize(&node->ffn_link);
     101        node->size = 0;
     102        node->lnkcnt = 0;
     103        node->refcnt = 0;
     104        node->dirty = false;
     105        node->lastc_cached_valid = false;
     106        node->lastc_cached_value = 0;
     107        node->currc_cached_valid = false;
     108        node->currc_cached_bn = 0;
     109        node->currc_cached_value = 0;
     110}
     111
     112static int exfat_node_sync(exfat_node_t *node)
     113{
     114        return EOK;
     115}
     116
     117static int exfat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
     118{
     119        link_t *lnk;
     120        exfat_node_t *nodep;
     121        int rc;
     122
     123        /*
     124         * We are called from fat_unmounted() and assume that there are already
     125         * no nodes belonging to this instance with non-zero refcount. Therefore
     126         * it is sufficient to clean up only the FAT free node list.
     127         */
     128
     129restart:
     130        fibril_mutex_lock(&ffn_mutex);
     131        for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     132                nodep = list_get_instance(lnk, exfat_node_t, ffn_link);
     133                if (!fibril_mutex_trylock(&nodep->lock)) {
     134                        fibril_mutex_unlock(&ffn_mutex);
     135                        goto restart;
     136                }
     137                if (!fibril_mutex_trylock(&nodep->idx->lock)) {
     138                        fibril_mutex_unlock(&nodep->lock);
     139                        fibril_mutex_unlock(&ffn_mutex);
     140                        goto restart;
     141                }
     142                if (nodep->idx->devmap_handle != devmap_handle) {
     143                        fibril_mutex_unlock(&nodep->idx->lock);
     144                        fibril_mutex_unlock(&nodep->lock);
     145                        continue;
     146                }
     147
     148                list_remove(&nodep->ffn_link);
     149                fibril_mutex_unlock(&ffn_mutex);
     150
     151                /*
     152                 * We can unlock the node and its index structure because we are
     153                 * the last player on this playground and VFS is preventing new
     154                 * players from entering.
     155                 */
     156                fibril_mutex_unlock(&nodep->idx->lock);
     157                fibril_mutex_unlock(&nodep->lock);
     158
     159                if (nodep->dirty) {
     160                        rc = exfat_node_sync(nodep);
     161                        if (rc != EOK)
     162                                return rc;
     163                }
     164                nodep->idx->nodep = NULL;
     165                free(nodep->bp);
     166                free(nodep);
     167
     168                /* Need to restart because we changed the ffn_head list. */
     169                goto restart;
     170        }
     171        fibril_mutex_unlock(&ffn_mutex);
     172
     173        return EOK;
     174}
     175
     176
     177/*
     178 * FAT libfs operations.
     179 */
     180
     181int exfat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
     182{
     183        return exfat_node_get(rfn, devmap_handle, 0);
     184}
     185
     186int exfat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     187{
     188        *rfn = NULL;
     189        return EOK;
     190}
     191
     192/** Instantiate a exFAT in-core node. */
     193int exfat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
     194{
     195        *rfn = NULL;
     196        return EOK;
     197}
     198
     199int exfat_node_open(fs_node_t *fn)
     200{
     201        /*
     202         * Opening a file is stateless, nothing
     203         * to be done here.
     204         */
     205        return EOK;
     206}
     207
     208int exfat_node_put(fs_node_t *fn)
     209{
     210        return EOK;
     211}
     212
     213int exfat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
     214{
     215        *rfn = NULL;
     216        return EOK;
     217}
     218
     219int exfat_destroy_node(fs_node_t *fn)
     220{
     221        return EOK;
     222}
     223
     224int exfat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
     225{
     226        return EOK;
     227}
     228
     229int exfat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     230{
     231        return EOK;
     232}
     233
     234int exfat_has_children(bool *has_children, fs_node_t *fn)
     235{
     236        *has_children = false;
     237        return EOK;
     238}
     239
     240
     241fs_index_t exfat_index_get(fs_node_t *fn)
     242{
     243        return EXFAT_NODE(fn)->idx->index;
     244}
     245
     246aoff64_t exfat_size_get(fs_node_t *fn)
     247{
     248        return EXFAT_NODE(fn)->size;
     249}
     250
     251unsigned exfat_lnkcnt_get(fs_node_t *fn)
     252{
     253        return EXFAT_NODE(fn)->lnkcnt;
     254}
     255
     256char exfat_plb_get_char(unsigned pos)
     257{
     258        return exfat_reg.plb_ro[pos % PLB_SIZE];
     259}
     260
     261bool exfat_is_directory(fs_node_t *fn)
     262{
     263        return EXFAT_NODE(fn)->type == EXFAT_DIRECTORY;
     264}
     265
     266bool exfat_is_file(fs_node_t *fn)
     267{
     268        return EXFAT_NODE(fn)->type == EXFAT_FILE;
     269}
     270
     271devmap_handle_t exfat_device_get(fs_node_t *node)
     272{
     273        return 0;
     274}
     275
    57276
    58277/** libfs operations */
    59 
    60 libfs_ops_t exfat_libfs_ops;
    61 /*
    62278libfs_ops_t exfat_libfs_ops = {
    63279        .root_get = exfat_root_get,
     
    79295        .device_get = exfat_device_get
    80296};
    81 */
     297
    82298
    83299/*
     
    136352        }
    137353
    138         async_answer_0(rid, EOK);
    139 /*      async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt); */
     354        /* Do some simple sanity checks on the file system. */
     355        rc = exfat_sanity_check(bs, devmap_handle);
     356        if (rc != EOK) {
     357                (void) block_cache_fini(devmap_handle);
     358                block_fini(devmap_handle);
     359                async_answer_0(rid, rc);
     360                return;
     361        }
     362
     363        rc = exfat_idx_init_by_devmap_handle(devmap_handle);
     364        if (rc != EOK) {
     365                (void) block_cache_fini(devmap_handle);
     366                block_fini(devmap_handle);
     367                async_answer_0(rid, rc);
     368                return;
     369        }
     370
     371        /* Initialize the root node. */
     372        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
     373        if (!rfn) {
     374                (void) block_cache_fini(devmap_handle);
     375                block_fini(devmap_handle);
     376                exfat_idx_fini_by_devmap_handle(devmap_handle);
     377                async_answer_0(rid, ENOMEM);
     378                return;
     379        }
     380
     381        fs_node_initialize(rfn);
     382        exfat_node_t *rootp = (exfat_node_t *)malloc(sizeof(exfat_node_t));
     383        if (!rootp) {
     384                free(rfn);
     385                (void) block_cache_fini(devmap_handle);
     386                block_fini(devmap_handle);
     387                exfat_idx_fini_by_devmap_handle(devmap_handle);
     388                async_answer_0(rid, ENOMEM);
     389                return;
     390        }
     391
     392        exfat_node_initialize(rootp);
     393
     394        /* exfat_idx_t *ridxp = exfat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0); */
     395        exfat_idx_t *ridxp = exfat_idx_get_by_pos(devmap_handle, 0, 0);
     396        if (!ridxp) {
     397                free(rfn);
     398                free(rootp);
     399                (void) block_cache_fini(devmap_handle);
     400                block_fini(devmap_handle);
     401                exfat_idx_fini_by_devmap_handle(devmap_handle);
     402                async_answer_0(rid, ENOMEM);
     403                return;
     404        }
     405        assert(ridxp->index == 0);
     406        /* ridxp->lock held */
     407
     408        rootp->type = EXFAT_DIRECTORY;
     409        rootp->firstc = ROOT_ST(bs);
     410        rootp->refcnt = 1;
     411        rootp->lnkcnt = 0;      /* FS root is not linked */
     412        rootp->idx = ridxp;
     413        ridxp->nodep = rootp;
     414        rootp->bp = rfn;
     415        rfn->data = rootp;
     416
     417        fibril_mutex_unlock(&ridxp->lock);
     418
     419        /* async_answer_0(rid, EOK); */
     420        async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
    140421}
    141422
     
    148429{
    149430        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     431        fs_node_t *fn;
     432        exfat_node_t *nodep;
     433        int rc;
     434
     435        rc = exfat_root_get(&fn, devmap_handle);
     436        if (rc != EOK) {
     437                async_answer_0(rid, rc);
     438                return;
     439        }
     440        nodep = EXFAT_NODE(fn);
     441
     442        /*
     443         * We expect exactly two references on the root node. One for the
     444         * fat_root_get() above and one created in fat_mounted().
     445         */
     446        if (nodep->refcnt != 2) {
     447                (void) exfat_node_put(fn);
     448                async_answer_0(rid, EBUSY);
     449                return;
     450        }
     451
     452        /*
     453         * Put the root node and force it to the FAT free node list.
     454         */
     455        (void) exfat_node_put(fn);
     456        (void) exfat_node_put(fn);
    150457
    151458        /*
     
    154461         * stop using libblock for this instance.
    155462         */
     463        (void) exfat_node_fini_by_devmap_handle(devmap_handle);
     464        exfat_idx_fini_by_devmap_handle(devmap_handle);
    156465        (void) block_cache_fini(devmap_handle);
    157466        block_fini(devmap_handle);
Note: See TracChangeset for help on using the changeset viewer.