Changeset 4c3c4a5 in mainline


Ignore:
Timestamp:
2011-06-29T04:04:19Z (13 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
Location:
uspace/srv/fs/exfat
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/exfat/Makefile

    rfcc3cd8 r4c3c4a5  
    3535SOURCES = \
    3636        exfat.c \
     37        exfat_fat.c \
    3738        exfat_ops.c \
     39        exfat_idx.c
    3840
    3941include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/fs/exfat/exfat.c

    rfcc3cd8 r4c3c4a5  
    158158
    159159        printf(NAME ": HelenOS exFAT file system server\n");
    160 /*
     160
    161161        rc = exfat_idx_init();
    162162        if (rc != EOK)
    163163                goto err;
    164 */
     164
    165165        vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
    166166        if (vfs_phone < EOK) {
     
    171171        rc = fs_register(vfs_phone, &exfat_reg, &exfat_vfs_info, exfat_connection);
    172172        if (rc != EOK) {
    173                 /* exfat_idx_fini(); */
     173                exfat_idx_fini();
    174174                goto err;
    175175        }
  • uspace/srv/fs/exfat/exfat.h

    rfcc3cd8 r4c3c4a5  
    3535#define EXFAT_FAT_H_
    3636
     37#include "exfat_fat.h"
    3738#include <fibril_synch.h>
    3839#include <libfs.h>
     
    5859#define DATA_CNT(bs)    uint32_t_le2host(bs->data_clusters)
    5960#define ROOT_ST(bs)             uint32_t_le2host(bs->rootdir_cluster)
    60 #define VOL_FLAGS               uint16_t_le2host(bs->volume_flags)
     61#define VOL_FLAGS(bs)   uint16_t_le2host(bs->volume_flags)
    6162
    6263
     
    8889} __attribute__((__packed__)) exfat_bs_t;
    8990
     91typedef enum {
     92        EXFAT_DIRECTORY,
     93        EXFAT_FILE
     94} exfat_node_type_t;
     95
     96struct exfat_node;
     97
     98typedef struct {
     99        /** Used indices (position) hash table link. */
     100        link_t          uph_link;
     101        /** Used indices (index) hash table link. */
     102        link_t          uih_link;
     103
     104        fibril_mutex_t  lock;
     105        devmap_handle_t devmap_handle;
     106        fs_index_t      index;
     107        /**
     108         * Parent node's first cluster.
     109         * Zero is used if this node is not linked, in which case nodep must
     110         * contain a pointer to the in-core node structure.
     111         * One is used when the parent is the root directory.
     112         */
     113        exfat_cluster_t pfc;
     114        /** Directory entry index within the parent node. */
     115        unsigned        pdi;
     116        /** Pointer to in-core node instance. */
     117        struct exfat_node       *nodep;
     118} exfat_idx_t;
     119
     120/** exFAT in-core node. */
     121typedef struct exfat_node {
     122        /** Back pointer to the FS node. */
     123        fs_node_t               *bp;
     124       
     125        fibril_mutex_t          lock;
     126        exfat_node_type_t       type;
     127        exfat_idx_t                     *idx;
     128        /**
     129         *  Node's first cluster.
     130         *  Zero is used for zero-length nodes.
     131         *  One is used to mark root directory.
     132         */
     133        exfat_cluster_t         firstc;
     134        /** exFAT in-core node free list link. */
     135        link_t                  ffn_link;
     136        aoff64_t                size;
     137        unsigned                lnkcnt;
     138        unsigned                refcnt;
     139        bool                    dirty;
     140
     141        /*
     142         * Cache of the node's last and "current" cluster to avoid some
     143         * unnecessary FAT walks.
     144         */
     145        /* Node's last cluster in FAT. */
     146        bool            lastc_cached_valid;
     147        exfat_cluster_t lastc_cached_value;
     148        /* Node's "current" cluster, i.e. where the last I/O took place. */
     149        bool            currc_cached_valid;
     150        aoff64_t        currc_cached_bn;
     151        exfat_cluster_t currc_cached_value;
     152} exfat_node_t;
     153
    90154
    91155extern fs_reg_t exfat_reg;
     
    95159extern void exfat_unmounted(ipc_callid_t, ipc_call_t *);
    96160extern void exfat_unmount(ipc_callid_t, ipc_call_t *);
     161extern void exfat_lookup(ipc_callid_t, ipc_call_t *);
     162extern void exfat_read(ipc_callid_t, ipc_call_t *);
     163extern void exfat_write(ipc_callid_t, ipc_call_t *);
     164extern void exfat_truncate(ipc_callid_t, ipc_call_t *);
     165extern void exfat_stat(ipc_callid_t, ipc_call_t *);
     166extern void exfat_close(ipc_callid_t, ipc_call_t *);
     167extern void exfat_destroy(ipc_callid_t, ipc_call_t *);
     168extern void exfat_open_node(ipc_callid_t, ipc_call_t *);
     169extern void exfat_stat(ipc_callid_t, ipc_call_t *);
     170extern void exfat_sync(ipc_callid_t, ipc_call_t *);
     171
     172extern int exfat_idx_get_new(exfat_idx_t **, devmap_handle_t);
     173extern exfat_idx_t *exfat_idx_get_by_pos(devmap_handle_t, exfat_cluster_t, unsigned);
     174extern exfat_idx_t *exfat_idx_get_by_index(devmap_handle_t, fs_index_t);
     175extern void exfat_idx_destroy(exfat_idx_t *);
     176extern void exfat_idx_hashin(exfat_idx_t *);
     177extern void exfat_idx_hashout(exfat_idx_t *);
     178
     179extern int exfat_idx_init(void);
     180extern void exfat_idx_fini(void);
     181extern int exfat_idx_init_by_devmap_handle(devmap_handle_t);
     182extern void exfat_idx_fini_by_devmap_handle(devmap_handle_t);
    97183
    98184#endif
  • 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.