Changeset 8ff0bd2 in mainline for uspace/srv/fs


Ignore:
Timestamp:
2011-09-04T11:30:58Z (14 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
03bc76a
Parents:
d2c67e7 (diff), deac215e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Location:
uspace/srv/fs
Files:
15 added
1 deleted
16 edited
5 moved

Legend:

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

    rd2c67e7 r8ff0bd2  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2006 Martin Decky
     3 * Copyright (c) 2008 Jakub Jermar
     4 * Copyright (c) 2011 Oleg Romanenko
    35 * All rights reserved.
    46 *
     
    2729 */
    2830
    29 /** @addtogroup tester
    30  * @brief Test devman service.
     31/** @addtogroup fs
    3132 * @{
    32  */
     33 */
     34
    3335/**
    34  * @file
     36 * @file        exfat.c
     37 * @brief       FAT file system driver for HelenOS.
    3538 */
    3639
    37 #include <inttypes.h>
     40#include "exfat.h"
     41#include <ipc/services.h>
     42#include <ns.h>
     43#include <async.h>
    3844#include <errno.h>
    39 #include <str_error.h>
    40 #include <sys/types.h>
    41 #include <async.h>
    42 #include <devman.h>
    43 #include <str.h>
    44 #include <async.h>
    45 #include <vfs/vfs.h>
    46 #include <vfs/vfs_sess.h>
    47 #include <sys/stat.h>
    48 #include <fcntl.h>
    49 #include "../tester.h"
     45#include <unistd.h>
     46#include <task.h>
     47#include <stdio.h>
     48#include <libfs.h>
     49#include "../../vfs/vfs.h"
    5050
    51 #define DEVICE_CLASS "test3"
     51#define NAME    "exfat"
    5252
    53 const char *test_devman2(void)
     53vfs_info_t exfat_vfs_info = {
     54        .name = NAME,
     55        .concurrent_read_write = false,
     56        .write_retains_size = false,   
     57};
     58
     59int main(int argc, char **argv)
    5460{
    55         size_t idx = 1;
    56         int rc = EOK;
    57         const char *err_msg = NULL;
    58         char *path = NULL;
    59         while (rc == EOK) {
    60                 rc = asprintf(&path, "/dev/class/%s\\%zu", DEVICE_CLASS, idx);
    61                 if (rc < 0) {
    62                         continue;
    63                 }
    64                 int fd = open(path, O_RDONLY);
    65                 if (fd < 0) {
    66                         TPRINTF("Failed opening `%s': %s.\n",
    67                             path, str_error(fd));
    68                         rc = fd;
    69                         err_msg = "Failed opening file";
    70                         continue;
    71                 }
    72                 async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
    73                 close(fd);
    74                 if (sess == NULL) {
    75                         TPRINTF("Failed opening phone: %s.\n", str_error(errno));
    76                         rc = errno;
    77                         err_msg = "Failed opening file descriptor phone";
    78                         continue;
    79                 }
    80                 async_hangup(sess);
    81                 TPRINTF("Path `%s' okay.\n", path);
    82                 free(path);
    83                 idx++;
    84                 rc = EOK;
     61        printf(NAME ": HelenOS exFAT file system server\n");
     62
     63        int rc = exfat_idx_init();
     64        if (rc != EOK)
     65                goto err;
     66
     67        async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     68            SERVICE_VFS, 0, 0);
     69        if (!vfs_sess) {
     70                printf(NAME ": failed to connect to VFS\n");
     71                return -1;
    8572        }
    8673       
    87         if (path != NULL)
    88                 free(path);
     74        rc = fs_register(vfs_sess, &exfat_vfs_info, &exfat_ops, &exfat_libfs_ops);
     75        if (rc != EOK) {
     76                exfat_idx_fini();
     77                goto err;
     78        }
    8979       
    90         return err_msg;
     80        printf(NAME ": Accepting connections\n");
     81        task_retval(0);
     82        async_manager();
     83
     84        /* not reached */
     85        return 0;
     86
     87err:
     88        printf(NAME ": Failed to register file system (%d)\n", rc);
     89        return rc;
    9190}
    9291
    93 /** @}
     92
     93/**
     94 * @}
    9495 */
  • uspace/srv/fs/exfat/exfat_bitmap.h

    rd2c67e7 r8ff0bd2  
    11/*
    2  * Copyright (c) 2009 Martin Decky
     2 * Copyright (c) 2011 Oleg Romanenko
    33 * All rights reserved.
    44 *
     
    3131 */
    3232
    33 #ifndef DEVFS_DEVFS_OPS_H_
    34 #define DEVFS_DEVFS_OPS_H_
     33#ifndef EXFAT_EXFAT_BITMAP_H_
     34#define EXFAT_EXFAT_BITMAP_H_
    3535
    36 #include <ipc/common.h>
    37 #include <bool.h>
     36#include <stdint.h>
     37#include "exfat.h"
     38#include "exfat_fat.h"
    3839
    39 extern bool devfs_init(void);
     40/* forward declarations */
     41struct exfat_node;
     42struct exfat_bs;
    4043
    41 extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
    42 extern void devfs_mount(ipc_callid_t, ipc_call_t *);
    43 extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
    44 extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
    45 extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
    46 extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
    47 extern void devfs_stat(ipc_callid_t, ipc_call_t *);
    48 extern void devfs_sync(ipc_callid_t, ipc_call_t *);
    49 extern void devfs_read(ipc_callid_t, ipc_call_t *);
    50 extern void devfs_write(ipc_callid_t, ipc_call_t *);
    51 extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
    52 extern void devfs_close(ipc_callid_t, ipc_call_t *);
    53 extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
     44extern int bitmap_alloc_clusters(struct exfat_bs *, service_id_t,
     45    exfat_cluster_t *, exfat_cluster_t);
     46extern int bitmap_append_clusters(struct exfat_bs *, struct exfat_node *,
     47    exfat_cluster_t);
     48extern int bitmap_free_clusters(struct exfat_bs *, struct exfat_node *,
     49    exfat_cluster_t);
     50extern int bitmap_replicate_clusters(struct exfat_bs *, struct exfat_node *);
     51
     52extern int bitmap_is_free(struct exfat_bs *, service_id_t, exfat_cluster_t);
     53extern int bitmap_set_cluster(struct exfat_bs *, service_id_t, exfat_cluster_t);
     54extern int bitmap_clear_cluster(struct exfat_bs *, service_id_t,
     55    exfat_cluster_t);
     56
     57extern int bitmap_set_clusters(struct exfat_bs *, service_id_t,
     58    exfat_cluster_t, exfat_cluster_t);
     59extern int bitmap_clear_clusters(struct exfat_bs *, service_id_t,
     60    exfat_cluster_t, exfat_cluster_t);
     61
    5462
    5563#endif
  • uspace/srv/fs/ext2fs/ext2fs.c

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2006 Martin Decky
    3  * Copyright (c) 2008 Jakub Jermar
    43 * Copyright (c) 2011 Martin Sucha
    54 * All rights reserved.
     
    5554};
    5655
    57 fs_reg_t ext2fs_reg;
    58 
    59 /**
    60  * This connection fibril processes VFS requests from VFS.
    61  *
    62  * In order to support simultaneous VFS requests, our design is as follows.
    63  * The connection fibril accepts VFS requests from VFS. If there is only one
    64  * instance of the fibril, VFS will need to serialize all VFS requests it sends
    65  * to EXT2FS. To overcome this bottleneck, VFS can send EXT2FS the IPC_M_CONNECT_ME_TO
    66  * call. In that case, a new connection fibril will be created, which in turn
    67  * will accept the call. Thus, a new phone will be opened for VFS.
    68  *
    69  * There are few issues with this arrangement. First, VFS can run out of
    70  * available phones. In that case, VFS can close some other phones or use one
    71  * phone for more serialized requests. Similarily, EXT2FS can refuse to duplicate
    72  * the connection. VFS should then just make use of already existing phones and
    73  * route its requests through them. To avoid paying the fibril creation price
    74  * upon each request, EXT2FS might want to keep the connections open after the
    75  * request has been completed.
    76  */
    77 static void ext2fs_connection(ipc_callid_t iid, ipc_call_t *icall)
    78 {
    79         if (iid) {
    80                 /*
    81                  * This only happens for connections opened by
    82                  * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
    83                  * created by IPC_M_CONNECT_TO_ME.
    84                  */
    85                 async_answer_0(iid, EOK);
    86         }
    87        
    88         dprintf(NAME ": connection opened\n");
    89         while (true) {
    90                 ipc_call_t call;
    91                 ipc_callid_t callid = async_get_call(&call);
    92                
    93                 if (!IPC_GET_IMETHOD(call))
    94                         return;
    95                
    96                 switch (IPC_GET_IMETHOD(call)) {
    97                 case VFS_OUT_MOUNTED:
    98                         ext2fs_mounted(callid, &call);
    99                         break;
    100                 case VFS_OUT_MOUNT:
    101                         ext2fs_mount(callid, &call);
    102                         break;
    103                 case VFS_OUT_UNMOUNTED:
    104                         ext2fs_unmounted(callid, &call);
    105                         break;
    106                 case VFS_OUT_UNMOUNT:
    107                         ext2fs_unmount(callid, &call);
    108                         break;
    109                 case VFS_OUT_LOOKUP:
    110                         ext2fs_lookup(callid, &call);
    111                         break;
    112                 case VFS_OUT_READ:
    113                         ext2fs_read(callid, &call);
    114                         break;
    115                 case VFS_OUT_WRITE:
    116                         ext2fs_write(callid, &call);
    117                         break;
    118                 case VFS_OUT_TRUNCATE:
    119                         ext2fs_truncate(callid, &call);
    120                         break;
    121                 case VFS_OUT_STAT:
    122                         ext2fs_stat(callid, &call);
    123                         break;
    124                 case VFS_OUT_CLOSE:
    125                         ext2fs_close(callid, &call);
    126                         break;
    127                 case VFS_OUT_DESTROY:
    128                         ext2fs_destroy(callid, &call);
    129                         break;
    130                 case VFS_OUT_OPEN_NODE:
    131                         ext2fs_open_node(callid, &call);
    132                         break;
    133                 case VFS_OUT_SYNC:
    134                         ext2fs_sync(callid, &call);
    135                         break;
    136                 default:
    137                         async_answer_0(callid, ENOTSUP);
    138                         break;
    139                 }
    140         }
    141 }
    142 
    14356int main(int argc, char **argv)
    14457{
     
    15871        }       
    15972               
    160         rc = fs_register(vfs_sess, &ext2fs_reg, &ext2fs_vfs_info, ext2fs_connection);
     73        rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
     74            &ext2fs_libfs_ops);
    16175        if (rc != EOK) {
    16276                fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
  • uspace/srv/fs/ext2fs/ext2fs.h

    rd2c67e7 r8ff0bd2  
    11/*
    2  * Copyright (c) 2008 Jakub Jermar
    32 * Copyright (c) 2011 Martin Sucha
    43 * All rights reserved.
     
    3635
    3736#include <libext2.h>
    38 #include <fibril_synch.h>
    3937#include <libfs.h>
    40 #include <atomic.h>
    4138#include <sys/types.h>
    42 #include <bool.h>
    43 #include "../../vfs/vfs.h"
    44 
    45 #ifndef dprintf
    46 #define dprintf(...)    printf(__VA_ARGS__)
    47 #endif
    4839
    4940#define min(a, b)               ((a) < (b) ? (a) : (b))
    5041
    51 extern fs_reg_t ext2fs_reg;
     42extern vfs_out_ops_t ext2fs_ops;
     43extern libfs_ops_t ext2fs_libfs_ops;
    5244
    5345extern int ext2fs_global_init(void);
    5446extern int ext2fs_global_fini(void);
    55 extern void ext2fs_mounted(ipc_callid_t, ipc_call_t *);
    56 extern void ext2fs_mount(ipc_callid_t, ipc_call_t *);
    57 extern void ext2fs_unmounted(ipc_callid_t, ipc_call_t *);
    58 extern void ext2fs_unmount(ipc_callid_t, ipc_call_t *);
    59 extern void ext2fs_lookup(ipc_callid_t, ipc_call_t *);
    60 extern void ext2fs_read(ipc_callid_t, ipc_call_t *);
    61 extern void ext2fs_write(ipc_callid_t, ipc_call_t *);
    62 extern void ext2fs_truncate(ipc_callid_t, ipc_call_t *);
    63 extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
    64 extern void ext2fs_close(ipc_callid_t, ipc_call_t *);
    65 extern void ext2fs_destroy(ipc_callid_t, ipc_call_t *);
    66 extern void ext2fs_open_node(ipc_callid_t, ipc_call_t *);
    67 extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
    68 extern void ext2fs_sync(ipc_callid_t, ipc_call_t *);
    6947
    7048#endif
  • uspace/srv/fs/ext2fs/ext2fs_ops.c

    rd2c67e7 r8ff0bd2  
    11/*
    2  * Copyright (c) 2008 Jakub Jermar
    32 * Copyright (c) 2011 Martin Sucha
    43 * All rights reserved.
     
    4342#include <libext2.h>
    4443#include <ipc/services.h>
    45 #include <ipc/devmap.h>
     44#include <ipc/loc.h>
    4645#include <macros.h>
    4746#include <async.h>
     
    7069typedef struct ext2fs_instance {
    7170        link_t link;
    72         devmap_handle_t devmap_handle;
     71        service_id_t service_id;
    7372        ext2_filesystem_t *filesystem;
    7473        unsigned int open_nodes_count;
     
    8685 * Forward declarations of auxiliary functions
    8786 */
    88 static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
    89 static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
    90         size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
    91 static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
    92         size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
     87static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **);
     88static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
     89    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
     90static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
     91    ext2_inode_ref_t *, size_t *);
    9392static bool ext2fs_is_dots(const uint8_t *, size_t);
    9493static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
     
    9897 * Forward declarations of EXT2 libfs operations.
    9998 */
    100 static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
     99static int ext2fs_root_get(fs_node_t **, service_id_t);
    101100static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
    102 static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
     101static int ext2fs_node_get(fs_node_t **, service_id_t, fs_index_t);
    103102static int ext2fs_node_open(fs_node_t *);
    104103static int ext2fs_node_put(fs_node_t *);
    105 static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
     104static int ext2fs_create_node(fs_node_t **, service_id_t, int);
    106105static int ext2fs_destroy_node(fs_node_t *);
    107106static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
     
    111110static aoff64_t ext2fs_size_get(fs_node_t *);
    112111static unsigned ext2fs_lnkcnt_get(fs_node_t *);
    113 static char ext2fs_plb_get_char(unsigned);
    114112static bool ext2fs_is_directory(fs_node_t *);
    115113static bool ext2fs_is_file(fs_node_t *node);
    116 static devmap_handle_t ext2fs_device_get(fs_node_t *node);
     114static service_id_t ext2fs_device_get(fs_node_t *node);
    117115
    118116/*
     
    136134        ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
    137135        assert(keys > 0);
    138         if (enode->instance->devmap_handle !=
    139             ((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
     136        if (enode->instance->service_id !=
     137            ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
    140138                return false;
    141139        }
     
    182180
    183181/**
    184  * Find an instance of filesystem for the given devmap_handle
    185  */
    186 int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
    187 {
    188         EXT2FS_DBG("(%" PRIun ", -)", devmap_handle);
    189         link_t *link;
     182 * Find an instance of filesystem for the given service_id
     183 */
     184int ext2fs_instance_get(service_id_t service_id, ext2fs_instance_t **inst)
     185{
     186        EXT2FS_DBG("(%" PRIun ", -)", service_id);
    190187        ext2fs_instance_t *tmp;
    191188       
     
    198195        }
    199196
    200         for (link = instance_list.next; link != &instance_list; link = link->next) {
     197        list_foreach(instance_list, link) {
    201198                tmp = list_get_instance(link, ext2fs_instance_t, link);
    202199               
    203                 if (tmp->devmap_handle == devmap_handle) {
     200                if (tmp->service_id == service_id) {
    204201                        *inst = tmp;
    205202                        fibril_mutex_unlock(&instance_list_mutex);
     
    216213
    217214
    218 int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
    219 {
    220         EXT2FS_DBG("(-, %" PRIun ")", devmap_handle);
    221         return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
     215int ext2fs_root_get(fs_node_t **rfn, service_id_t service_id)
     216{
     217        EXT2FS_DBG("(-, %" PRIun ")", service_id);
     218        return ext2fs_node_get(rfn, service_id, EXT2_INODE_ROOT_INDEX);
    222219}
    223220
     
    241238        }
    242239       
    243         rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref);
     240        rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0);
    244241        if (rc != EOK) {
    245242                return rc;
     
    292289
    293290/** Instantiate a EXT2 in-core node. */
    294 int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
    295 {
    296         EXT2FS_DBG("(-,%" PRIun ",%u)", devmap_handle, index);
     291int ext2fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
     292{
     293        EXT2FS_DBG("(-,%" PRIun ",%u)", service_id, index);
    297294       
    298295        ext2fs_instance_t *inst = NULL;
    299296        int rc;
    300297       
    301         rc = ext2fs_instance_get(devmap_handle, &inst);
     298        rc = ext2fs_instance_get(service_id, &inst);
    302299        if (rc != EOK) {
    303300                return rc;
     
    320317        /* Check if the node is not already open */
    321318        unsigned long key[] = {
    322                 [OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle,
     319                [OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
    323320                [OPEN_NODES_INODE_KEY] = index,
    324321        };
     
    414411
    415412        unsigned long key[] = {
    416                 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle,
     413                [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
    417414                [OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
    418415        };
     
    432429}
    433430
    434 int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
     431int ext2fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    435432{
    436433        EXT2FS_DBG("");
     
    479476        }
    480477       
    481         rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref);
     478        rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0);
    482479        if (rc != EOK) {
    483480                EXT2FS_DBG("error %u", rc);
     
    541538}
    542539
    543 char ext2fs_plb_get_char(unsigned pos)
    544 {
    545         return ext2fs_reg.plb_ro[pos % PLB_SIZE];
    546 }
    547 
    548540bool ext2fs_is_directory(fs_node_t *fn)
    549541{
     
    565557}
    566558
    567 devmap_handle_t ext2fs_device_get(fs_node_t *fn)
     559service_id_t ext2fs_device_get(fs_node_t *fn)
    568560{
    569561        EXT2FS_DBG("");
    570562        ext2fs_node_t *enode = EXT2FS_NODE(fn);
    571         return enode->instance->devmap_handle;
     563        return enode->instance->service_id;
    572564}
    573565
     
    587579        .size_get = ext2fs_size_get,
    588580        .lnkcnt_get = ext2fs_lnkcnt_get,
    589         .plb_get_char = ext2fs_plb_get_char,
    590581        .is_directory = ext2fs_is_directory,
    591582        .is_file = ext2fs_is_file,
     
    597588 */
    598589
    599 void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
    600 {
    601         EXT2FS_DBG("");
    602         int rc;
    603         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     590static int ext2fs_mounted(service_id_t service_id, const char *opts,
     591   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
     592{
     593        EXT2FS_DBG("");
     594        int rc;
    604595        ext2_filesystem_t *fs;
    605596        ext2fs_instance_t *inst;
    606597        bool read_only;
    607598       
    608         /* Accept the mount options */
    609         char *opts;
    610         rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
    611        
    612         if (rc != EOK) {
    613                 async_answer_0(rid, rc);
    614                 return;
    615         }
    616 
    617         free(opts);
    618        
    619599        /* Allocate libext2 filesystem structure */
    620600        fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
    621         if (fs == NULL) {
    622                 async_answer_0(rid, ENOMEM);
    623                 return;
    624         }
     601        if (fs == NULL)
     602                return ENOMEM;
    625603       
    626604        /* Allocate instance structure */
     
    628606        if (inst == NULL) {
    629607                free(fs);
    630                 async_answer_0(rid, ENOMEM);
    631                 return;
     608                return ENOMEM;
    632609        }
    633610       
    634611        /* Initialize the filesystem  */
    635         rc = ext2_filesystem_init(fs, devmap_handle);
     612        rc = ext2_filesystem_init(fs, service_id);
    636613        if (rc != EOK) {
    637614                free(fs);
    638615                free(inst);
    639                 async_answer_0(rid, rc);
    640                 return;
     616                return rc;
    641617        }
    642618       
     
    647623                free(fs);
    648624                free(inst);
    649                 async_answer_0(rid, rc);
    650                 return;
     625                return rc;
    651626        }
    652627       
     
    657632                free(fs);
    658633                free(inst);
    659                 async_answer_0(rid, rc);
    660                 return;
     634                return rc;
    661635        }
    662636       
    663637        /* Initialize instance */
    664638        link_initialize(&inst->link);
    665         inst->devmap_handle = devmap_handle;
     639        inst->service_id = service_id;
    666640        inst->filesystem = fs;
    667641        inst->open_nodes_count = 0;
     
    674648                free(fs);
    675649                free(inst);
    676                 async_answer_0(rid, rc);
    677                 return;
     650                return rc;
    678651        }
    679652        ext2fs_node_t *enode = EXT2FS_NODE(root_node);
     
    684657        fibril_mutex_unlock(&instance_list_mutex);
    685658       
    686         async_answer_3(rid, EOK,
    687             EXT2_INODE_ROOT_INDEX,
    688             0,
    689             ext2_inode_get_usage_count(enode->inode_ref->inode));
     659        *index = EXT2_INODE_ROOT_INDEX;
     660        *size = 0;
     661        *lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
    690662       
    691663        ext2fs_node_put(root_node);
    692 }
    693 
    694 void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
    695 {
    696         EXT2FS_DBG("");
    697         libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
    698 }
    699 
    700 void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
    701 {
    702         EXT2FS_DBG("");
    703         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     664
     665        return EOK;
     666}
     667
     668static int ext2fs_unmounted(service_id_t service_id)
     669{
     670        EXT2FS_DBG("");
    704671        ext2fs_instance_t *inst;
    705672        int rc;
    706673       
    707         rc = ext2fs_instance_get(devmap_handle, &inst);
    708        
    709         if (rc != EOK) {
    710                 async_answer_0(rid, rc);
    711                 return;
    712         }
     674        rc = ext2fs_instance_get(service_id, &inst);
     675       
     676        if (rc != EOK)
     677                return rc;
    713678       
    714679        fibril_mutex_lock(&open_nodes_lock);
     
    717682        if (inst->open_nodes_count != 0) {
    718683                fibril_mutex_unlock(&open_nodes_lock);
    719                 async_answer_0(rid, EBUSY);
    720                 return;
     684                return EBUSY;
    721685        }
    722686       
     
    730694        ext2_filesystem_fini(inst->filesystem);
    731695       
    732         async_answer_0(rid, EOK);
    733 }
    734 
    735 void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
    736 {
    737         EXT2FS_DBG("");
    738         libfs_unmount(&ext2fs_libfs_ops, rid, request);
    739 }
    740 
    741 void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
    742 {
    743         EXT2FS_DBG("");
    744         libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
    745 }
    746 
    747 void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
    748 {
    749         EXT2FS_DBG("");
    750         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    751         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    752         aoff64_t pos =
    753             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     696        return EOK;
     697}
     698
     699static int
     700ext2fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
     701    size_t *rbytes)
     702{
     703        EXT2FS_DBG("");
    754704       
    755705        ext2fs_instance_t *inst;
     
    764714        if (!async_data_read_receive(&callid, &size)) {
    765715                async_answer_0(callid, EINVAL);
    766                 async_answer_0(rid, EINVAL);
    767                 return;
    768         }
    769        
    770         rc = ext2fs_instance_get(devmap_handle, &inst);
     716                return EINVAL;
     717        }
     718       
     719        rc = ext2fs_instance_get(service_id, &inst);
    771720        if (rc != EOK) {
    772721                async_answer_0(callid, rc);
    773                 async_answer_0(rid, rc);
    774                 return;
     722                return rc;
    775723        }
    776724       
     
    778726        if (rc != EOK) {
    779727                async_answer_0(callid, rc);
    780                 async_answer_0(rid, rc);
    781                 return;
     728                return rc;
    782729        }
    783730       
    784731        if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
    785                     EXT2_INODE_MODE_FILE)) {
    786                 ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
    787         }
    788         else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
    789                     EXT2_INODE_MODE_DIRECTORY)) {
    790                 ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
    791         }
    792         else {
     732            EXT2_INODE_MODE_FILE)) {
     733                rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
     734                    rbytes);
     735        } else if (ext2_inode_is_type(inst->filesystem->superblock,
     736            inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
     737                rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
     738                    rbytes);
     739        } else {
    793740                /* Other inode types not supported */
    794741                async_answer_0(callid, ENOTSUP);
    795                 async_answer_0(rid, ENOTSUP);
     742                rc = ENOTSUP;
    796743        }
    797744       
    798745        ext2_filesystem_put_inode_ref(inode_ref);
    799746       
     747        return rc;
    800748}
    801749
     
    815763}
    816764
    817 void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
    818         size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
     765int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
     766    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
    819767{
    820768        ext2_directory_iterator_t it;
    821         aoff64_t cur;
     769        aoff64_t next;
    822770        uint8_t *buf;
    823771        size_t name_size;
     
    825773        bool found = false;
    826774       
    827         rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref);
     775        rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos);
    828776        if (rc != EOK) {
    829777                async_answer_0(callid, rc);
    830                 async_answer_0(rid, rc);
    831                 return;
    832         }
    833        
    834         /* Find the index we want to read
    835          * Note that we need to iterate and count as
    836          * the underlying structure is a linked list
    837          * Moreover, we want to skip . and .. entries
     778                return rc;
     779        }
     780       
     781        /* Find next interesting directory entry.
     782         * We want to skip . and .. entries
    838783         * as these are not used in HelenOS
    839784         */
    840         cur = 0;
    841785        while (it.current != NULL) {
    842786                if (it.current->inode == 0) {
     
    845789               
    846790                name_size = ext2_directory_entry_ll_get_name_length(
    847                         inst->filesystem->superblock, it.current);
     791                    inst->filesystem->superblock, it.current);
    848792               
    849793                /* skip . and .. */
     
    852796                }
    853797               
    854                 /* Is this the dir entry we want to read? */
    855                 if (cur == pos) {
    856                         /* The on-disk entry does not contain \0 at the end
    857                          * end of entry name, so we copy it to new buffer
    858                          * and add the \0 at the end
    859                          */
    860                         buf = malloc(name_size+1);
    861                         if (buf == NULL) {
    862                                 ext2_directory_iterator_fini(&it);
    863                                 async_answer_0(callid, ENOMEM);
    864                                 async_answer_0(rid, ENOMEM);
    865                                 return;
    866                         }
    867                         memcpy(buf, &it.current->name, name_size);
    868                         *(buf+name_size) = 0;
    869                         found = true;
    870                         (void) async_data_read_finalize(callid, buf, name_size+1);
    871                         free(buf);
    872                         break;
    873                 }
    874                 cur++;
     798                /* The on-disk entry does not contain \0 at the end
     799                 * end of entry name, so we copy it to new buffer
     800                 * and add the \0 at the end
     801                 */
     802                buf = malloc(name_size+1);
     803                if (buf == NULL) {
     804                        ext2_directory_iterator_fini(&it);
     805                        async_answer_0(callid, ENOMEM);
     806                        return ENOMEM;
     807                }
     808                memcpy(buf, &it.current->name, name_size);
     809                *(buf + name_size) = 0;
     810                found = true;
     811                (void) async_data_read_finalize(callid, buf, name_size + 1);
     812                free(buf);
     813                break;
    875814               
    876815skip:
     
    879818                        ext2_directory_iterator_fini(&it);
    880819                        async_answer_0(callid, rc);
    881                         async_answer_0(rid, rc);
    882                         return;
    883                 }
     820                        return rc;
     821                }
     822        }
     823       
     824        if (found) {
     825                rc = ext2_directory_iterator_next(&it);
     826                if (rc != EOK)
     827                        return rc;
     828                next = it.current_offset;
    884829        }
    885830       
    886831        rc = ext2_directory_iterator_fini(&it);
    887         if (rc != EOK) {
    888                 async_answer_0(rid, rc);
    889                 return;
    890         }
     832        if (rc != EOK)
     833                return rc;
    891834       
    892835        if (found) {
    893                 async_answer_1(rid, EOK, 1);
    894         }
    895         else {
     836                *rbytes = next - pos;
     837                return EOK;
     838        } else {
    896839                async_answer_0(callid, ENOENT);
    897                 async_answer_0(rid, ENOENT);
    898         }
    899 }
    900 
    901 void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
    902         size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
     840                return ENOENT;
     841        }
     842}
     843
     844int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
     845    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
    903846{
    904847        int rc;
     
    918861                /* Read 0 bytes successfully */
    919862                async_data_read_finalize(callid, NULL, 0);
    920                 async_answer_1(rid, EOK, 0);
    921                 return;
     863                *rbytes = 0;
     864                return EOK;
    922865        }
    923866       
     
    938881        if (rc != EOK) {
    939882                async_answer_0(callid, rc);
    940                 async_answer_0(rid, rc);
    941                 return;
     883                return rc;
    942884        }
    943885       
     
    951893                if (buffer == NULL) {
    952894                        async_answer_0(callid, ENOMEM);
    953                         async_answer_0(rid, ENOMEM);
    954                         return;
     895                        return ENOMEM;
    955896                }
    956897               
     
    958899               
    959900                async_data_read_finalize(callid, buffer, bytes);
    960                 async_answer_1(rid, EOK, bytes);
     901                *rbytes = bytes;
    961902               
    962903                free(buffer);
    963904               
    964                 return;
     905                return EOK;
    965906        }
    966907       
    967908        /* Usual case - we need to read a block from device */
    968         rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
     909        rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE);
    969910        if (rc != EOK) {
    970911                async_answer_0(callid, rc);
    971                 async_answer_0(rid, rc);
    972                 return;
     912                return rc;
    973913        }
    974914       
     
    977917       
    978918        rc = block_put(block);
    979         if (rc != EOK) {
    980                 async_answer_0(rid, rc);
    981                 return;
    982         }
    983                
    984         async_answer_1(rid, EOK, bytes);
    985 }
    986 
    987 void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
    988 {
    989         EXT2FS_DBG("");
    990 //      devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    991 //      fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    992 //      aoff64_t pos =
    993 //          (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    994        
    995         // TODO
    996         async_answer_0(rid, ENOTSUP);
    997 }
    998 
    999 void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
    1000 {
    1001         EXT2FS_DBG("");
    1002 //      devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1003 //      fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1004 //      aoff64_t size =
    1005 //          (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    1006        
    1007         // TODO
    1008         async_answer_0(rid, ENOTSUP);
    1009 }
    1010 
    1011 void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
    1012 {
    1013         EXT2FS_DBG("");
    1014         async_answer_0(rid, EOK);
    1015 }
    1016 
    1017 void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
    1018 {
    1019         EXT2FS_DBG("");
    1020 //      devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
    1021 //      fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    1022        
    1023         // TODO
    1024         async_answer_0(rid, ENOTSUP);
    1025 }
    1026 
    1027 void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
    1028 {
    1029         EXT2FS_DBG("");
    1030         libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
    1031 }
    1032 
    1033 void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
    1034 {
    1035         EXT2FS_DBG("");
    1036         libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
    1037 }
    1038 
    1039 void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
    1040 {
    1041         EXT2FS_DBG("");
    1042 //      devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1043 //      fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1044        
    1045         // TODO
    1046         async_answer_0(rid, ENOTSUP);
    1047 }
     919        if (rc != EOK)
     920                return rc;
     921       
     922        *rbytes = bytes;
     923        return EOK;
     924}
     925
     926static int
     927ext2fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
     928    size_t *wbytes, aoff64_t *nsize)
     929{
     930        EXT2FS_DBG("");
     931        return ENOTSUP;
     932}
     933
     934static int
     935ext2fs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
     936{
     937        EXT2FS_DBG("");
     938        return ENOTSUP;
     939}
     940
     941static int ext2fs_close(service_id_t service_id, fs_index_t index)
     942{
     943        EXT2FS_DBG("");
     944        return EOK;
     945}
     946
     947static int ext2fs_destroy(service_id_t service_id, fs_index_t index)
     948{
     949        EXT2FS_DBG("");
     950        return ENOTSUP;
     951}
     952
     953static int ext2fs_sync(service_id_t service_id, fs_index_t index)
     954{
     955        EXT2FS_DBG("");
     956        return ENOTSUP;
     957}
     958
     959vfs_out_ops_t ext2fs_ops = {
     960        .mounted = ext2fs_mounted,
     961        .unmounted = ext2fs_unmounted,
     962        .read = ext2fs_read,
     963        .write = ext2fs_write,
     964        .truncate = ext2fs_truncate,
     965        .close = ext2fs_close,
     966        .destroy = ext2fs_destroy,
     967        .sync = ext2fs_sync,
     968};
    1048969
    1049970/**
    1050971 * @}
    1051972 */
     973
  • uspace/srv/fs/fat/Makefile

    rd2c67e7 r8ff0bd2  
    3939        fat_idx.c \
    4040        fat_dentry.c \
     41        fat_directory.c \
    4142        fat_fat.c
    4243
  • uspace/srv/fs/fat/fat.c

    rd2c67e7 r8ff0bd2  
    22 * Copyright (c) 2006 Martin Decky
    33 * Copyright (c) 2008 Jakub Jermar
     4 * Copyright (c) 2011 Oleg Romanenko
    45 * All rights reserved.
    56 *
     
    5657};
    5758
    58 fs_reg_t fat_reg;
    59 
    60 /**
    61  * This connection fibril processes VFS requests from VFS.
    62  *
    63  * In order to support simultaneous VFS requests, our design is as follows.
    64  * The connection fibril accepts VFS requests from VFS. If there is only one
    65  * instance of the fibril, VFS will need to serialize all VFS requests it sends
    66  * to FAT. To overcome this bottleneck, VFS can send FAT the IPC_M_CONNECT_ME_TO
    67  * call. In that case, a new connection fibril will be created, which in turn
    68  * will accept the call. Thus, a new phone will be opened for VFS.
    69  *
    70  * There are few issues with this arrangement. First, VFS can run out of
    71  * available phones. In that case, VFS can close some other phones or use one
    72  * phone for more serialized requests. Similarily, FAT can refuse to duplicate
    73  * the connection. VFS should then just make use of already existing phones and
    74  * route its requests through them. To avoid paying the fibril creation price
    75  * upon each request, FAT might want to keep the connections open after the
    76  * request has been completed.
    77  */
    78 static void fat_connection(ipc_callid_t iid, ipc_call_t *icall)
    79 {
    80         if (iid) {
    81                 /*
    82                  * This only happens for connections opened by
    83                  * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
    84                  * created by IPC_M_CONNECT_TO_ME.
    85                  */
    86                 async_answer_0(iid, EOK);
    87         }
    88        
    89         dprintf(NAME ": connection opened\n");
    90        
    91         while (true) {
    92                 ipc_call_t call;
    93                 ipc_callid_t callid = async_get_call(&call);
    94                
    95                 if (!IPC_GET_IMETHOD(call))
    96                         return;
    97                
    98                 switch (IPC_GET_IMETHOD(call)) {
    99                 case VFS_OUT_MOUNTED:
    100                         fat_mounted(callid, &call);
    101                         break;
    102                 case VFS_OUT_MOUNT:
    103                         fat_mount(callid, &call);
    104                         break;
    105                 case VFS_OUT_UNMOUNTED:
    106                         fat_unmounted(callid, &call);
    107                         break;
    108                 case VFS_OUT_UNMOUNT:
    109                         fat_unmount(callid, &call);
    110                         break;
    111                 case VFS_OUT_LOOKUP:
    112                         fat_lookup(callid, &call);
    113                         break;
    114                 case VFS_OUT_READ:
    115                         fat_read(callid, &call);
    116                         break;
    117                 case VFS_OUT_WRITE:
    118                         fat_write(callid, &call);
    119                         break;
    120                 case VFS_OUT_TRUNCATE:
    121                         fat_truncate(callid, &call);
    122                         break;
    123                 case VFS_OUT_STAT:
    124                         fat_stat(callid, &call);
    125                         break;
    126                 case VFS_OUT_CLOSE:
    127                         fat_close(callid, &call);
    128                         break;
    129                 case VFS_OUT_DESTROY:
    130                         fat_destroy(callid, &call);
    131                         break;
    132                 case VFS_OUT_OPEN_NODE:
    133                         fat_open_node(callid, &call);
    134                         break;
    135                 case VFS_OUT_SYNC:
    136                         fat_sync(callid, &call);
    137                         break;
    138                 default:
    139                         async_answer_0(callid, ENOTSUP);
    140                         break;
    141                 }
    142         }
    143 }
    144 
    14559int main(int argc, char **argv)
    14660{
     
    15872        }
    15973       
    160         rc = fs_register(vfs_sess, &fat_reg, &fat_vfs_info, fat_connection);
     74        rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops);
    16175        if (rc != EOK) {
    16276                fat_idx_fini();
  • uspace/srv/fs/fat/fat.h

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    4647#endif
    4748
    48 #define min(a, b)               ((a) < (b) ? (a) : (b))
     49#define min(a, b)       ((a) < (b) ? (a) : (b))
    4950
    5051/*
     
    5556#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5657#define FATCNT(bs)      (bs)->fatcnt
    57 #define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
     58
     59#define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) ? \
     60    uint16_t_le2host((bs)->sec_per_fat) : \
     61    uint32_t_le2host(bs->fat32.sectors_per_fat))
     62
    5863#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    59 #define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
    60                         uint16_t_le2host((bs)->totsec16) : \
    61                         uint32_t_le2host(bs->totsec32))
    62 
    63 #define BS_BLOCK                0
    64 #define BS_SIZE                 512
     64
     65#define TS(bs)          (uint16_t_le2host((bs)->totsec16) ? \
     66    uint16_t_le2host((bs)->totsec16) : \
     67    uint32_t_le2host(bs->totsec32))
     68
     69#define BS_BLOCK        0
     70#define BS_SIZE         512
    6571
    6672typedef struct fat_bs {
     
    175181
    176182        fibril_mutex_t  lock;
    177         devmap_handle_t devmap_handle;
     183        service_id_t    service_id;
    178184        fs_index_t      index;
    179185        /**
     
    224230} fat_node_t;
    225231
    226 extern fs_reg_t fat_reg;
    227 
    228 extern void fat_mounted(ipc_callid_t, ipc_call_t *);
    229 extern void fat_mount(ipc_callid_t, ipc_call_t *);
    230 extern void fat_unmounted(ipc_callid_t, ipc_call_t *);
    231 extern void fat_unmount(ipc_callid_t, ipc_call_t *);
    232 extern void fat_lookup(ipc_callid_t, ipc_call_t *);
    233 extern void fat_read(ipc_callid_t, ipc_call_t *);
    234 extern void fat_write(ipc_callid_t, ipc_call_t *);
    235 extern void fat_truncate(ipc_callid_t, ipc_call_t *);
    236 extern void fat_stat(ipc_callid_t, ipc_call_t *);
    237 extern void fat_close(ipc_callid_t, ipc_call_t *);
    238 extern void fat_destroy(ipc_callid_t, ipc_call_t *);
    239 extern void fat_open_node(ipc_callid_t, ipc_call_t *);
    240 extern void fat_stat(ipc_callid_t, ipc_call_t *);
    241 extern void fat_sync(ipc_callid_t, ipc_call_t *);
    242 
    243 extern int fat_idx_get_new(fat_idx_t **, devmap_handle_t);
    244 extern fat_idx_t *fat_idx_get_by_pos(devmap_handle_t, fat_cluster_t, unsigned);
    245 extern fat_idx_t *fat_idx_get_by_index(devmap_handle_t, fs_index_t);
     232extern vfs_out_ops_t fat_ops;
     233extern libfs_ops_t fat_libfs_ops;
     234
     235extern int fat_idx_get_new(fat_idx_t **, service_id_t);
     236extern fat_idx_t *fat_idx_get_by_pos(service_id_t, fat_cluster_t, unsigned);
     237extern fat_idx_t *fat_idx_get_by_index(service_id_t, fs_index_t);
    246238extern void fat_idx_destroy(fat_idx_t *);
    247239extern void fat_idx_hashin(fat_idx_t *);
     
    250242extern int fat_idx_init(void);
    251243extern void fat_idx_fini(void);
    252 extern int fat_idx_init_by_devmap_handle(devmap_handle_t);
    253 extern void fat_idx_fini_by_devmap_handle(devmap_handle_t);
     244extern int fat_idx_init_by_service_id(service_id_t);
     245extern void fat_idx_fini_by_service_id(service_id_t);
    254246
    255247#endif
  • uspace/srv/fs/fat/fat_dentry.c

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3940#include <ctype.h>
    4041#include <str.h>
    41 
    42 static bool is_d_char(const char ch)
    43 {
    44         if (isalnum(ch) || ch == '_')
    45                 return true;
    46         else
    47                 return false;
    48 }
     42#include <errno.h>
     43#include <byteorder.h>
     44#include <assert.h>
    4945
    5046/** Compare path component with the name read from the dentry.
     
    8076}
    8177
    82 bool fat_dentry_name_verify(const char *name)
     78void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
     79{
     80        unsigned int i;
     81       
     82        for (i = 0; i < FAT_NAME_LEN; i++) {
     83                if (d->name[i] == FAT_PAD)
     84                        break;
     85               
     86                if (d->name[i] == FAT_DENTRY_E5_ESC)
     87                        *buf++ = 0xe5;
     88                else {
     89                        if (d->lcase & FAT_LCASE_LOWER_NAME)
     90                                *buf++ = tolower(d->name[i]);
     91                        else
     92                                *buf++ = d->name[i];
     93                }
     94        }
     95       
     96        if (d->ext[0] != FAT_PAD)
     97                *buf++ = '.';
     98       
     99        for (i = 0; i < FAT_EXT_LEN; i++) {
     100                if (d->ext[i] == FAT_PAD) {
     101                        *buf = '\0';
     102                        return;
     103                }
     104               
     105                if (d->ext[i] == FAT_DENTRY_E5_ESC)
     106                        *buf++ = 0xe5;
     107                else {
     108                        if (d->lcase & FAT_LCASE_LOWER_EXT)
     109                                *buf++ = tolower(d->ext[i]);
     110                        else
     111                                *buf++ = d->ext[i];
     112                }
     113        }
     114       
     115        *buf = '\0';
     116}
     117
     118void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     119{
     120        unsigned int i;
     121        const char fake_ext[] = "   ";
     122        bool lower_name = true;
     123        bool lower_ext = true;
     124       
     125        for (i = 0; i < FAT_NAME_LEN; i++) {
     126                switch ((uint8_t) *name) {
     127                case 0xe5:
     128                        d->name[i] = FAT_DENTRY_E5_ESC;
     129                        name++;
     130                        break;
     131                case '\0':
     132                case '.':
     133                        d->name[i] = FAT_PAD;
     134                        break;
     135                default:
     136                        if (isalpha(*name)) {
     137                                if (!islower(*name))
     138                                        lower_name = false;
     139                        }
     140                       
     141                        d->name[i] = toupper(*name++);
     142                        break;
     143                }
     144        }
     145       
     146        if (*name++ != '.')
     147                name = fake_ext;
     148       
     149        for (i = 0; i < FAT_EXT_LEN; i++) {
     150                switch ((uint8_t) *name) {
     151                case 0xe5:
     152                        d->ext[i] = FAT_DENTRY_E5_ESC;
     153                        name++;
     154                        break;
     155                case '\0':
     156                        d->ext[i] = FAT_PAD;
     157                        break;
     158                default:
     159                        if (isalpha(*name)) {
     160                                if (!islower(*name))
     161                                        lower_ext = false;
     162                        }
     163                       
     164                        d->ext[i] = toupper(*name++);
     165                        break;
     166                }
     167        }
     168       
     169        if (lower_name)
     170                d->lcase |= FAT_LCASE_LOWER_NAME;
     171        else
     172                d->lcase &= ~FAT_LCASE_LOWER_NAME;
     173       
     174        if (lower_ext)
     175                d->lcase |= FAT_LCASE_LOWER_EXT;
     176        else
     177                d->lcase &= ~FAT_LCASE_LOWER_EXT;
     178}
     179
     180fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
     181{
     182        if (d->attr == FAT_ATTR_LFN) {
     183                /* long name entry */
     184                if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
     185                        return FAT_DENTRY_FREE;
     186                else
     187                        return FAT_DENTRY_LFN;
     188        }
     189        if (d->attr & FAT_ATTR_VOLLABEL) {
     190                /* volume label entry */
     191                return FAT_DENTRY_SKIP;
     192        }
     193        if (d->name[0] == FAT_DENTRY_ERASED) {
     194                /* not-currently-used entry */
     195                return FAT_DENTRY_FREE;
     196        }
     197        if (d->name[0] == FAT_DENTRY_UNUSED) {
     198                /* never used entry */
     199                return FAT_DENTRY_LAST;
     200        }
     201        if (d->name[0] == FAT_DENTRY_DOT) {
     202                /*
     203                 * Most likely '.' or '..'.
     204                 * It cannot occur in a regular file name.
     205                 */
     206                return FAT_DENTRY_SKIP;
     207        }
     208        return FAT_DENTRY_VALID;
     209}
     210
     211/** Compute checksum of Node name.
     212 *
     213 * Returns an unsigned byte checksum computed on an unsigned byte
     214 * array. The array must be 11 bytes long and is assumed to contain
     215 * a name stored in the format of a MS-DOS directory entry.
     216 *
     217 * @param name          Node name read from the dentry.
     218 *
     219 * @return              An 8-bit unsigned checksum of the name.
     220 */
     221uint8_t fat_dentry_chksum(uint8_t *name)
     222{
     223        uint8_t i, sum = 0;
     224
     225        for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
     226                sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
     227
     228        return sum;
     229}
     230
     231/** Get number of bytes in a string with size limit.
     232 *
     233 * @param str  NULL-terminated (or not) string.
     234 * @param size Maximum number of bytes to consider.
     235 *
     236 * @return Number of bytes in string (without 0 and ff).
     237 *
     238 */
     239size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
     240{
     241        size_t offset = 0;
     242
     243        while (offset < size) {
     244                if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
     245                        break;
     246                offset++;
     247        }
     248        return offset;
     249}
     250
     251/** Get number of bytes in a FAT long entry occuped by characters.
     252 *
     253 * @param d FAT long entry.
     254 *
     255 * @return Number of bytes.
     256 *
     257 */
     258size_t fat_lfn_size(const fat_dentry_t *d)
     259{
     260        size_t size = 0;
     261       
     262        size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
     263        size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
     264        size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
     265       
     266        return size;
     267}
     268
     269size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
     270{
     271        int i;
     272        for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
     273                if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
     274                        continue;
     275                (*offset)--;
     276                dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
     277        }
     278        for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
     279                if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
     280                        continue;
     281                (*offset)--;
     282                dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
     283        }
     284        for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
     285                if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
     286                        continue;
     287                (*offset)--;
     288                dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
     289        }
     290        return *offset;
     291}
     292
     293size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
     294    fat_dentry_t *d)
     295{
     296        size_t idx;
     297        for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
     298                if (*offset < size) {
     299                        d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
     300                        (*offset)++;
     301                } else
     302                        d->lfn.part1[idx] = FAT_LFN_PAD;
     303        }
     304        for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
     305                if (*offset < size) {
     306                        d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
     307                        (*offset)++;
     308                } else
     309                        d->lfn.part2[idx] = FAT_LFN_PAD;
     310        }
     311        for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) {
     312                if (*offset < size) {
     313                        d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
     314                        (*offset)++;
     315                } else
     316                        d->lfn.part3[idx] = FAT_LFN_PAD;
     317        }
     318
     319        if (src[*offset] == 0)
     320                offset++;
     321        FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
     322        d->lfn.type = 0;
     323        d->lfn.firstc_lo = 0;
     324       
     325        return *offset;
     326}
     327
     328void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
     329{
     330        wchar_t ch;
     331        size_t off = 0;
     332        size_t i = 0;
     333       
     334        while (i < count) {
     335                if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
     336                        if (ascii_check(ch) & IS_D_CHAR(ch))
     337                                *dst = toupper(ch);
     338                        else
     339                                *dst = pad;
     340                } else
     341                        break;
     342
     343                dst++;
     344                i++;
     345        }
     346        *dst = '\0';
     347}
     348
     349bool fat_valid_name(const char *name)
     350{
     351        wchar_t ch;
     352        size_t offset=0;
     353        bool result = true;
     354       
     355        while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
     356                if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
     357                        result = false;
     358                        break;
     359                }
     360        }
     361        return result;
     362}
     363
     364bool fat_valid_short_name(const char *name)
    83365{
    84366        unsigned int i;
    85367        unsigned int dot = 0;
    86368        bool dot_found = false;
    87        
    88369
    89370        for (i = 0; name[i]; i++) {
     
    96377                        }
    97378                } else {
    98                         if (!is_d_char(name[i]))
     379                        if (!IS_D_CHAR(name[i]))
    99380                                return false;
    100381                }
     
    114395}
    115396
    116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    117 {
    118         unsigned int i;
    119        
    120         for (i = 0; i < FAT_NAME_LEN; i++) {
    121                 if (d->name[i] == FAT_PAD)
    122                         break;
    123                
    124                 if (d->name[i] == FAT_DENTRY_E5_ESC)
    125                         *buf++ = 0xe5;
    126                 else {
    127                         if (d->lcase & FAT_LCASE_LOWER_NAME)
    128                                 *buf++ = tolower(d->name[i]);
    129                         else
    130                                 *buf++ = d->name[i];
    131                 }
    132         }
    133        
    134         if (d->ext[0] != FAT_PAD)
    135                 *buf++ = '.';
    136        
    137         for (i = 0; i < FAT_EXT_LEN; i++) {
    138                 if (d->ext[i] == FAT_PAD) {
    139                         *buf = '\0';
    140                         return;
    141                 }
    142                
    143                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
    144                         *buf++ = 0xe5;
    145                 else {
    146                         if (d->lcase & FAT_LCASE_LOWER_EXT)
    147                                 *buf++ = tolower(d->ext[i]);
    148                         else
    149                                 *buf++ = d->ext[i];
    150                 }
    151         }
    152        
    153         *buf = '\0';
    154 }
    155 
    156 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
    157 {
    158         unsigned int i;
    159         const char fake_ext[] = "   ";
    160         bool lower_name = true;
    161         bool lower_ext = true;
    162        
    163         for (i = 0; i < FAT_NAME_LEN; i++) {
    164                 switch ((uint8_t) *name) {
    165                 case 0xe5:
    166                         d->name[i] = FAT_DENTRY_E5_ESC;
    167                         name++;
    168                         break;
    169                 case '\0':
    170                 case '.':
    171                         d->name[i] = FAT_PAD;
    172                         break;
    173                 default:
    174                         if (isalpha(*name)) {
    175                                 if (!islower(*name))
    176                                         lower_name = false;
    177                         }
    178                        
    179                         d->name[i] = toupper(*name++);
    180                         break;
    181                 }
    182         }
    183        
    184         if (*name++ != '.')
    185                 name = fake_ext;
    186        
    187         for (i = 0; i < FAT_EXT_LEN; i++) {
    188                 switch ((uint8_t) *name) {
    189                 case 0xe5:
    190                         d->ext[i] = FAT_DENTRY_E5_ESC;
    191                         name++;
    192                         break;
    193                 case '\0':
    194                         d->ext[i] = FAT_PAD;
    195                         break;
    196                 default:
    197                         if (isalpha(*name)) {
    198                                 if (!islower(*name))
    199                                         lower_ext = false;
    200                         }
    201                        
    202                         d->ext[i] = toupper(*name++);
    203                         break;
    204                 }
    205         }
    206        
    207         if (lower_name)
    208                 d->lcase |= FAT_LCASE_LOWER_NAME;
    209         else
    210                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
    211        
    212         if (lower_ext)
    213                 d->lcase |= FAT_LCASE_LOWER_EXT;
    214         else
    215                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
    216 }
    217 
    218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    219 {
    220         if (d->attr & FAT_ATTR_VOLLABEL) {
    221                 /* volume label entry */
    222                 return FAT_DENTRY_SKIP;
    223         }
    224         if (d->name[0] == FAT_DENTRY_ERASED) {
    225                 /* not-currently-used entry */
    226                 return FAT_DENTRY_FREE;
    227         }
    228         if (d->name[0] == FAT_DENTRY_UNUSED) {
    229                 /* never used entry */
    230                 return FAT_DENTRY_LAST;
    231         }
    232         if (d->name[0] == FAT_DENTRY_DOT) {
    233                 /*
    234                  * Most likely '.' or '..'.
    235                  * It cannot occur in a regular file name.
    236                  */
    237                 return FAT_DENTRY_SKIP;
    238         }
    239         return FAT_DENTRY_VALID;
     397size_t utf16_length(const uint16_t *wstr)
     398{
     399        size_t len = 0;
     400       
     401        while (*wstr++ != 0)
     402                len++;
     403       
     404        return len;
    240405}
    241406
  • uspace/srv/fs/fat/fat_dentry.h

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3738#include <bool.h>
    3839
     40#define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')
     41#define FAT_STOP_CHARS "*?/\\\n\t|'"
     42
    3943#define FAT_NAME_LEN            8
    4044#define FAT_EXT_LEN             3
     
    4448#define FAT_EXT_PAD             "   "
    4549
    46 #define FAT_ATTR_RDONLY         (1 << 0)
    47 #define FAT_ATTR_VOLLABEL       (1 << 3)
    48 #define FAT_ATTR_SUBDIR         (1 << 4)
    49 
     50#define FAT_ATTR_RDONLY   0x01
     51#define FAT_ATTR_HIDDEN   0x02
     52#define FAT_ATTR_SYSTEM   0x04
     53#define FAT_ATTR_VOLLABEL 0x08
     54#define FAT_ATTR_SUBDIR   0x10
     55#define FAT_ATTR_ARCHIVE  0x20
     56#define FAT_ATTR_LFN \
     57    (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
     58   
    5059#define FAT_LCASE_LOWER_NAME    0x08
    5160#define FAT_LCASE_LOWER_EXT     0x10
    5261
    53 #define FAT_PAD                 ' '
     62#define FAT_PAD                 ' '
     63#define FAT_LFN_PAD     0xffff
     64#define FAT_SFN_CHAR '_'
    5465
    5566#define FAT_DENTRY_UNUSED       0x00
     
    5768#define FAT_DENTRY_DOT          0x2e
    5869#define FAT_DENTRY_ERASED       0xe5
     70#define FAT_LFN_LAST            0x40
     71#define FAT_LFN_ERASED          0x80
     72
     73#define FAT_LFN_ORDER(d) ((d)->lfn.order)
     74#define FAT_IS_LFN(d) \
     75    ((FAT_LFN_ORDER((d)) & FAT_LFN_LAST) == FAT_LFN_LAST)
     76#define FAT_LFN_COUNT(d) \
     77    (FAT_LFN_ORDER((d)) ^ FAT_LFN_LAST)
     78#define FAT_LFN_PART1(d) ((d)->lfn.part1)
     79#define FAT_LFN_PART2(d) ((d)->lfn.part2)
     80#define FAT_LFN_PART3(d) ((d)->lfn.part3)
     81#define FAT_LFN_ATTR(d) ((d)->lfn.attr)
     82#define FAT_LFN_CHKSUM(d) ((d)->lfn.check_sum)
     83
     84#define FAT_LFN_NAME_SIZE   260
     85#define FAT_LFN_MAX_COUNT   20
     86#define FAT_LFN_PART1_SIZE  5
     87#define FAT_LFN_PART2_SIZE  6
     88#define FAT_LFN_PART3_SIZE  2
     89#define FAT_LFN_ENTRY_SIZE \
     90    (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
    5991
    6092typedef enum {
     
    6294        FAT_DENTRY_LAST,
    6395        FAT_DENTRY_FREE,
    64         FAT_DENTRY_VALID
     96        FAT_DENTRY_VALID,
     97        FAT_DENTRY_LFN
    6598} fat_dentry_clsf_t;
    6699
    67 typedef struct {
    68         uint8_t         name[8];
    69         uint8_t         ext[3];
    70         uint8_t         attr;
    71         uint8_t         lcase;
    72         uint8_t         ctime_fine;
    73         uint16_t        ctime;
    74         uint16_t        cdate;
    75         uint16_t        adate;
    76         union {
    77                 uint16_t        eaidx;          /* FAT12/FAT16 */
    78                 uint16_t        firstc_hi;      /* FAT32 */
     100typedef union {
     101        struct {
     102                uint8_t         name[8];
     103                uint8_t         ext[3];
     104                uint8_t         attr;
     105                uint8_t         lcase;
     106                uint8_t         ctime_fine;
     107                uint16_t        ctime;
     108                uint16_t        cdate;
     109                uint16_t        adate;
     110                union {
     111                        uint16_t        eaidx;          /* FAT12/FAT16 */
     112                        uint16_t        firstc_hi;      /* FAT32 */
     113                } __attribute__ ((packed));
     114                uint16_t        mtime;
     115                uint16_t        mdate;
     116                union {
     117                        uint16_t        firstc;         /* FAT12/FAT16 */
     118                        uint16_t        firstc_lo;      /* FAT32 */
     119                } __attribute__ ((packed));
     120                uint32_t        size;
    79121        } __attribute__ ((packed));
    80         uint16_t        mtime;
    81         uint16_t        mdate;
    82         union {
    83                 uint16_t        firstc;         /* FAT12/FAT16 */
    84                 uint16_t        firstc_lo;      /* FAT32 */
    85         } __attribute__ ((packed));
    86         uint32_t        size;
     122        struct {
     123                uint8_t         order;
     124                uint16_t        part1[FAT_LFN_PART1_SIZE];
     125                uint8_t         attr;
     126                uint8_t         type;
     127                uint8_t         check_sum;
     128                uint16_t        part2[FAT_LFN_PART2_SIZE];
     129                uint16_t        firstc_lo; /* MUST be 0 */
     130                uint16_t        part3[FAT_LFN_PART3_SIZE];
     131        } __attribute__ ((packed)) lfn;
    87132} __attribute__ ((packed)) fat_dentry_t;
    88133
     134
    89135extern int fat_dentry_namecmp(char *, const char *);
    90 extern bool fat_dentry_name_verify(const char *);
    91136extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    92137extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    93138extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
     139extern uint8_t fat_dentry_chksum(uint8_t *);
     140
     141extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
     142extern size_t fat_lfn_size(const fat_dentry_t *);
     143extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
     144extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t,
     145    fat_dentry_t *);
     146
     147extern void str_to_ascii(char *, const char *, size_t, uint8_t);
     148extern size_t utf16_length(const uint16_t *);
     149
     150extern bool fat_valid_name(const char *);
     151extern bool fat_valid_short_name(const char *);
    94152
    95153#endif
  • uspace/srv/fs/fat/fat_fat.c

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    5051#include <mem.h>
    5152
    52 /*
    53  * Convenience macros for computing some frequently used values from the
    54  * primitive boot sector members.
    55  */
    56 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    57                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    58 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    59 
    60 #define CLBN2PBN(bs, cl, bn) \
    61         (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     53#define IS_ODD(number)  (number & 0x1)
    6254
    6355/**
     
    6557 * during allocation of clusters. The lock does not have to be held durring
    6658 * deallocation of clusters.
    67  */ 
     59 */
    6860static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6961
     
    7163 *
    7264 * @param bs            Buffer holding the boot sector for the file.
    73  * @param devmap_handle Device handle of the device with the file.
     65 * @param service_id    Service ID of the device with the file.
    7466 * @param firstc        First cluster to start the walk with.
    7567 * @param lastc         If non-NULL, output argument hodling the last cluster
     
    7769 * @param numc          If non-NULL, output argument holding the number of
    7870 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     71 * @param max_clusters  Maximum number of clusters to visit.
    8072 *
    8173 * @return              EOK on success or a negative error code.
    8274 */
    83 int 
    84 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    85     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    86 {
    87         block_t *b;
    88         uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     75int
     76fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
     77    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
     78{
     79        uint32_t clusters = 0;
     80        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     81        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9082        int rc;
    9183
     
    9991        }
    10092
    101         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    102                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    103                 unsigned fidx;  /* FAT1 entry index */
    104 
     93        while (clst < clst_last1 && clusters < max_clusters) {
    10594                assert(clst >= FAT_CLST_FIRST);
    10695                if (lastc)
    10796                        *lastc = clst;  /* remember the last cluster number */
    108                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    109                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     97
    11098                /* read FAT1 */
    111                 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
    112                     BLOCK_FLAGS_NONE);
    113                 if (rc != EOK)
    114                         return rc;
    115                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    116                 assert(clst != FAT_CLST_BAD);
    117                 rc = block_put(b);
    118                 if (rc != EOK)
    119                         return rc;
     99                rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst);
     100                if (rc != EOK)
     101                        return rc;
     102
     103                assert(clst != clst_bad);
    120104                clusters++;
    121105        }
    122106
    123         if (lastc && clst < FAT_CLST_LAST1)
     107        if (lastc && clst < clst_last1)
    124108                *lastc = clst;
    125109        if (numc)
     
    151135                return ELIMIT;
    152136
    153         if (nodep->firstc == FAT_CLST_ROOT)
     137        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
    154138                goto fall_through;
    155139
     
    160144                 * when fortunately we have the last cluster number cached.
    161145                 */
    162                 return block_get(block, nodep->idx->devmap_handle,
     146                return block_get(block, nodep->idx->service_id,
    163147                    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
    164148        }
     
    174158
    175159fall_through:
    176         rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
     160        rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
    177161            &currc, relbn, flags);
    178162        if (rc != EOK)
    179163                return rc;
    180        
     164
    181165        /*
    182166         * Update the "current" cluster cache.
     
    193177 * @param block         Pointer to a block pointer for storing result.
    194178 * @param bs            Buffer holding the boot sector of the file system.
    195  * @param devmap_handle Device handle of the file system.
     179 * @param service_id    Service ID handle of the file system.
    196180 * @param fcl           First cluster used by the file. Can be zero if the file
    197181 *                      is empty.
    198182 * @param clp           If not NULL, address where the cluster containing bn
    199183 *                      will be stored.
    200  *                      stored 
     184 *                      stored
    201185 * @param bn            Block number.
    202186 * @param flags         Flags passed to libblock.
     
    205189 */
    206190int
    207 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
     191_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
    208192    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    209193{
    210         uint16_t clusters;
    211         unsigned max_clusters;
     194        uint32_t clusters;
     195        uint32_t max_clusters;
    212196        fat_cluster_t c;
    213197        int rc;
     
    219203                return ELIMIT;
    220204
    221         if (fcl == FAT_CLST_ROOT) {
     205        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
    222206                /* root directory special case */
    223207                assert(bn < RDS(bs));
    224                 rc = block_get(block, devmap_handle,
     208                rc = block_get(block, service_id,
    225209                    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
    226210                return rc;
     
    228212
    229213        max_clusters = bn / SPC(bs);
    230         rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
     214        rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
    231215        if (rc != EOK)
    232216                return rc;
    233217        assert(clusters == max_clusters);
    234218
    235         rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
     219        rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
    236220
    237221        if (clp)
     
    253237 * @return              EOK on success or a negative error code.
    254238 */
    255 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
     239int
     240fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
    256241{
    257242        block_t *b;
     
    275260                        return rc;
    276261        }
    277        
     262
    278263        if (o >= pos)
    279264                return EOK;
    280        
     265
    281266        /* zero out the initial part of the new cluster chain */
    282267        for (o = boundary; o < pos; o += BPS(bs)) {
    283                 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
     268                rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
    284269                    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
    285270                if (rc != EOK)
     
    298283 *
    299284 * @param bs            Buffer holding the boot sector for the file system.
    300  * @param devmap_handle Device handle for the file system.
     285 * @param service_id    Service ID for the file system.
    301286 * @param clst          Cluster which to get.
    302287 * @param value         Output argument holding the value of the cluster.
     
    304289 * @return              EOK or a negative error code.
    305290 */
    306 int
    307 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     291static int
     292fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    308293    fat_cluster_t clst, fat_cluster_t *value)
    309294{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
    313 
    314         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     295        block_t *b, *b1;
     296        uint16_t byte1, byte2;
     297        aoff64_t offset;
     298        int rc;
     299
     300        offset = (clst + clst / 2);
     301        if (offset / BPS(bs) >= SF(bs))
     302                return ERANGE;
     303
     304        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     305            offset / BPS(bs), BLOCK_FLAGS_NONE);
    316306        if (rc != EOK)
    317307                return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
     308
     309        byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
     310        /* This cluster access spans a sector boundary. Check only for FAT12 */
     311        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     312                /* Is this the last sector of FAT? */
     313                if (offset / BPS(bs) < SF(bs)) {
     314                        /* No, read the next sector */
     315                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     316                            SF(bs) * fatno + offset / BPS(bs),
     317                            BLOCK_FLAGS_NONE);
     318                        if (rc != EOK) {
     319                                block_put(b);
     320                                return rc;
     321                        }
     322                        /*
     323                        * Combining value with last byte of current sector and
     324                        * first byte of next sector
     325                        */
     326                        byte2 = ((uint8_t*) b1->data)[0];
     327
     328                        rc = block_put(b1);
     329                        if (rc != EOK) {
     330                                block_put(b);
     331                                return rc;
     332                        }
     333                } else {
     334                        /* Yes. This is the last sector of FAT */
     335                        block_put(b);
     336                        return ERANGE;
     337                }
     338        } else
     339                byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];
     340
     341        *value = uint16_t_le2host(byte1 | (byte2 << 8));
     342        if (IS_ODD(clst))
     343                *value = (*value) >> 4;
     344        else
     345                *value = (*value) & FAT12_MASK;
     346       
    321347        rc = block_put(b);
    322        
     348
    323349        return rc;
    324350}
    325351
     352/** Get cluster from the first FAT.
     353 *
     354 * @param bs            Buffer holding the boot sector for the file system.
     355 * @param service_id    Service ID for the file system.
     356 * @param clst          Cluster which to get.
     357 * @param value         Output argument holding the value of the cluster.
     358 *
     359 * @return              EOK or a negative error code.
     360 */
     361static int
     362fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     363    fat_cluster_t clst, fat_cluster_t *value)
     364{
     365        block_t *b;
     366        aoff64_t offset;
     367        int rc;
     368
     369        offset = (clst * FAT16_CLST_SIZE);
     370
     371        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     372            offset / BPS(bs), BLOCK_FLAGS_NONE);
     373        if (rc != EOK)
     374                return rc;
     375
     376        *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
     377
     378        rc = block_put(b);
     379
     380        return rc;
     381}
     382
     383/** Get cluster from the first FAT.
     384 *
     385 * @param bs            Buffer holding the boot sector for the file system.
     386 * @param service_id    Service ID for the file system.
     387 * @param clst          Cluster which to get.
     388 * @param value         Output argument holding the value of the cluster.
     389 *
     390 * @return              EOK or a negative error code.
     391 */
     392static int
     393fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     394    fat_cluster_t clst, fat_cluster_t *value)
     395{
     396        block_t *b;
     397        aoff64_t offset;
     398        int rc;
     399
     400        offset = (clst * FAT32_CLST_SIZE);
     401
     402        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     403            offset / BPS(bs), BLOCK_FLAGS_NONE);
     404        if (rc != EOK)
     405                return rc;
     406
     407        *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) &
     408            FAT32_MASK;
     409
     410        rc = block_put(b);
     411
     412        return rc;
     413}
     414
     415
     416/** Get cluster from the first FAT.
     417 *
     418 * @param bs            Buffer holding the boot sector for the file system.
     419 * @param service_id    Service ID for the file system.
     420 * @param clst          Cluster which to get.
     421 * @param value         Output argument holding the value of the cluster.
     422 *
     423 * @return              EOK or a negative error code.
     424 */
     425int
     426fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     427    fat_cluster_t clst, fat_cluster_t *value)
     428{
     429        int rc;
     430
     431        assert(fatno < FATCNT(bs));
     432
     433        if (FAT_IS_FAT12(bs))
     434                rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);
     435        else if (FAT_IS_FAT16(bs))
     436                rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);
     437        else
     438                rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);
     439
     440        return rc;
     441}
     442
    326443/** Set cluster in one instance of FAT.
    327444 *
    328445 * @param bs            Buffer holding the boot sector for the file system.
    329  * @param devmap_handle Device handle for the file system.
     446 * @param service_id    Service ID for the file system.
    330447 * @param fatno         Number of the FAT instance where to make the change.
    331448 * @param clst          Cluster which is to be set.
     
    334451 * @return              EOK on success or a negative error code.
    335452 */
    336 int
    337 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     453static int
     454fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    338455    fat_cluster_t clst, fat_cluster_t value)
    339456{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342         int rc;
    343 
    344         assert(fatno < FATCNT(bs));
    345         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
     457        block_t *b, *b1 = NULL;
     458        aoff64_t offset;
     459        uint16_t byte1, byte2;
     460        int rc;
     461
     462        offset = (clst + clst / 2);
     463        if (offset / BPS(bs) >= SF(bs))
     464                return ERANGE;
     465       
     466        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     467            offset / BPS(bs), BLOCK_FLAGS_NONE);
    347468        if (rc != EOK)
    348469                return rc;
    349         cp = (fat_cluster_t *)b->data +
    350             clst % (BPS(bs) / sizeof(fat_cluster_t));
    351         *cp = host2uint16_t_le(value);
    352         b->dirty = true;                /* need to sync block */
     470
     471        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     472        bool border = false;
     473        /* This cluster access spans a sector boundary. */
     474        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     475                /* Is it the last sector of FAT? */
     476                if (offset / BPS(bs) < SF(bs)) {
     477                        /* No, read the next sector */
     478                        rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
     479                            SF(bs) * fatno + offset / BPS(bs),
     480                            BLOCK_FLAGS_NONE);
     481                        if (rc != EOK) {
     482                                block_put(b);
     483                                return rc;
     484                        }
     485                        /*
     486                         * Combining value with last byte of current sector and
     487                         * first byte of next sector
     488                         */
     489                        byte2 = ((uint8_t *) b1->data)[0];
     490                        border = true;
     491                } else {
     492                        /* Yes. This is the last sector of FAT */
     493                        block_put(b);
     494                        return ERANGE;
     495                }
     496        } else
     497                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs)) + 1];
     498
     499        if (IS_ODD(clst)) {
     500                byte1 &= 0x0f;
     501                byte2 = 0;
     502                value = (value << 4);
     503        } else {
     504                byte1 = 0;
     505                byte2 &= 0xf0;
     506                value &= FAT12_MASK;
     507        }
     508
     509        byte1 = byte1 | (value & 0xff);
     510        byte2 = byte2 | (value >> 8);
     511
     512        ((uint8_t *) b->data)[(offset % BPS(bs))] = byte1;
     513        if (border) {
     514                ((uint8_t *) b1->data)[0] = byte2;
     515
     516                b1->dirty = true;
     517                rc = block_put(b1);
     518                if (rc != EOK) {
     519                        block_put(b);
     520                        return rc;
     521                }
     522        } else
     523                ((uint8_t *) b->data)[(offset % BPS(bs)) + 1] = byte2;
     524
     525        b->dirty = true;        /* need to sync block */
    353526        rc = block_put(b);
     527
    354528        return rc;
    355529}
    356530
     531/** Set cluster in one instance of FAT.
     532 *
     533 * @param bs            Buffer holding the boot sector for the file system.
     534 * @param service_id    Service ID for the file system.
     535 * @param fatno         Number of the FAT instance where to make the change.
     536 * @param clst          Cluster which is to be set.
     537 * @param value         Value to set the cluster with.
     538 *
     539 * @return              EOK on success or a negative error code.
     540 */
     541static int
     542fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     543    fat_cluster_t clst, fat_cluster_t value)
     544{
     545        block_t *b;
     546        aoff64_t offset;
     547        int rc;
     548
     549        offset = (clst * FAT16_CLST_SIZE);
     550
     551        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     552            offset / BPS(bs), BLOCK_FLAGS_NONE);
     553        if (rc != EOK)
     554                return rc;
     555
     556        *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
     557
     558        b->dirty = true;        /* need to sync block */
     559        rc = block_put(b);
     560
     561        return rc;
     562}
     563
     564/** Set cluster in one instance of FAT.
     565 *
     566 * @param bs            Buffer holding the boot sector for the file system.
     567 * @param service_id    Service ID for the file system.
     568 * @param fatno         Number of the FAT instance where to make the change.
     569 * @param clst          Cluster which is to be set.
     570 * @param value         Value to set the cluster with.
     571 *
     572 * @return              EOK on success or a negative error code.
     573 */
     574static int
     575fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     576    fat_cluster_t clst, fat_cluster_t value)
     577{
     578        block_t *b;
     579        aoff64_t offset;
     580        int rc;
     581        fat_cluster_t temp;
     582
     583        offset = (clst * FAT32_CLST_SIZE);
     584
     585        rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
     586            offset / BPS(bs), BLOCK_FLAGS_NONE);
     587        if (rc != EOK)
     588                return rc;
     589
     590        temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
     591        temp &= 0xf0000000;
     592        temp |= (value & FAT32_MASK);
     593        *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
     594
     595        b->dirty = true;        /* need to sync block */
     596        rc = block_put(b);
     597
     598        return rc;
     599}
     600
     601/** Set cluster in one instance of FAT.
     602 *
     603 * @param bs            Buffer holding the boot sector for the file system.
     604 * @param service_id    Device service ID for the file system.
     605 * @param fatno         Number of the FAT instance where to make the change.
     606 * @param clst          Cluster which is to be set.
     607 * @param value         Value to set the cluster with.
     608 *
     609 * @return              EOK on success or a negative error code.
     610 */
     611int
     612fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     613    fat_cluster_t clst, fat_cluster_t value)
     614{
     615        int rc;
     616
     617        assert(fatno < FATCNT(bs));
     618
     619        if (FAT_IS_FAT12(bs))
     620                rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value);
     621        else if (FAT_IS_FAT16(bs))
     622                rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value);
     623        else
     624                rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value);
     625
     626        return rc;
     627}
     628
    357629/** Replay the allocatoin of clusters in all shadow instances of FAT.
    358630 *
    359631 * @param bs            Buffer holding the boot sector of the file system.
    360  * @param devmap_handle Device handle of the file system.
     632 * @param service_id    Service ID of the file system.
    361633 * @param lifo          Chain of allocated clusters.
    362634 * @param nclsts        Number of clusters in the lifo chain.
     
    364636 * @return              EOK on success or a negative error code.
    365637 */
    366 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
     638int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
    367639    fat_cluster_t *lifo, unsigned nclsts)
    368640{
    369641        uint8_t fatno;
    370642        unsigned c;
    371         int rc;
    372 
    373         for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
     643        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     644        int rc;
     645
     646        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
    374647                for (c = 0; c < nclsts; c++) {
    375                         rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     648                        rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
     649                            c == 0 ? clst_last1 : lifo[c - 1]);
    377650                        if (rc != EOK)
    378651                                return rc;
     
    391664 *
    392665 * @param bs            Buffer holding the boot sector of the file system.
    393  * @param devmap_handle Device handle of the file system.
     666 * @param service_id    Device service ID of the file system.
    394667 * @param nclsts        Number of clusters to allocate.
    395668 * @param mcl           Output parameter where the first cluster in the chain
     
    401674 */
    402675int
    403 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
     676fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
    404677    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405678{
    406         block_t *blk;
    407         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    408         unsigned found = 0;     /* top of the free cluster number stack */
    409         unsigned b, c, cl;
    410         int rc;
     679        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     680        unsigned found = 0;     /* top of the free cluster number stack */
     681        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     682        int rc = EOK;
    411683
    412684        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
     
    418690         */
    419691        fibril_mutex_lock(&fat_alloc_lock);
    420         for (b = 0, cl = 0; b < SF(bs); b++) {
    421                 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
    422                     BLOCK_FLAGS_NONE);
    423                 if (rc != EOK)
    424                         goto error;
    425                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
     692        for (clst = FAT_CLST_FIRST; clst < CC(bs) + 2 && found < nclsts;
     693            clst++) {
     694                rc = fat_get_cluster(bs, service_id, FAT1, clst, &value);
     695                if (rc != EOK)
     696                        break;
     697
     698                if (value == FAT_CLST_RES0) {
    426699                        /*
    427                          * Check if the entire cluster is physically there.
    428                          * This check becomes necessary when the file system is
    429                          * created with fewer total sectors than how many is
    430                          * inferred from the size of the file allocation table
    431                          * or when the last cluster ends beyond the end of the
    432                          * device.
     700                         * The cluster is free. Put it into our stack
     701                         * of found clusters and mark it as non-free.
    433702                         */
    434                         if ((cl >= FAT_CLST_FIRST) &&
    435                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    436                                 rc = block_put(blk);
    437                                 if (rc != EOK)
    438                                         goto error;
    439                                 goto out;
    440                         }
    441 
    442                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    443                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    444                                 /*
    445                                  * The cluster is free. Put it into our stack
    446                                  * of found clusters and mark it as non-free.
    447                                  */
    448                                 lifo[found] = cl;
    449                                 *clst = (found == 0) ?
    450                                     host2uint16_t_le(FAT_CLST_LAST1) :
    451                                     host2uint16_t_le(lifo[found - 1]);
    452                                 blk->dirty = true;      /* need to sync block */
    453                                 if (++found == nclsts) {
    454                                         /* we are almost done */
    455                                         rc = block_put(blk);
    456                                         if (rc != EOK)
    457                                                 goto error;
    458                                         /* update the shadow copies of FAT */
    459                                         rc = fat_alloc_shadow_clusters(bs,
    460                                             devmap_handle, lifo, nclsts);
    461                                         if (rc != EOK)
    462                                                 goto error;
    463                                         *mcl = lifo[found - 1];
    464                                         *lcl = lifo[0];
    465                                         free(lifo);
    466                                         fibril_mutex_unlock(&fat_alloc_lock);
    467                                         return EOK;
    468                                 }
    469                         }
     703                        lifo[found] = clst;
     704                        rc = fat_set_cluster(bs, service_id, FAT1, clst,
     705                            (found == 0) ?  clst_last1 : lifo[found - 1]);
     706                        if (rc != EOK)
     707                                break;
     708
     709                        found++;
    470710                }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     711        }
     712
     713        if (rc == EOK && found == nclsts) {
     714                rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts);
     715                if (rc == EOK) {
     716                        *mcl = lifo[found - 1];
     717                        *lcl = lifo[0];
     718                        free(lifo);
    474719                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
     720                        return EOK;
    477721                }
    478722        }
    479 out:
     723
     724        /* If something wrong - free the clusters */
     725        while (found--) {
     726                (void) fat_set_cluster(bs, service_id, FAT1, lifo[found],
     727                    FAT_CLST_RES0);
     728        }
     729
     730        free(lifo);
    480731        fibril_mutex_unlock(&fat_alloc_lock);
    481732
    482         /*
    483          * We could not find enough clusters. Now we need to free the clusters
    484          * we have allocated so far.
    485          */
    486         while (found--) {
    487                 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    488                     FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
    495         free(lifo);
    496733        return ENOSPC;
    497734}
     
    500737 *
    501738 * @param bs            Buffer hodling the boot sector of the file system.
    502  * @param devmap_handle Device handle of the file system.
     739 * @param service_id    Device service ID of the file system.
    503740 * @param firstc        First cluster in the chain which is to be freed.
    504741 *
     
    506743 */
    507744int
    508 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
     745fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
    509746{
    510747        unsigned fatno;
    511         fat_cluster_t nextc;
     748        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512749        int rc;
    513750
    514751        /* Mark all clusters in the chain as free in all copies of FAT. */
    515         while (firstc < FAT_CLST_LAST1) {
    516                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
    517                 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    518                 if (rc != EOK)
    519                         return rc;
    520                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    521                         rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
     752        while (firstc < FAT_CLST_LAST1(bs)) {
     753                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
     754
     755                rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
     756                if (rc != EOK)
     757                        return rc;
     758
     759                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     760                        rc = fat_set_cluster(bs, service_id, fatno, firstc,
    522761                            FAT_CLST_RES0);
    523762                        if (rc != EOK)
     
    540779 * @return              EOK on success or a negative error code.
    541780 */
    542 int
    543 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
     781int fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl,
    544782    fat_cluster_t lcl)
    545783{
    546         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     784        service_id_t service_id = nodep->idx->service_id;
    547785        fat_cluster_t lastc;
    548786        uint8_t fatno;
     
    558796                        nodep->lastc_cached_valid = false;
    559797                } else {
    560                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
    561                             &lastc, NULL, (uint16_t) -1);
     798                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
     799                            &lastc, NULL, (uint32_t) -1);
    562800                        if (rc != EOK)
    563801                                return rc;
    564802                }
    565803
    566                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
    568                             lastc, mcl);
     804                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     805                        rc = fat_set_cluster(bs, nodep->idx->service_id,
     806                            fatno, lastc, mcl);
    569807                        if (rc != EOK)
    570808                                return rc;
     
    590828int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591829{
    592         int rc;
    593         devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     830        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     831        int rc;
     832        service_id_t service_id = nodep->idx->service_id;
    594833
    595834        /*
     
    602841        if (lcl == FAT_CLST_RES0) {
    603842                /* The node will have zero size and no clusters allocated. */
    604                 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
     843                rc = fat_free_clusters(bs, service_id, nodep->firstc);
    605844                if (rc != EOK)
    606845                        return rc;
     
    611850                unsigned fatno;
    612851
    613                 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
     852                rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
    614853                if (rc != EOK)
    615854                        return rc;
    616855
    617856                /* Terminate the cluster chain in all copies of FAT. */
    618                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    619                         rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    620                             FAT_CLST_LAST1);
     857                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     858                        rc = fat_set_cluster(bs, service_id, fatno, lcl,
     859                            clst_last1);
    621860                        if (rc != EOK)
    622861                                return rc;
     
    624863
    625864                /* Free all following clusters. */
    626                 rc = fat_free_clusters(bs, devmap_handle, nextc);
     865                rc = fat_free_clusters(bs, service_id, nextc);
    627866                if (rc != EOK)
    628867                        return rc;
     
    639878
    640879int
    641 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
     880fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
    642881{
    643882        int i;
     
    646885
    647886        for (i = 0; i < SPC(bs); i++) {
    648                 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
     887                rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
    649888                    BLOCK_FLAGS_NOREAD);
    650889                if (rc != EOK)
     
    666905 * does not contain a fat file system.
    667906 */
    668 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
     907int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
    669908{
    670909        fat_cluster_t e0, e1;
     
    673912
    674913        /* Check number of FATs. */
    675         if (bs->fatcnt == 0)
     914        if (FATCNT(bs) == 0)
    676915                return ENOTSUP;
    677916
    678917        /* Check total number of sectors. */
    679 
    680         if (bs->totsec16 == 0 && bs->totsec32 == 0)
     918        if (TS(bs) == 0)
    681919                return ENOTSUP;
    682920
    683921        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     922            bs->totsec16 != bs->totsec32)
    685923                return ENOTSUP;
    686924
     
    690928
    691929        /* Check number of sectors per FAT. */
    692         if (bs->sec_per_fat == 0)
     930        if (SF(bs) == 0)
    693931                return ENOTSUP;
    694932
     
    700938         * sanitized to support file systems with this property.
    701939         */
    702         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    703             uint16_t_le2host(bs->bps) != 0)
     940        if (!FAT_IS_FAT32(bs) &&
     941            (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
    704942                return ENOTSUP;
    705943
    706944        /* Check signature of each FAT. */
    707 
    708         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
    709                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
     945        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
     946                rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
    710947                if (rc != EOK)
    711948                        return EIO;
    712949
    713                 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
     950                rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
    714951                if (rc != EOK)
    715952                        return EIO;
    716953
    717                 /* Check that first byte of FAT contains the media descriptor. */
     954                /*
     955                 * Check that first byte of FAT contains the media descriptor.
     956                 */
    718957                if ((e0 & 0xff) != bs->mdesc)
    719958                        return ENOTSUP;
     
    723962                 * set to one.
    724963                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     964                if (!FAT_IS_FAT12(bs) &&
     965                    ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
    726966                        return ENOTSUP;
    727967        }
     
    732972/**
    733973 * @}
    734  */ 
     974 */
  • uspace/srv/fs/fat/fat_fat.h

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334#ifndef FAT_FAT_FAT_H_
     
    4041#define FAT1            0
    4142
    42 #define FAT_CLST_RES0   0x0000
    43 #define FAT_CLST_RES1   0x0001
    44 #define FAT_CLST_FIRST  0x0002
    45 #define FAT_CLST_BAD    0xfff7
    46 #define FAT_CLST_LAST1  0xfff8
    47 #define FAT_CLST_LAST8  0xffff
     43#define FAT_CLST_RES0     0
     44#define FAT_CLST_RES1     1
     45#define FAT_CLST_FIRST    2
     46
     47#define FAT32_CLST_BAD    0x0ffffff7
     48#define FAT32_CLST_LAST1  0x0ffffff8
     49#define FAT32_CLST_LAST8  0x0fffffff
     50
     51#define FAT12_MASK        0x0fff
     52#define FAT16_MASK        0xffff
     53#define FAT32_MASK        0x0fffffff
     54
     55#define FAT12_CLST_MAX    4085
     56#define FAT16_CLST_MAX    65525
     57
     58/* Size in bytes for cluster value of FAT */
     59#define FAT12_CLST_SIZE   2
     60#define FAT16_CLST_SIZE   2
     61#define FAT32_CLST_SIZE   4
    4862
    4963/* internally used to mark root directory's parent */
     
    5266#define FAT_CLST_ROOT           FAT_CLST_RES1
    5367
     68/*
     69 * Convenience macros for computing some frequently used values from the
     70 * primitive boot sector members.
     71 */
     72#define RDS(bs)   ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     73                   (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     74#define SSA(bs)   (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     75#define DS(bs)    (TS(bs) - SSA(bs))
     76#define CC(bs)    (DS(bs) / SPC(bs))
     77
     78#define CLBN2PBN(bs, cl, bn) \
     79        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     80
     81#define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
     82#define FAT_IS_FAT16(bs) \
     83    ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
     84#define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
     85
     86#define FAT_CLST_SIZE(bs) \
     87    (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
     88
     89#define FAT_MASK(bs) \
     90    (FAT_IS_FAT12(bs) ? FAT12_MASK : \
     91    (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
     92
     93#define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
     94#define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
     95#define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
     96
     97#define FAT_ROOT_CLST(bs) \
     98    (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
     99    FAT_CLST_ROOT)
     100
    54101/* forward declarations */
    55102struct block;
     
    57104struct fat_bs;
    58105
    59 typedef uint16_t fat_cluster_t;
     106typedef uint32_t fat_cluster_t;
    60107
    61 #define fat_clusters_get(numc, bs, dh, fc) \
    62     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
    63 extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t,
    64     fat_cluster_t *, uint16_t *, uint16_t);
     108#define fat_clusters_get(numc, bs, sid, fc) \
     109    fat_cluster_walk((bs), (sid), (fc), NULL, (numc), (uint32_t) -1)
     110extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
     111    fat_cluster_t *, uint32_t *, uint32_t);
    65112
    66113extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
    67114    aoff64_t, int);
    68 extern int _fat_block_get(block_t **, struct fat_bs *, devmap_handle_t,
     115extern int _fat_block_get(block_t **, struct fat_bs *, service_id_t,
    69116    fat_cluster_t, fat_cluster_t *, aoff64_t, int);
    70117
     
    73120extern int fat_chop_clusters(struct fat_bs *, struct fat_node *,
    74121    fat_cluster_t);
    75 extern int fat_alloc_clusters(struct fat_bs *, devmap_handle_t, unsigned,
     122extern int fat_alloc_clusters(struct fat_bs *, service_id_t, unsigned,
    76123    fat_cluster_t *, fat_cluster_t *);
    77 extern int fat_free_clusters(struct fat_bs *, devmap_handle_t, fat_cluster_t);
    78 extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t,
     124extern int fat_free_clusters(struct fat_bs *, service_id_t, fat_cluster_t);
     125extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t,
    79126    fat_cluster_t *, unsigned);
    80 extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned,
     127extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned,
    81128    fat_cluster_t, fat_cluster_t *);
    82 extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned,
     129extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned,
    83130    fat_cluster_t, fat_cluster_t);
    84131extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
    85132    aoff64_t);
    86 extern int fat_zero_cluster(struct fat_bs *, devmap_handle_t, fat_cluster_t);
    87 extern int fat_sanity_check(struct fat_bs *, devmap_handle_t);
     133extern int fat_zero_cluster(struct fat_bs *, service_id_t, fat_cluster_t);
     134extern int fat_sanity_check(struct fat_bs *, service_id_t);
    88135
    89136#endif
  • uspace/srv/fs/fat/fat_idx.c

    rd2c67e7 r8ff0bd2  
    5959typedef struct {
    6060        link_t          link;
    61         devmap_handle_t devmap_handle;
     61        service_id_t    service_id;
    6262
    6363        /** Next unassigned index. */
    64         fs_index_t      next;
     64        fs_index_t next;
    6565        /** Number of remaining unassigned indices. */
    66         uint64_t        remaining;
     66        uint64_t remaining;
    6767
    6868        /** Sorted list of intervals of freed indices. */
    69         link_t          freed_head;
     69        list_t freed_list;
    7070} unused_t;
    7171
     
    7474
    7575/** List of unused structures. */
    76 static LIST_INITIALIZE(unused_head);
    77 
    78 static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)
     76static LIST_INITIALIZE(unused_list);
     77
     78static void unused_initialize(unused_t *u, service_id_t service_id)
    7979{
    8080        link_initialize(&u->link);
    81         u->devmap_handle = devmap_handle;
     81        u->service_id = service_id;
    8282        u->next = 0;
    8383        u->remaining = ((uint64_t)((fs_index_t)-1)) + 1;
    84         list_initialize(&u->freed_head);
    85 }
    86 
    87 static unused_t *unused_find(devmap_handle_t devmap_handle, bool lock)
     84        list_initialize(&u->freed_list);
     85}
     86
     87static unused_t *unused_find(service_id_t service_id, bool lock)
    8888{
    8989        unused_t *u;
    90         link_t *l;
    9190
    9291        if (lock)
    9392                fibril_mutex_lock(&unused_lock);
    94         for (l = unused_head.next; l != &unused_head; l = l->next) {
     93
     94        list_foreach(unused_list, l) {
    9595                u = list_get_instance(l, unused_t, link);
    96                 if (u->devmap_handle == devmap_handle)
     96                if (u->service_id == service_id)
    9797                        return u;
    9898        }
     99       
    99100        if (lock)
    100101                fibril_mutex_unlock(&unused_lock);
     
    107108/**
    108109 * Global hash table of all used fat_idx_t structures.
    109  * The index structures are hashed by the devmap_handle, parent node's first
     110 * The index structures are hashed by the service_id, parent node's first
    110111 * cluster and index within the parent directory.
    111112 */
     
    115116#define UPH_BUCKETS     (1 << UPH_BUCKETS_LOG)
    116117
    117 #define UPH_DH_KEY      0
     118#define UPH_SID_KEY     0
    118119#define UPH_PFC_KEY     1
    119120#define UPH_PDI_KEY     2
     
    121122static hash_index_t pos_hash(unsigned long key[])
    122123{
    123         devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
     124        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    124125        fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
    125126        unsigned pdi = (unsigned)key[UPH_PDI_KEY];
     
    141142        h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
    142143            (UPH_BUCKETS_LOG / 2);
    143         h |= (devmap_handle & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
     144        h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
    144145            (3 * (UPH_BUCKETS_LOG / 4));
    145146
     
    149150static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
    150151{
    151         devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
     152        service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
    152153        fat_cluster_t pfc;
    153154        unsigned pdi;
     
    156157        switch (keys) {
    157158        case 1:
    158                 return (devmap_handle == fidx->devmap_handle);
     159                return (service_id == fidx->service_id);
    159160        case 3:
    160161                pfc = (fat_cluster_t) key[UPH_PFC_KEY];
    161162                pdi = (unsigned) key[UPH_PDI_KEY];
    162                 return (devmap_handle == fidx->devmap_handle) && (pfc == fidx->pfc) &&
     163                return (service_id == fidx->service_id) && (pfc == fidx->pfc) &&
    163164                    (pdi == fidx->pdi);
    164165        default:
     
    182183/**
    183184 * Global hash table of all used fat_idx_t structures.
    184  * The index structures are hashed by the devmap_handle and index.
     185 * The index structures are hashed by the service_id and index.
    185186 */
    186187static hash_table_t ui_hash;
     
    189190#define UIH_BUCKETS     (1 << UIH_BUCKETS_LOG)
    190191
    191 #define UIH_DH_KEY      0
     192#define UIH_SID_KEY     0
    192193#define UIH_INDEX_KEY   1
    193194
    194195static hash_index_t idx_hash(unsigned long key[])
    195196{
    196         devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
     197        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    197198        fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
    198199
    199200        hash_index_t h;
    200201
    201         h = devmap_handle & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
     202        h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
    202203        h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
    203204            (UIH_BUCKETS_LOG / 2);
     
    208209static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
    209210{
    210         devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
     211        service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
    211212        fs_index_t index;
    212213        fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
     
    214215        switch (keys) {
    215216        case 1:
    216                 return (devmap_handle == fidx->devmap_handle);
     217                return (service_id == fidx->service_id);
    217218        case 2:
    218219                index = (fs_index_t) key[UIH_INDEX_KEY];
    219                 return (devmap_handle == fidx->devmap_handle) &&
     220                return (service_id == fidx->service_id) &&
    220221                    (index == fidx->index);
    221222        default:
     
    240241
    241242/** Allocate a VFS index which is not currently in use. */
    242 static bool fat_index_alloc(devmap_handle_t devmap_handle, fs_index_t *index)
     243static bool fat_index_alloc(service_id_t service_id, fs_index_t *index)
    243244{
    244245        unused_t *u;
    245246       
    246247        assert(index);
    247         u = unused_find(devmap_handle, true);
     248        u = unused_find(service_id, true);
    248249        if (!u)
    249250                return false;   
    250251
    251         if (list_empty(&u->freed_head)) {
     252        if (list_empty(&u->freed_list)) {
    252253                if (u->remaining) {
    253254                        /*
     
    262263        } else {
    263264                /* There are some freed indices which we can reuse. */
    264                 freed_t *f = list_get_instance(u->freed_head.next, freed_t,
    265                     link);
     265                freed_t *f = list_get_instance(list_first(&u->freed_list),
     266                    freed_t, link);
    266267                *index = f->first;
    267268                if (f->first++ == f->last) {
     
    302303
    303304/** Free a VFS index, which is no longer in use. */
    304 static void fat_index_free(devmap_handle_t devmap_handle, fs_index_t index)
     305static void fat_index_free(service_id_t service_id, fs_index_t index)
    305306{
    306307        unused_t *u;
    307308
    308         u = unused_find(devmap_handle, true);
     309        u = unused_find(service_id, true);
    309310        assert(u);
    310311
     
    320321                link_t *lnk;
    321322                freed_t *n;
    322                 for (lnk = u->freed_head.next; lnk != &u->freed_head;
     323                for (lnk = u->freed_list.head.next; lnk != &u->freed_list.head;
    323324                    lnk = lnk->next) {
    324325                        freed_t *f = list_get_instance(lnk, freed_t, link);
    325326                        if (f->first == index + 1) {
    326327                                f->first--;
    327                                 if (lnk->prev != &u->freed_head)
     328                                if (lnk->prev != &u->freed_list.head)
    328329                                        try_coalesce_intervals(lnk->prev, lnk,
    329330                                            lnk);
     
    333334                        if (f->last == index - 1) {
    334335                                f->last++;
    335                                 if (lnk->next != &u->freed_head)
     336                                if (lnk->next != &u->freed_list.head)
    336337                                        try_coalesce_intervals(lnk, lnk->next,
    337338                                            lnk);
     
    359360                n->first = index;
    360361                n->last = index;
    361                 list_append(&n->link, &u->freed_head);
     362                list_append(&n->link, &u->freed_list);
    362363        }
    363364        fibril_mutex_unlock(&unused_lock);
    364365}
    365366
    366 static int fat_idx_create(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
     367static int fat_idx_create(fat_idx_t **fidxp, service_id_t service_id)
    367368{
    368369        fat_idx_t *fidx;
     
    371372        if (!fidx)
    372373                return ENOMEM;
    373         if (!fat_index_alloc(devmap_handle, &fidx->index)) {
     374        if (!fat_index_alloc(service_id, &fidx->index)) {
    374375                free(fidx);
    375376                return ENOSPC;
     
    379380        link_initialize(&fidx->uih_link);
    380381        fibril_mutex_initialize(&fidx->lock);
    381         fidx->devmap_handle = devmap_handle;
     382        fidx->service_id = service_id;
    382383        fidx->pfc = FAT_CLST_RES0;      /* no parent yet */
    383384        fidx->pdi = 0;
     
    388389}
    389390
    390 int fat_idx_get_new(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
     391int fat_idx_get_new(fat_idx_t **fidxp, service_id_t service_id)
    391392{
    392393        fat_idx_t *fidx;
     
    394395
    395396        fibril_mutex_lock(&used_lock);
    396         rc = fat_idx_create(&fidx, devmap_handle);
     397        rc = fat_idx_create(&fidx, service_id);
    397398        if (rc != EOK) {
    398399                fibril_mutex_unlock(&used_lock);
     
    401402               
    402403        unsigned long ikey[] = {
    403                 [UIH_DH_KEY] = devmap_handle,
     404                [UIH_SID_KEY] = service_id,
    404405                [UIH_INDEX_KEY] = fidx->index,
    405406        };
     
    414415
    415416fat_idx_t *
    416 fat_idx_get_by_pos(devmap_handle_t devmap_handle, fat_cluster_t pfc, unsigned pdi)
     417fat_idx_get_by_pos(service_id_t service_id, fat_cluster_t pfc, unsigned pdi)
    417418{
    418419        fat_idx_t *fidx;
    419420        link_t *l;
    420421        unsigned long pkey[] = {
    421                 [UPH_DH_KEY] = devmap_handle,
     422                [UPH_SID_KEY] = service_id,
    422423                [UPH_PFC_KEY] = pfc,
    423424                [UPH_PDI_KEY] = pdi,
     
    431432                int rc;
    432433
    433                 rc = fat_idx_create(&fidx, devmap_handle);
     434                rc = fat_idx_create(&fidx, service_id);
    434435                if (rc != EOK) {
    435436                        fibril_mutex_unlock(&used_lock);
     
    438439               
    439440                unsigned long ikey[] = {
    440                         [UIH_DH_KEY] = devmap_handle,
     441                        [UIH_SID_KEY] = service_id,
    441442                        [UIH_INDEX_KEY] = fidx->index,
    442443                };
     
    457458{
    458459        unsigned long pkey[] = {
    459                 [UPH_DH_KEY] = idx->devmap_handle,
     460                [UPH_SID_KEY] = idx->service_id,
    460461                [UPH_PFC_KEY] = idx->pfc,
    461462                [UPH_PDI_KEY] = idx->pdi,
     
    470471{
    471472        unsigned long pkey[] = {
    472                 [UPH_DH_KEY] = idx->devmap_handle,
     473                [UPH_SID_KEY] = idx->service_id,
    473474                [UPH_PFC_KEY] = idx->pfc,
    474475                [UPH_PDI_KEY] = idx->pdi,
     
    481482
    482483fat_idx_t *
    483 fat_idx_get_by_index(devmap_handle_t devmap_handle, fs_index_t index)
     484fat_idx_get_by_index(service_id_t service_id, fs_index_t index)
    484485{
    485486        fat_idx_t *fidx = NULL;
    486487        link_t *l;
    487488        unsigned long ikey[] = {
    488                 [UIH_DH_KEY] = devmap_handle,
     489                [UIH_SID_KEY] = service_id,
    489490                [UIH_INDEX_KEY] = index,
    490491        };
     
    508509{
    509510        unsigned long ikey[] = {
    510                 [UIH_DH_KEY] = idx->devmap_handle,
     511                [UIH_SID_KEY] = idx->service_id,
    511512                [UIH_INDEX_KEY] = idx->index,
    512513        };
    513         devmap_handle_t devmap_handle = idx->devmap_handle;
     514        service_id_t service_id = idx->service_id;
    514515        fs_index_t index = idx->index;
    515516
     
    525526        fibril_mutex_unlock(&used_lock);
    526527        /* Release the VFS index. */
    527         fat_index_free(devmap_handle, index);
     528        fat_index_free(service_id, index);
    528529        /* The index structure itself is freed in idx_remove_callback(). */
    529530}
     
    547548}
    548549
    549 int fat_idx_init_by_devmap_handle(devmap_handle_t devmap_handle)
     550int fat_idx_init_by_service_id(service_id_t service_id)
    550551{
    551552        unused_t *u;
     
    555556        if (!u)
    556557                return ENOMEM;
    557         unused_initialize(u, devmap_handle);
     558        unused_initialize(u, service_id);
    558559        fibril_mutex_lock(&unused_lock);
    559         if (!unused_find(devmap_handle, false)) {
    560                 list_append(&u->link, &unused_head);
     560        if (!unused_find(service_id, false)) {
     561                list_append(&u->link, &unused_list);
    561562        } else {
    562563                free(u);
     
    567568}
    568569
    569 void fat_idx_fini_by_devmap_handle(devmap_handle_t devmap_handle)
     570void fat_idx_fini_by_service_id(service_id_t service_id)
    570571{
    571572        unsigned long ikey[] = {
    572                 [UIH_DH_KEY] = devmap_handle
     573                [UIH_SID_KEY] = service_id
    573574        };
    574575        unsigned long pkey[] = {
    575                 [UPH_DH_KEY] = devmap_handle
     576                [UPH_SID_KEY] = service_id
    576577        };
    577578
     
    589590         * Free the unused and freed structures for this instance.
    590591         */
    591         unused_t *u = unused_find(devmap_handle, true);
     592        unused_t *u = unused_find(service_id, true);
    592593        assert(u);
    593594        list_remove(&u->link);
    594595        fibril_mutex_unlock(&unused_lock);
    595596
    596         while (!list_empty(&u->freed_head)) {
     597        while (!list_empty(&u->freed_list)) {
    597598                freed_t *f;
    598                 f = list_get_instance(u->freed_head.next, freed_t, link);
     599                f = list_get_instance(list_first(&u->freed_list), freed_t, link);
    599600                list_remove(&f->link);
    600601                free(f);
  • uspace/srv/fs/fat/fat_ops.c

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    3940#include "fat_dentry.h"
    4041#include "fat_fat.h"
     42#include "fat_directory.h"
    4143#include "../../vfs/vfs.h"
    4244#include <libfs.h>
    4345#include <libblock.h>
    4446#include <ipc/services.h>
    45 #include <ipc/devmap.h>
     47#include <ipc/loc.h>
    4648#include <macros.h>
    4749#include <async.h>
     
    5658#include <align.h>
    5759#include <malloc.h>
     60#include <str.h>
    5861
    5962#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    6770
    6871/** List of cached free FAT nodes. */
    69 static LIST_INITIALIZE(ffn_head);
     72static LIST_INITIALIZE(ffn_list);
    7073
    7174/*
    7275 * Forward declarations of FAT libfs operations.
    7376 */
    74 static int fat_root_get(fs_node_t **, devmap_handle_t);
     77static int fat_root_get(fs_node_t **, service_id_t);
    7578static int fat_match(fs_node_t **, fs_node_t *, const char *);
    76 static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
     79static int fat_node_get(fs_node_t **, service_id_t, fs_index_t);
    7780static int fat_node_open(fs_node_t *);
    7881static int fat_node_put(fs_node_t *);
    79 static int fat_create_node(fs_node_t **, devmap_handle_t, int);
     82static int fat_create_node(fs_node_t **, service_id_t, int);
    8083static int fat_destroy_node(fs_node_t *);
    8184static int fat_link(fs_node_t *, fs_node_t *, const char *);
     
    8588static aoff64_t fat_size_get(fs_node_t *);
    8689static unsigned fat_lnkcnt_get(fs_node_t *);
    87 static char fat_plb_get_char(unsigned);
    8890static bool fat_is_directory(fs_node_t *);
    8991static bool fat_is_file(fs_node_t *node);
    90 static devmap_handle_t fat_device_get(fs_node_t *node);
     92static service_id_t fat_device_get(fs_node_t *node);
    9193
    9294/*
     
    105107        node->dirty = false;
    106108        node->lastc_cached_valid = false;
    107         node->lastc_cached_value = FAT_CLST_LAST1;
     109        node->lastc_cached_value = 0;
    108110        node->currc_cached_valid = false;
    109111        node->currc_cached_bn = 0;
    110         node->currc_cached_value = FAT_CLST_LAST1;
     112        node->currc_cached_value = 0;
    111113}
    112114
     
    117119        fat_dentry_t *d;
    118120        int rc;
    119        
     121
    120122        assert(node->dirty);
    121123
    122         bs = block_bb_get(node->idx->devmap_handle);
    123        
     124        bs = block_bb_get(node->idx->service_id);
     125
    124126        /* Read the block that contains the dentry of interest. */
    125         rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     127        rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
    126128            NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    127129            BLOCK_FLAGS_NONE);
     
    137139                d->attr = FAT_ATTR_SUBDIR;
    138140        }
    139        
     141
    140142        /* TODO: update other fields? (e.g time fields) */
    141        
     143
    142144        b->dirty = true;                /* need to sync block */
    143145        rc = block_put(b);
     
    145147}
    146148
    147 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
    148 {
    149         link_t *lnk;
     149static int fat_node_fini_by_service_id(service_id_t service_id)
     150{
    150151        fat_node_t *nodep;
    151152        int rc;
     
    159160restart:
    160161        fibril_mutex_lock(&ffn_mutex);
    161         for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
     162        list_foreach(ffn_list, lnk) {
    162163                nodep = list_get_instance(lnk, fat_node_t, ffn_link);
    163164                if (!fibril_mutex_trylock(&nodep->lock)) {
     
    170171                        goto restart;
    171172                }
    172                 if (nodep->idx->devmap_handle != devmap_handle) {
     173                if (nodep->idx->service_id != service_id) {
    173174                        fibril_mutex_unlock(&nodep->idx->lock);
    174175                        fibril_mutex_unlock(&nodep->lock);
     
    196197                free(nodep);
    197198
    198                 /* Need to restart because we changed the ffn_head list. */
     199                /* Need to restart because we changed ffn_list. */
    199200                goto restart;
    200201        }
     
    211212
    212213        fibril_mutex_lock(&ffn_mutex);
    213         if (!list_empty(&ffn_head)) {
     214        if (!list_empty(&ffn_list)) {
    214215                /* Try to use a cached free node structure. */
    215216                fat_idx_t *idxp_tmp;
    216                 nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
     217                nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
     218                    ffn_link);
    217219                if (!fibril_mutex_trylock(&nodep->lock))
    218220                        goto skip_cache;
     
    256258        fn->data = nodep;
    257259        nodep->bp = fn;
    258        
     260
    259261        *nodepp = nodep;
    260262        return EOK;
     
    292294         * We must instantiate the node from the file system.
    293295         */
    294        
     296
    295297        assert(idxp->pfc);
    296298
     
    299301                return rc;
    300302
    301         bs = block_bb_get(idxp->devmap_handle);
     303        bs = block_bb_get(idxp->service_id);
    302304
    303305        /* Read the block that contains the dentry of interest. */
    304         rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL,
     306        rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL,
    305307            (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    306308        if (rc != EOK) {
     
    310312
    311313        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     314        if (FAT_IS_FAT32(bs)) {
     315                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     316                    (uint16_t_le2host(d->firstc_hi) << 16);
     317        } else
     318                nodep->firstc = uint16_t_le2host(d->firstc);
     319
    312320        if (d->attr & FAT_ATTR_SUBDIR) {
    313                 /* 
     321                /*
    314322                 * The only directory which does not have this bit set is the
    315323                 * root directory itself. The root directory node is handled
     
    317325                 */
    318326                nodep->type = FAT_DIRECTORY;
     327
    319328                /*
    320329                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    322331                 * size of the directory by walking the FAT.
    323332                 */
    324                 uint16_t clusters;
    325                 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
    326                     uint16_t_le2host(d->firstc));
     333                uint32_t clusters;
     334                rc = fat_clusters_get(&clusters, bs, idxp->service_id,
     335                    nodep->firstc);
    327336                if (rc != EOK) {
    328337                        (void) block_put(b);
     
    335344                nodep->size = uint32_t_le2host(d->size);
    336345        }
    337         nodep->firstc = uint16_t_le2host(d->firstc);
     346
    338347        nodep->lnkcnt = 1;
    339348        nodep->refcnt = 1;
     
    357366 */
    358367
    359 int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
    360 {
    361         return fat_node_get(rfn, devmap_handle, 0);
     368int fat_root_get(fs_node_t **rfn, service_id_t service_id)
     369{
     370        return fat_node_get(rfn, service_id, 0);
    362371}
    363372
    364373int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    365374{
    366         fat_bs_t *bs;
    367375        fat_node_t *parentp = FAT_NODE(pfn);
    368         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    369         unsigned i, j;
    370         unsigned blocks;
     376        char name[FAT_LFN_NAME_SIZE];
    371377        fat_dentry_t *d;
    372         devmap_handle_t devmap_handle;
    373         block_t *b;
     378        service_id_t service_id;
    374379        int rc;
    375380
    376381        fibril_mutex_lock(&parentp->idx->lock);
    377         devmap_handle = parentp->idx->devmap_handle;
     382        service_id = parentp->idx->service_id;
    378383        fibril_mutex_unlock(&parentp->idx->lock);
    379 
    380         bs = block_bb_get(devmap_handle);
    381         blocks = parentp->size / BPS(bs);
    382         for (i = 0; i < blocks; i++) {
    383                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    384                 if (rc != EOK)
    385                         return rc;
    386                 for (j = 0; j < DPS(bs); j++) {
    387                         d = ((fat_dentry_t *)b->data) + j;
    388                         switch (fat_classify_dentry(d)) {
    389                         case FAT_DENTRY_SKIP:
    390                         case FAT_DENTRY_FREE:
    391                                 continue;
    392                         case FAT_DENTRY_LAST:
    393                                 /* miss */
    394                                 rc = block_put(b);
    395                                 *rfn = NULL;
    396                                 return rc;
    397                         default:
    398                         case FAT_DENTRY_VALID:
    399                                 fat_dentry_name_get(d, name);
    400                                 break;
     384       
     385        fat_directory_t di;
     386        rc = fat_directory_open(parentp, &di);
     387        if (rc != EOK)
     388                return rc;
     389
     390        while (fat_directory_read(&di, name, &d) == EOK) {
     391                if (fat_dentry_namecmp(name, component) == 0) {
     392                        /* hit */
     393                        fat_node_t *nodep;
     394                        aoff64_t o = di.pos %
     395                            (BPS(di.bs) / sizeof(fat_dentry_t));
     396                        fat_idx_t *idx = fat_idx_get_by_pos(service_id,
     397                            parentp->firstc, di.bnum * DPS(di.bs) + o);
     398                        if (!idx) {
     399                                /*
     400                                 * Can happen if memory is low or if we
     401                                 * run out of 32-bit indices.
     402                                 */
     403                                rc = fat_directory_close(&di);
     404                                return (rc == EOK) ? ENOMEM : rc;
    401405                        }
    402                         if (fat_dentry_namecmp(name, component) == 0) {
    403                                 /* hit */
    404                                 fat_node_t *nodep;
    405                                 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
    406                                     parentp->firstc, i * DPS(bs) + j);
    407                                 if (!idx) {
    408                                         /*
    409                                          * Can happen if memory is low or if we
    410                                          * run out of 32-bit indices.
    411                                          */
    412                                         rc = block_put(b);
    413                                         return (rc == EOK) ? ENOMEM : rc;
    414                                 }
    415                                 rc = fat_node_get_core(&nodep, idx);
    416                                 fibril_mutex_unlock(&idx->lock);
    417                                 if (rc != EOK) {
    418                                         (void) block_put(b);
    419                                         return rc;
    420                                 }
    421                                 *rfn = FS_NODE(nodep);
    422                                 rc = block_put(b);
    423                                 if (rc != EOK)
    424                                         (void) fat_node_put(*rfn);
     406                        rc = fat_node_get_core(&nodep, idx);
     407                        fibril_mutex_unlock(&idx->lock);
     408                        if (rc != EOK) {
     409                                (void) fat_directory_close(&di);
    425410                                return rc;
    426411                        }
    427                 }
    428                 rc = block_put(b);
    429                 if (rc != EOK)
     412                        *rfn = FS_NODE(nodep);
     413                        rc = fat_directory_close(&di);
     414                        if (rc != EOK)
     415                                (void) fat_node_put(*rfn);
    430416                        return rc;
    431         }
    432 
     417                } else {
     418                        rc = fat_directory_next(&di);
     419                        if (rc != EOK)
     420                                break;
     421                }
     422        }
     423        (void) fat_directory_close(&di);
    433424        *rfn = NULL;
    434425        return EOK;
     
    436427
    437428/** Instantiate a FAT in-core node. */
    438 int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
     429int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
    439430{
    440431        fat_node_t *nodep;
     
    442433        int rc;
    443434
    444         idxp = fat_idx_get_by_index(devmap_handle, index);
     435        idxp = fat_idx_get_by_index(service_id, index);
    445436        if (!idxp) {
    446437                *rfn = NULL;
     
    473464                if (nodep->idx) {
    474465                        fibril_mutex_lock(&ffn_mutex);
    475                         list_append(&nodep->ffn_link, &ffn_head);
     466                        list_append(&nodep->ffn_link, &ffn_list);
    476467                        fibril_mutex_unlock(&ffn_mutex);
    477468                } else {
     
    493484}
    494485
    495 int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
     486int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
    496487{
    497488        fat_idx_t *idxp;
     
    501492        int rc;
    502493
    503         bs = block_bb_get(devmap_handle);
     494        bs = block_bb_get(service_id);
    504495        if (flags & L_DIRECTORY) {
    505496                /* allocate a cluster */
    506                 rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);
     497                rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl);
    507498                if (rc != EOK)
    508499                        return rc;
    509500                /* populate the new cluster with unused dentries */
    510                 rc = fat_zero_cluster(bs, devmap_handle, mcl);
    511                 if (rc != EOK) {
    512                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     501                rc = fat_zero_cluster(bs, service_id, mcl);
     502                if (rc != EOK) {
     503                        (void) fat_free_clusters(bs, service_id, mcl);
    513504                        return rc;
    514505                }
     
    517508        rc = fat_node_get_new(&nodep);
    518509        if (rc != EOK) {
    519                 (void) fat_free_clusters(bs, devmap_handle, mcl);
    520                 return rc;
    521         }
    522         rc = fat_idx_get_new(&idxp, devmap_handle);
     510                (void) fat_free_clusters(bs, service_id, mcl);
     511                return rc;
     512        }
     513        rc = fat_idx_get_new(&idxp, service_id);
    523514        if (rc != EOK) {
    524                 (void) fat_free_clusters(bs, devmap_handle, mcl);       
     515                (void) fat_free_clusters(bs, service_id, mcl); 
    525516                (void) fat_node_put(FS_NODE(nodep));
    526517                return rc;
     
    571562        assert(!has_children);
    572563
    573         bs = block_bb_get(nodep->idx->devmap_handle);
     564        bs = block_bb_get(nodep->idx->service_id);
    574565        if (nodep->firstc != FAT_CLST_RES0) {
    575566                assert(nodep->size);
    576567                /* Free all clusters allocated to the node. */
    577                 rc = fat_free_clusters(bs, nodep->idx->devmap_handle,
     568                rc = fat_free_clusters(bs, nodep->idx->service_id,
    578569                    nodep->firstc);
    579570        }
     
    592583        fat_bs_t *bs;
    593584        block_t *b;
    594         unsigned i, j;
    595         unsigned blocks;
    596         fat_cluster_t mcl, lcl;
     585        fat_directory_t di;
     586        fat_dentry_t de;
    597587        int rc;
    598588
     
    608598        fibril_mutex_unlock(&childp->lock);
    609599
    610         if (!fat_dentry_name_verify(name)) {
    611                 /*
    612                  * Attempt to create unsupported name.
    613                  */
     600        if (!fat_valid_name(name))
    614601                return ENOTSUP;
    615         }
    616 
    617         /*
    618          * Get us an unused parent node's dentry or grow the parent and allocate
    619          * a new one.
    620          */
    621        
     602
    622603        fibril_mutex_lock(&parentp->idx->lock);
    623         bs = block_bb_get(parentp->idx->devmap_handle);
    624 
    625         blocks = parentp->size / BPS(bs);
    626 
    627         for (i = 0; i < blocks; i++) {
    628                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    629                 if (rc != EOK) {
    630                         fibril_mutex_unlock(&parentp->idx->lock);
    631                         return rc;
    632                 }
    633                 for (j = 0; j < DPS(bs); j++) {
    634                         d = ((fat_dentry_t *)b->data) + j;
    635                         switch (fat_classify_dentry(d)) {
    636                         case FAT_DENTRY_SKIP:
    637                         case FAT_DENTRY_VALID:
    638                                 /* skipping used and meta entries */
    639                                 continue;
    640                         case FAT_DENTRY_FREE:
    641                         case FAT_DENTRY_LAST:
    642                                 /* found an empty slot */
    643                                 goto hit;
    644                         }
    645                 }
    646                 rc = block_put(b);
    647                 if (rc != EOK) {
    648                         fibril_mutex_unlock(&parentp->idx->lock);
    649                         return rc;
    650                 }
    651         }
    652         j = 0;
    653        
    654         /*
    655          * We need to grow the parent in order to create a new unused dentry.
    656          */
    657         if (parentp->firstc == FAT_CLST_ROOT) {
    658                 /* Can't grow the root directory. */
    659                 fibril_mutex_unlock(&parentp->idx->lock);
    660                 return ENOSPC;
    661         }
    662         rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
     604        bs = block_bb_get(parentp->idx->service_id);
     605        rc = fat_directory_open(parentp, &di);
    663606        if (rc != EOK) {
    664607                fibril_mutex_unlock(&parentp->idx->lock);
    665608                return rc;
    666609        }
    667         rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
    668         if (rc != EOK) {
    669                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    670                 fibril_mutex_unlock(&parentp->idx->lock);
    671                 return rc;
    672         }
    673         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    674         if (rc != EOK) {
    675                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    676                 fibril_mutex_unlock(&parentp->idx->lock);
    677                 return rc;
    678         }
    679         parentp->size += BPS(bs) * SPC(bs);
    680         parentp->dirty = true;          /* need to sync node */
    681         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    682         if (rc != EOK) {
    683                 fibril_mutex_unlock(&parentp->idx->lock);
    684                 return rc;
    685         }
    686         d = (fat_dentry_t *)b->data;
    687 
    688 hit:
     610
    689611        /*
    690612         * At this point we only establish the link between the parent and the
     
    693615         * dentry data is kept in the child node structure.
    694616         */
    695         memset(d, 0, sizeof(fat_dentry_t));
    696         fat_dentry_name_set(d, name);
    697         b->dirty = true;                /* need to sync block */
    698         rc = block_put(b);
     617        memset(&de, 0, sizeof(fat_dentry_t));
     618
     619        rc = fat_directory_write(&di, name, &de);
     620        if (rc != EOK) {
     621                (void) fat_directory_close(&di);
     622                fibril_mutex_unlock(&parentp->idx->lock);
     623                return rc;
     624        }
     625        rc = fat_directory_close(&di);
     626        if (rc != EOK) {
     627                fibril_mutex_unlock(&parentp->idx->lock);
     628                return rc;
     629        }
     630
    699631        fibril_mutex_unlock(&parentp->idx->lock);
    700         if (rc != EOK)
    701                 return rc;
    702632
    703633        fibril_mutex_lock(&childp->idx->lock);
    704        
     634
    705635        if (childp->type == FAT_DIRECTORY) {
    706636                /*
     
    721651                d = (fat_dentry_t *) b->data;
    722652                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    723                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     653                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    724654                        memset(d, 0, sizeof(fat_dentry_t));
    725655                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    731661                d++;
    732662                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    733                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     663                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    734664                        memset(d, 0, sizeof(fat_dentry_t));
    735665                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    736666                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    737667                        d->attr = FAT_ATTR_SUBDIR;
    738                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    739                             host2uint16_t_le(FAT_CLST_RES0) :
     668                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     669                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    740670                            host2uint16_t_le(parentp->firstc);
    741671                        /* TODO: initialize also the date/time members. */
     
    751681
    752682        childp->idx->pfc = parentp->firstc;
    753         childp->idx->pdi = i * DPS(bs) + j;
     683        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    754684        fibril_mutex_unlock(&childp->idx->lock);
    755685
     
    771701        fat_node_t *parentp = FAT_NODE(pfn);
    772702        fat_node_t *childp = FAT_NODE(cfn);
    773         fat_bs_t *bs;
    774         fat_dentry_t *d;
    775         block_t *b;
    776703        bool has_children;
    777704        int rc;
     
    779706        if (!parentp)
    780707                return EBUSY;
    781        
     708
    782709        rc = fat_has_children(&has_children, cfn);
    783710        if (rc != EOK)
     
    790717        assert(childp->lnkcnt == 1);
    791718        fibril_mutex_lock(&childp->idx->lock);
    792         bs = block_bb_get(childp->idx->devmap_handle);
    793 
    794         rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
    795             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    796             BLOCK_FLAGS_NONE);
    797         if (rc != EOK)
     719       
     720        fat_directory_t di;
     721        rc = fat_directory_open(parentp, &di);
     722        if (rc != EOK)
    798723                goto error;
    799         d = (fat_dentry_t *)b->data +
    800             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    801         /* mark the dentry as not-currently-used */
    802         d->name[0] = FAT_DENTRY_ERASED;
    803         b->dirty = true;                /* need to sync block */
    804         rc = block_put(b);
     724        rc = fat_directory_seek(&di, childp->idx->pdi);
     725        if (rc != EOK)
     726                goto error;
     727        rc = fat_directory_erase(&di);
     728        if (rc != EOK)
     729                goto error;
     730        rc = fat_directory_close(&di);
    805731        if (rc != EOK)
    806732                goto error;
     
    821747
    822748error:
    823         fibril_mutex_unlock(&parentp->idx->lock);
     749        (void) fat_directory_close(&di);
     750        fibril_mutex_unlock(&childp->idx->lock);
    824751        fibril_mutex_unlock(&childp->lock);
    825         fibril_mutex_unlock(&childp->idx->lock);
     752        fibril_mutex_unlock(&parentp->lock);
    826753        return rc;
    827754}
     
    840767                return EOK;
    841768        }
    842        
     769
    843770        fibril_mutex_lock(&nodep->idx->lock);
    844         bs = block_bb_get(nodep->idx->devmap_handle);
     771        bs = block_bb_get(nodep->idx->service_id);
    845772
    846773        blocks = nodep->size / BPS(bs);
     
    848775        for (i = 0; i < blocks; i++) {
    849776                fat_dentry_t *d;
    850        
     777
    851778                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    852779                if (rc != EOK) {
     
    876803                if (rc != EOK) {
    877804                        fibril_mutex_unlock(&nodep->idx->lock);
    878                         return rc;     
     805                        return rc;
    879806                }
    880807        }
     
    901828}
    902829
    903 char fat_plb_get_char(unsigned pos)
    904 {
    905         return fat_reg.plb_ro[pos % PLB_SIZE];
    906 }
    907 
    908830bool fat_is_directory(fs_node_t *fn)
    909831{
     
    916838}
    917839
    918 devmap_handle_t fat_device_get(fs_node_t *node)
     840service_id_t fat_device_get(fs_node_t *node)
    919841{
    920842        return 0;
     
    936858        .size_get = fat_size_get,
    937859        .lnkcnt_get = fat_lnkcnt_get,
    938         .plb_get_char = fat_plb_get_char,
    939860        .is_directory = fat_is_directory,
    940861        .is_file = fat_is_file,
     
    943864
    944865/*
    945  * VFS operations.
     866 * FAT VFS_OUT operations.
    946867 */
    947868
    948 void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
    949 {
    950         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     869static int
     870fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
     871    aoff64_t *size, unsigned *linkcnt)
     872{
    951873        enum cache_mode cmode;
    952874        fat_bs_t *bs;
    953        
    954         /* Accept the mount options */
    955         char *opts;
    956         int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
    957        
    958         if (rc != EOK) {
    959                 async_answer_0(rid, rc);
    960                 return;
    961         }
     875        int rc;
    962876
    963877        /* Check for option enabling write through. */
     
    967881                cmode = CACHE_MODE_WB;
    968882
    969         free(opts);
    970 
    971883        /* initialize libblock */
    972         rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
     884        rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
     885        if (rc != EOK)
     886                return rc;
     887
     888        /* prepare the boot block */
     889        rc = block_bb_read(service_id, BS_BLOCK);
    973890        if (rc != EOK) {
    974                 async_answer_0(rid, rc);
    975                 return;
    976         }
    977 
    978         /* prepare the boot block */
    979         rc = block_bb_read(devmap_handle, BS_BLOCK);
    980         if (rc != EOK) {
    981                 block_fini(devmap_handle);
    982                 async_answer_0(rid, rc);
    983                 return;
     891                block_fini(service_id);
     892                return rc;
    984893        }
    985894
    986895        /* get the buffer with the boot sector */
    987         bs = block_bb_get(devmap_handle);
     896        bs = block_bb_get(service_id);
    988897       
    989898        if (BPS(bs) != BS_SIZE) {
    990                 block_fini(devmap_handle);
    991                 async_answer_0(rid, ENOTSUP);
    992                 return;
     899                block_fini(service_id);
     900                return ENOTSUP;
    993901        }
    994902
    995903        /* Initialize the block cache */
    996         rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode);
     904        rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
    997905        if (rc != EOK) {
    998                 block_fini(devmap_handle);
    999                 async_answer_0(rid, rc);
    1000                 return;
     906                block_fini(service_id);
     907                return rc;
    1001908        }
    1002909
    1003910        /* Do some simple sanity checks on the file system. */
    1004         rc = fat_sanity_check(bs, devmap_handle);
     911        rc = fat_sanity_check(bs, service_id);
    1005912        if (rc != EOK) {
    1006                 (void) block_cache_fini(devmap_handle);
    1007                 block_fini(devmap_handle);
    1008                 async_answer_0(rid, rc);
    1009                 return;
    1010         }
    1011 
    1012         rc = fat_idx_init_by_devmap_handle(devmap_handle);
     913                (void) block_cache_fini(service_id);
     914                block_fini(service_id);
     915                return rc;
     916        }
     917
     918        rc = fat_idx_init_by_service_id(service_id);
    1013919        if (rc != EOK) {
    1014                 (void) block_cache_fini(devmap_handle);
    1015                 block_fini(devmap_handle);
    1016                 async_answer_0(rid, rc);
    1017                 return;
     920                (void) block_cache_fini(service_id);
     921                block_fini(service_id);
     922                return rc;
    1018923        }
    1019924
     
    1021926        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    1022927        if (!rfn) {
    1023                 (void) block_cache_fini(devmap_handle);
    1024                 block_fini(devmap_handle);
    1025                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1026                 async_answer_0(rid, ENOMEM);
    1027                 return;
    1028         }
     928                (void) block_cache_fini(service_id);
     929                block_fini(service_id);
     930                fat_idx_fini_by_service_id(service_id);
     931                return ENOMEM;
     932        }
     933
    1029934        fs_node_initialize(rfn);
    1030935        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
    1031936        if (!rootp) {
    1032937                free(rfn);
    1033                 (void) block_cache_fini(devmap_handle);
    1034                 block_fini(devmap_handle);
    1035                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1036                 async_answer_0(rid, ENOMEM);
    1037                 return;
     938                (void) block_cache_fini(service_id);
     939                block_fini(service_id);
     940                fat_idx_fini_by_service_id(service_id);
     941                return ENOMEM;
    1038942        }
    1039943        fat_node_initialize(rootp);
    1040944
    1041         fat_idx_t *ridxp = fat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0);
     945        fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
    1042946        if (!ridxp) {
    1043947                free(rfn);
    1044948                free(rootp);
    1045                 (void) block_cache_fini(devmap_handle);
    1046                 block_fini(devmap_handle);
    1047                 fat_idx_fini_by_devmap_handle(devmap_handle);
    1048                 async_answer_0(rid, ENOMEM);
    1049                 return;
     949                (void) block_cache_fini(service_id);
     950                block_fini(service_id);
     951                fat_idx_fini_by_service_id(service_id);
     952                return ENOMEM;
    1050953        }
    1051954        assert(ridxp->index == 0);
     
    1053956
    1054957        rootp->type = FAT_DIRECTORY;
    1055         rootp->firstc = FAT_CLST_ROOT;
     958        rootp->firstc = FAT_ROOT_CLST(bs);
    1056959        rootp->refcnt = 1;
    1057960        rootp->lnkcnt = 0;      /* FS root is not linked */
    1058         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     961
     962        if (FAT_IS_FAT32(bs)) {
     963                uint32_t clusters;
     964                rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     965                if (rc != EOK) {
     966                        free(rfn);
     967                        free(rootp);
     968                        (void) block_cache_fini(service_id);
     969                        block_fini(service_id);
     970                        fat_idx_fini_by_service_id(service_id);
     971                        return ENOTSUP;
     972                }
     973                rootp->size = BPS(bs) * SPC(bs) * clusters;
     974        } else
     975                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     976
    1059977        rootp->idx = ridxp;
    1060978        ridxp->nodep = rootp;
    1061979        rootp->bp = rfn;
    1062980        rfn->data = rootp;
    1063        
     981
    1064982        fibril_mutex_unlock(&ridxp->lock);
    1065983
    1066         async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
    1067 }
    1068 
    1069 void fat_mount(ipc_callid_t rid, ipc_call_t *request)
    1070 {
    1071         libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1072 }
    1073 
    1074 void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
    1075 {
    1076         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     984        *index = ridxp->index;
     985        *size = rootp->size;
     986        *linkcnt = rootp->lnkcnt;
     987
     988        return EOK;
     989}
     990
     991static int fat_unmounted(service_id_t service_id)
     992{
    1077993        fs_node_t *fn;
    1078994        fat_node_t *nodep;
    1079995        int rc;
    1080996
    1081         rc = fat_root_get(&fn, devmap_handle);
    1082         if (rc != EOK) {
    1083                 async_answer_0(rid, rc);
    1084                 return;
    1085         }
     997        rc = fat_root_get(&fn, service_id);
     998        if (rc != EOK)
     999                return rc;
    10861000        nodep = FAT_NODE(fn);
    10871001
     
    10921006        if (nodep->refcnt != 2) {
    10931007                (void) fat_node_put(fn);
    1094                 async_answer_0(rid, EBUSY);
    1095                 return;
    1096         }
    1097        
     1008                return EBUSY;
     1009        }
     1010
    10981011        /*
    10991012         * Put the root node and force it to the FAT free node list.
     
    11071020         * stop using libblock for this instance.
    11081021         */
    1109         (void) fat_node_fini_by_devmap_handle(devmap_handle);
    1110         fat_idx_fini_by_devmap_handle(devmap_handle);
    1111         (void) block_cache_fini(devmap_handle);
    1112         block_fini(devmap_handle);
    1113 
    1114         async_answer_0(rid, EOK);
    1115 }
    1116 
    1117 void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
    1118 {
    1119         libfs_unmount(&fat_libfs_ops, rid, request);
    1120 }
    1121 
    1122 void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
    1123 {
    1124         libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1125 }
    1126 
    1127 void fat_read(ipc_callid_t rid, ipc_call_t *request)
    1128 {
    1129         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1130         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1131         aoff64_t pos =
    1132             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1022        (void) fat_node_fini_by_service_id(service_id);
     1023        fat_idx_fini_by_service_id(service_id);
     1024        (void) block_cache_fini(service_id);
     1025        block_fini(service_id);
     1026
     1027        return EOK;
     1028}
     1029
     1030static int
     1031fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
     1032    size_t *rbytes)
     1033{
    11331034        fs_node_t *fn;
    11341035        fat_node_t *nodep;
     
    11381039        int rc;
    11391040
    1140         rc = fat_node_get(&fn, devmap_handle, index);
    1141         if (rc != EOK) {
    1142                 async_answer_0(rid, rc);
    1143                 return;
    1144         }
    1145         if (!fn) {
    1146                 async_answer_0(rid, ENOENT);
    1147                 return;
    1148         }
     1041        rc = fat_node_get(&fn, service_id, index);
     1042        if (rc != EOK)
     1043                return rc;
     1044        if (!fn)
     1045                return ENOENT;
    11491046        nodep = FAT_NODE(fn);
    11501047
     
    11541051                fat_node_put(fn);
    11551052                async_answer_0(callid, EINVAL);
    1156                 async_answer_0(rid, EINVAL);
    1157                 return;
    1158         }
    1159 
    1160         bs = block_bb_get(devmap_handle);
     1053                return EINVAL;
     1054        }
     1055
     1056        bs = block_bb_get(service_id);
    11611057
    11621058        if (nodep->type == FAT_FILE) {
     
    11781074                                fat_node_put(fn);
    11791075                                async_answer_0(callid, rc);
    1180                                 async_answer_0(rid, rc);
    1181                                 return;
     1076                                return rc;
    11821077                        }
    11831078                        (void) async_data_read_finalize(callid,
     
    11861081                        if (rc != EOK) {
    11871082                                fat_node_put(fn);
    1188                                 async_answer_0(rid, rc);
    1189                                 return;
     1083                                return rc;
    11901084                        }
    11911085                }
    11921086        } else {
    1193                 unsigned bnum;
    11941087                aoff64_t spos = pos;
    1195                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1088                char name[FAT_LFN_NAME_SIZE];
    11961089                fat_dentry_t *d;
    11971090
     
    12001093                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    12011094
    1202                 /*
    1203                  * Our strategy for readdir() is to use the position pointer as
    1204                  * an index into the array of all dentries. On entry, it points
    1205                  * to the first unread dentry. If we skip any dentries, we bump
    1206                  * the position pointer accordingly.
    1207                  */
    1208                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1209                 while (bnum < nodep->size / BPS(bs)) {
    1210                         aoff64_t o;
    1211 
    1212                         rc = fat_block_get(&b, bs, nodep, bnum,
    1213                             BLOCK_FLAGS_NONE);
    1214                         if (rc != EOK)
    1215                                 goto err;
    1216                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1217                             o < BPS(bs) / sizeof(fat_dentry_t);
    1218                             o++, pos++) {
    1219                                 d = ((fat_dentry_t *)b->data) + o;
    1220                                 switch (fat_classify_dentry(d)) {
    1221                                 case FAT_DENTRY_SKIP:
    1222                                 case FAT_DENTRY_FREE:
    1223                                         continue;
    1224                                 case FAT_DENTRY_LAST:
    1225                                         rc = block_put(b);
    1226                                         if (rc != EOK)
    1227                                                 goto err;
    1228                                         goto miss;
    1229                                 default:
    1230                                 case FAT_DENTRY_VALID:
    1231                                         fat_dentry_name_get(d, name);
    1232                                         rc = block_put(b);
    1233                                         if (rc != EOK)
    1234                                                 goto err;
    1235                                         goto hit;
    1236                                 }
    1237                         }
    1238                         rc = block_put(b);
    1239                         if (rc != EOK)
    1240                                 goto err;
    1241                         bnum++;
    1242                 }
    1243 miss:
    1244                 rc = fat_node_put(fn);
    1245                 async_answer_0(callid, rc != EOK ? rc : ENOENT);
    1246                 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
    1247                 return;
     1095                fat_directory_t di;
     1096                rc = fat_directory_open(nodep, &di);
     1097                if (rc != EOK)
     1098                        goto err;
     1099                rc = fat_directory_seek(&di, pos);
     1100                if (rc != EOK) {
     1101                        (void) fat_directory_close(&di);
     1102                        goto err;
     1103                }
     1104
     1105                rc = fat_directory_read(&di, name, &d);
     1106                if (rc == EOK)
     1107                        goto hit;
     1108                if (rc == ENOENT)
     1109                        goto miss;
    12481110
    12491111err:
    12501112                (void) fat_node_put(fn);
    12511113                async_answer_0(callid, rc);
    1252                 async_answer_0(rid, rc);
    1253                 return;
     1114                return rc;
     1115
     1116miss:
     1117                rc = fat_directory_close(&di);
     1118                if (rc != EOK)
     1119                        goto err;
     1120                rc = fat_node_put(fn);
     1121                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     1122                *rbytes = 0;
     1123                return rc != EOK ? rc : ENOENT;
    12541124
    12551125hit:
    1256                 (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1126                pos = di.pos;
     1127                rc = fat_directory_close(&di);
     1128                if (rc != EOK)
     1129                        goto err;
     1130                (void) async_data_read_finalize(callid, name,
     1131                    str_size(name) + 1);
    12571132                bytes = (pos - spos) + 1;
    12581133        }
    12591134
    12601135        rc = fat_node_put(fn);
    1261         async_answer_1(rid, rc, (sysarg_t)bytes);
    1262 }
    1263 
    1264 void fat_write(ipc_callid_t rid, ipc_call_t *request)
    1265 {
    1266         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1267         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1268         aoff64_t pos =
    1269             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1136        *rbytes = bytes;
     1137        return rc;
     1138}
     1139
     1140static int
     1141fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
     1142    size_t *wbytes, aoff64_t *nsize)
     1143{
    12701144        fs_node_t *fn;
    12711145        fat_node_t *nodep;
    12721146        fat_bs_t *bs;
    1273         size_t bytes, size;
     1147        size_t bytes;
    12741148        block_t *b;
    12751149        aoff64_t boundary;
     
    12771151        int rc;
    12781152       
    1279         rc = fat_node_get(&fn, devmap_handle, index);
    1280         if (rc != EOK) {
    1281                 async_answer_0(rid, rc);
    1282                 return;
    1283         }
    1284         if (!fn) {
    1285                 async_answer_0(rid, ENOENT);
    1286                 return;
    1287         }
     1153        rc = fat_node_get(&fn, service_id, index);
     1154        if (rc != EOK)
     1155                return rc;
     1156        if (!fn)
     1157                return ENOENT;
    12881158        nodep = FAT_NODE(fn);
    1289        
     1159
    12901160        ipc_callid_t callid;
    12911161        size_t len;
     
    12931163                (void) fat_node_put(fn);
    12941164                async_answer_0(callid, EINVAL);
    1295                 async_answer_0(rid, EINVAL);
    1296                 return;
    1297         }
    1298 
    1299         bs = block_bb_get(devmap_handle);
     1165                return EINVAL;
     1166        }
     1167
     1168        bs = block_bb_get(service_id);
    13001169
    13011170        /*
     
    13041173         * but this one greatly simplifies fat_write(). Note that we can afford
    13051174         * to do this because the client must be ready to handle the return
    1306          * value signalizing a smaller number of bytes written. 
    1307          */ 
     1175         * value signalizing a smaller number of bytes written.
     1176         */
    13081177        bytes = min(len, BPS(bs) - pos % BPS(bs));
    13091178        if (bytes == BPS(bs))
    13101179                flags |= BLOCK_FLAGS_NOREAD;
    1311        
     1180
    13121181        boundary = ROUND_UP(nodep->size, BPC(bs));
    13131182        if (pos < boundary) {
     
    13221191                        (void) fat_node_put(fn);
    13231192                        async_answer_0(callid, rc);
    1324                         async_answer_0(rid, rc);
    1325                         return;
     1193                        return rc;
    13261194                }
    13271195                rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
     
    13291197                        (void) fat_node_put(fn);
    13301198                        async_answer_0(callid, rc);
    1331                         async_answer_0(rid, rc);
    1332                         return;
     1199                        return rc;
    13331200                }
    13341201                (void) async_data_write_finalize(callid,
     
    13381205                if (rc != EOK) {
    13391206                        (void) fat_node_put(fn);
    1340                         async_answer_0(rid, rc);
    1341                         return;
     1207                        return rc;
    13421208                }
    13431209                if (pos + bytes > nodep->size) {
     
    13451211                        nodep->dirty = true;    /* need to sync node */
    13461212                }
    1347                 size = nodep->size;
     1213                *wbytes = bytes;
     1214                *nsize = nodep->size;
    13481215                rc = fat_node_put(fn);
    1349                 async_answer_2(rid, rc, bytes, nodep->size);
    1350                 return;
     1216                return rc;
    13511217        } else {
    13521218                /*
     
    13551221                 */
    13561222                unsigned nclsts;
    1357                 fat_cluster_t mcl, lcl; 
    1358  
     1223                fat_cluster_t mcl, lcl;
     1224
    13591225                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13601226                /* create an independent chain of nclsts clusters in all FATs */
    1361                 rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);
     1227                rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl);
    13621228                if (rc != EOK) {
    13631229                        /* could not allocate a chain of nclsts clusters */
    13641230                        (void) fat_node_put(fn);
    13651231                        async_answer_0(callid, rc);
    1366                         async_answer_0(rid, rc);
    1367                         return;
     1232                        return rc;
    13681233                }
    13691234                /* zero fill any gaps */
    13701235                rc = fat_fill_gap(bs, nodep, mcl, pos);
    13711236                if (rc != EOK) {
    1372                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1237                        (void) fat_free_clusters(bs, service_id, mcl);
    13731238                        (void) fat_node_put(fn);
    13741239                        async_answer_0(callid, rc);
    1375                         async_answer_0(rid, rc);
    1376                         return;
    1377                 }
    1378                 rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
     1240                        return rc;
     1241                }
     1242                rc = _fat_block_get(&b, bs, service_id, lcl, NULL,
    13791243                    (pos / BPS(bs)) % SPC(bs), flags);
    13801244                if (rc != EOK) {
    1381                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1245                        (void) fat_free_clusters(bs, service_id, mcl);
    13821246                        (void) fat_node_put(fn);
    13831247                        async_answer_0(callid, rc);
    1384                         async_answer_0(rid, rc);
    1385                         return;
     1248                        return rc;
    13861249                }
    13871250                (void) async_data_write_finalize(callid,
     
    13901253                rc = block_put(b);
    13911254                if (rc != EOK) {
    1392                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1255                        (void) fat_free_clusters(bs, service_id, mcl);
    13931256                        (void) fat_node_put(fn);
    1394                         async_answer_0(rid, rc);
    1395                         return;
     1257                        return rc;
    13961258                }
    13971259                /*
     
    14011263                rc = fat_append_clusters(bs, nodep, mcl, lcl);
    14021264                if (rc != EOK) {
    1403                         (void) fat_free_clusters(bs, devmap_handle, mcl);
     1265                        (void) fat_free_clusters(bs, service_id, mcl);
    14041266                        (void) fat_node_put(fn);
    1405                         async_answer_0(rid, rc);
    1406                         return;
    1407                 }
    1408                 nodep->size = size = pos + bytes;
     1267                        return rc;
     1268                }
     1269                *nsize = nodep->size = pos + bytes;
     1270                rc = fat_node_put(fn);
    14091271                nodep->dirty = true;            /* need to sync node */
    1410                 rc = fat_node_put(fn);
    1411                 async_answer_2(rid, rc, bytes, size);
    1412                 return;
    1413         }
    1414 }
    1415 
    1416 void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
    1417 {
    1418         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1419         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1420         aoff64_t size =
    1421             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     1272                *wbytes = bytes;
     1273                return rc;
     1274        }
     1275}
     1276
     1277static int
     1278fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
     1279{
    14221280        fs_node_t *fn;
    14231281        fat_node_t *nodep;
     
    14251283        int rc;
    14261284
    1427         rc = fat_node_get(&fn, devmap_handle, index);
    1428         if (rc != EOK) {
    1429                 async_answer_0(rid, rc);
    1430                 return;
    1431         }
    1432         if (!fn) {
    1433                 async_answer_0(rid, ENOENT);
    1434                 return;
    1435         }
     1285        rc = fat_node_get(&fn, service_id, index);
     1286        if (rc != EOK)
     1287                return rc;
     1288        if (!fn)
     1289                return ENOENT;
    14361290        nodep = FAT_NODE(fn);
    14371291
    1438         bs = block_bb_get(devmap_handle);
     1292        bs = block_bb_get(service_id);
    14391293
    14401294        if (nodep->size == size) {
     
    14521306                nodep->size = size;
    14531307                nodep->dirty = true;            /* need to sync node */
    1454                 rc = EOK;       
     1308                rc = EOK;
    14551309        } else {
    14561310                /*
     
    14631317                } else {
    14641318                        fat_cluster_t lastc;
    1465                         rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
     1319                        rc = fat_cluster_walk(bs, service_id, nodep->firstc,
    14661320                            &lastc, NULL, (size - 1) / BPC(bs));
    14671321                        if (rc != EOK)
     
    14731327                nodep->size = size;
    14741328                nodep->dirty = true;            /* need to sync node */
    1475                 rc = EOK;       
     1329                rc = EOK;
    14761330        }
    14771331out:
    14781332        fat_node_put(fn);
    1479         async_answer_0(rid, rc);
    1480         return;
    1481 }
    1482 
    1483 void fat_close(ipc_callid_t rid, ipc_call_t *request)
    1484 {
    1485         async_answer_0(rid, EOK);
    1486 }
    1487 
    1488 void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
    1489 {
    1490         devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
    1491         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
     1333        return rc;
     1334}
     1335
     1336static int fat_close(service_id_t service_id, fs_index_t index)
     1337{
     1338        return EOK;
     1339}
     1340
     1341static int fat_destroy(service_id_t service_id, fs_index_t index)
     1342{
    14921343        fs_node_t *fn;
    14931344        fat_node_t *nodep;
    14941345        int rc;
    14951346
    1496         rc = fat_node_get(&fn, devmap_handle, index);
    1497         if (rc != EOK) {
    1498                 async_answer_0(rid, rc);
    1499                 return;
    1500         }
    1501         if (!fn) {
    1502                 async_answer_0(rid, ENOENT);
    1503                 return;
    1504         }
     1347        rc = fat_node_get(&fn, service_id, index);
     1348        if (rc != EOK)
     1349                return rc;
     1350        if (!fn)
     1351                return ENOENT;
    15051352
    15061353        nodep = FAT_NODE(fn);
     
    15121359
    15131360        rc = fat_destroy_node(fn);
    1514         async_answer_0(rid, rc);
    1515 }
    1516 
    1517 void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
    1518 {
    1519         libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1520 }
    1521 
    1522 void fat_stat(ipc_callid_t rid, ipc_call_t *request)
    1523 {
    1524         libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
    1525 }
    1526 
    1527 void fat_sync(ipc_callid_t rid, ipc_call_t *request)
    1528 {
    1529         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    1530         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    1531        
     1361        return rc;
     1362}
     1363
     1364static int fat_sync(service_id_t service_id, fs_index_t index)
     1365{
    15321366        fs_node_t *fn;
    1533         int rc = fat_node_get(&fn, devmap_handle, index);
    1534         if (rc != EOK) {
    1535                 async_answer_0(rid, rc);
    1536                 return;
    1537         }
    1538         if (!fn) {
    1539                 async_answer_0(rid, ENOENT);
    1540                 return;
    1541         }
    1542        
     1367        int rc = fat_node_get(&fn, service_id, index);
     1368        if (rc != EOK)
     1369                return rc;
     1370        if (!fn)
     1371                return ENOENT;
     1372
    15431373        fat_node_t *nodep = FAT_NODE(fn);
    1544        
     1374
    15451375        nodep->dirty = true;
    15461376        rc = fat_node_sync(nodep);
    1547        
     1377
    15481378        fat_node_put(fn);
    1549         async_answer_0(rid, rc);
    1550 }
     1379        return rc;
     1380}
     1381
     1382vfs_out_ops_t fat_ops = {
     1383        .mounted = fat_mounted,
     1384        .unmounted = fat_unmounted,
     1385        .read = fat_read,
     1386        .write = fat_write,
     1387        .truncate = fat_truncate,
     1388        .close = fat_close,
     1389        .destroy = fat_destroy,
     1390        .sync = fat_sync,
     1391};
    15511392
    15521393/**
  • uspace/srv/fs/locfs/Makefile

    rd2c67e7 r8ff0bd2  
    3131LIBS = $(LIBFS_PREFIX)/libfs.a
    3232EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
    33 BINARY = devfs
     33BINARY = locfs
    3434STATIC_NEEDED = y
    3535
    3636SOURCES = \
    37         devfs.c \
    38         devfs_ops.c
     37        locfs.c \
     38        locfs_ops.c
    3939
    4040include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/fs/locfs/locfs.c

    rd2c67e7 r8ff0bd2  
    3232
    3333/**
    34  * @file devfs.c
    35  * @brief Devices file system.
     34 * @file locfs.c
     35 * @brief Location-service file system.
    3636 *
    37  * Every device registered to device mapper is represented as a file in this
     37 * Every service registered with location service is represented as a file in this
    3838 * file system.
    3939 */
     
    4646#include <task.h>
    4747#include <libfs.h>
    48 #include "devfs.h"
    49 #include "devfs_ops.h"
     48#include "locfs.h"
     49#include "locfs_ops.h"
    5050
    51 #define NAME  "devfs"
     51#define NAME  "locfs"
    5252
    53 static vfs_info_t devfs_vfs_info = {
     53static vfs_info_t locfs_vfs_info = {
    5454        .name = NAME,
    5555        .concurrent_read_write = false,
     
    5757};
    5858
    59 fs_reg_t devfs_reg;
    60 
    61 static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall)
    62 {
    63         if (iid)
    64                 async_answer_0(iid, EOK);
    65        
    66         while (true) {
    67                 ipc_call_t call;
    68                 ipc_callid_t callid = async_get_call(&call);
    69                
    70                 if (!IPC_GET_IMETHOD(call))
    71                         return;
    72                
    73                 switch (IPC_GET_IMETHOD(call)) {
    74                 case VFS_OUT_MOUNTED:
    75                         devfs_mounted(callid, &call);
    76                         break;
    77                 case VFS_OUT_MOUNT:
    78                         devfs_mount(callid, &call);
    79                         break;
    80                 case VFS_OUT_UNMOUNTED:
    81                         devfs_unmounted(callid, &call);
    82                         break;
    83                 case VFS_OUT_UNMOUNT:
    84                         devfs_unmount(callid, &call);
    85                         break;
    86                 case VFS_OUT_LOOKUP:
    87                         devfs_lookup(callid, &call);
    88                         break;
    89                 case VFS_OUT_OPEN_NODE:
    90                         devfs_open_node(callid, &call);
    91                         break;
    92                 case VFS_OUT_STAT:
    93                         devfs_stat(callid, &call);
    94                         break;
    95                 case VFS_OUT_READ:
    96                         devfs_read(callid, &call);
    97                         break;
    98                 case VFS_OUT_WRITE:
    99                         devfs_write(callid, &call);
    100                         break;
    101                 case VFS_OUT_TRUNCATE:
    102                         devfs_truncate(callid, &call);
    103                         break;
    104                 case VFS_OUT_CLOSE:
    105                         devfs_close(callid, &call);
    106                         break;
    107                 case VFS_OUT_SYNC:
    108                         devfs_sync(callid, &call);
    109                         break;
    110                 case VFS_OUT_DESTROY:
    111                         devfs_destroy(callid, &call);
    112                         break;
    113                 default:
    114                         async_answer_0(callid, ENOTSUP);
    115                         break;
    116                 }
    117         }
    118 }
    119 
    12059int main(int argc, char *argv[])
    12160{
    12261        printf("%s: HelenOS Device Filesystem\n", NAME);
    12362       
    124         if (!devfs_init()) {
    125                 printf("%s: failed to initialize devfs\n", NAME);
     63        if (!locfs_init()) {
     64                printf("%s: failed to initialize locfs\n", NAME);
    12665                return -1;
    12766        }
     
    13473        }
    13574       
    136         int rc = fs_register(vfs_sess, &devfs_reg, &devfs_vfs_info,
    137             devfs_connection);
     75        int rc = fs_register(vfs_sess, &locfs_vfs_info, &locfs_ops,
     76            &locfs_libfs_ops);
    13877        if (rc != EOK) {
    13978                printf("%s: Failed to register file system (%d)\n", NAME, rc);
     
    15291 * @}
    15392 */
     93
  • uspace/srv/fs/locfs/locfs_ops.h

    rd2c67e7 r8ff0bd2  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    33 #ifndef DEVFS_DEVFS_H_
    34 #define DEVFS_DEVFS_H_
     33#ifndef LOCFS_LOCFS_OPS_H_
     34#define LOCFS_LOCFS_OPS_H_
    3535
    36 #include <libfs.h>
     36#include <bool.h>
    3737
    38 extern fs_reg_t devfs_reg;
     38extern bool locfs_init(void);
    3939
    4040#endif
  • uspace/srv/fs/tmpfs/tmpfs.c

    rd2c67e7 r8ff0bd2  
    6161};
    6262
    63 fs_reg_t tmpfs_reg;
    64 
    65 /**
    66  * This connection fibril processes VFS requests from VFS.
    67  *
    68  * In order to support simultaneous VFS requests, our design is as follows.
    69  * The connection fibril accepts VFS requests from VFS. If there is only one
    70  * instance of the fibril, VFS will need to serialize all VFS requests it sends
    71  * to FAT. To overcome this bottleneck, VFS can send TMPFS the
    72  * IPC_M_CONNECT_ME_TO call. In that case, a new connection fibril will be
    73  * created, which in turn will accept the call. Thus, a new phone will be
    74  * opened for VFS.
    75  *
    76  * There are few issues with this arrangement. First, VFS can run out of
    77  * available phones. In that case, VFS can close some other phones or use one
    78  * phone for more serialized requests. Similarily, TMPFS can refuse to duplicate
    79  * the connection. VFS should then just make use of already existing phones and
    80  * route its requests through them. To avoid paying the fibril creation price
    81  * upon each request, TMPFS might want to keep the connections open after the
    82  * request has been completed.
    83  */
    84 static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall)
    85 {
    86         if (iid) {
    87                 /*
    88                  * This only happens for connections opened by
    89                  * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
    90                  * created by IPC_M_CONNECT_TO_ME.
    91                  */
    92                 async_answer_0(iid, EOK);
    93         }
    94        
    95         dprintf(NAME ": connection opened\n");
    96        
    97         while (true) {
    98                 ipc_call_t call;
    99                 ipc_callid_t callid = async_get_call(&call);
    100                
    101                 if (!IPC_GET_IMETHOD(call))
    102                         return;
    103                
    104                 switch (IPC_GET_IMETHOD(call)) {
    105                 case VFS_OUT_MOUNTED:
    106                         tmpfs_mounted(callid, &call);
    107                         break;
    108                 case VFS_OUT_MOUNT:
    109                         tmpfs_mount(callid, &call);
    110                         break;
    111                 case VFS_OUT_UNMOUNTED:
    112                         tmpfs_unmounted(callid, &call);
    113                         break;
    114                 case VFS_OUT_UNMOUNT:
    115                         tmpfs_unmount(callid, &call);
    116                         break;
    117                 case VFS_OUT_LOOKUP:
    118                         tmpfs_lookup(callid, &call);
    119                         break;
    120                 case VFS_OUT_READ:
    121                         tmpfs_read(callid, &call);
    122                         break;
    123                 case VFS_OUT_WRITE:
    124                         tmpfs_write(callid, &call);
    125                         break;
    126                 case VFS_OUT_TRUNCATE:
    127                         tmpfs_truncate(callid, &call);
    128                         break;
    129                 case VFS_OUT_CLOSE:
    130                         tmpfs_close(callid, &call);
    131                         break;
    132                 case VFS_OUT_DESTROY:
    133                         tmpfs_destroy(callid, &call);
    134                         break;
    135                 case VFS_OUT_OPEN_NODE:
    136                         tmpfs_open_node(callid, &call);
    137                         break;
    138                 case VFS_OUT_STAT:
    139                         tmpfs_stat(callid, &call);
    140                         break;
    141                 case VFS_OUT_SYNC:
    142                         tmpfs_sync(callid, &call);
    143                         break;
    144                 default:
    145                         async_answer_0(callid, ENOTSUP);
    146                         break;
    147                 }
    148         }
    149 }
    150 
    15163int main(int argc, char **argv)
    15264{
     
    16577        }
    16678       
    167         int rc = fs_register(vfs_sess, &tmpfs_reg, &tmpfs_vfs_info,
    168             tmpfs_connection);
     79        int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops,
     80            &tmpfs_libfs_ops);
    16981        if (rc != EOK) {
    17082                printf(NAME ": Failed to register file system (%d)\n", rc);
  • uspace/srv/fs/tmpfs/tmpfs.h

    rd2c67e7 r8ff0bd2  
    6161        fs_node_t *bp;          /**< Back pointer to the FS node. */
    6262        fs_index_t index;       /**< TMPFS node index. */
    63         devmap_handle_t devmap_handle;/**< Device handle. */
     63        service_id_t service_id;/**< Service ID of block device. */
    6464        link_t nh_link;         /**< Nodes hash table link. */
    6565        tmpfs_dentry_type_t type;
     
    6767        size_t size;            /**< File size if type is TMPFS_FILE. */
    6868        void *data;             /**< File content's if type is TMPFS_FILE. */
    69         link_t cs_head;         /**< Head of child's siblings list. */
     69        list_t cs_list;         /**< Child's siblings list. */
    7070} tmpfs_node_t;
    7171
    72 extern fs_reg_t tmpfs_reg;
    73 
     72extern vfs_out_ops_t tmpfs_ops;
    7473extern libfs_ops_t tmpfs_libfs_ops;
    7574
    7675extern bool tmpfs_init(void);
    77 
    78 extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
    79 extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
    80 extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
    81 extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
    82 extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
    83 extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
    84 extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
    85 extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
    86 extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
    87 extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
    88 extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
    89 extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
    90 extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
    91 
    92 extern bool tmpfs_restore(devmap_handle_t);
     76extern bool tmpfs_restore(service_id_t);
    9377
    9478#endif
  • uspace/srv/fs/tmpfs/tmpfs_dump.c

    rd2c67e7 r8ff0bd2  
    5555
    5656static bool
    57 tmpfs_restore_recursion(devmap_handle_t dev, size_t *bufpos, size_t *buflen,
     57tmpfs_restore_recursion(service_id_t dsid, size_t *bufpos, size_t *buflen,
    5858    aoff64_t *pos, fs_node_t *pfn)
    5959{
     
    6868                uint32_t size;
    6969               
    70                 if (block_seqread(dev, bufpos, buflen, pos, &entry,
     70                if (block_seqread(dsid, bufpos, buflen, pos, &entry,
    7171                    sizeof(entry)) != EOK)
    7272                        return false;
     
    8282                                return false;
    8383                       
    84                         rc = ops->create(&fn, dev, L_FILE);
     84                        rc = ops->create(&fn, dsid, L_FILE);
    8585                        if (rc != EOK || fn == NULL) {
    8686                                free(fname);
     
    8888                        }
    8989                       
    90                         if (block_seqread(dev, bufpos, buflen, pos, fname,
     90                        if (block_seqread(dsid, bufpos, buflen, pos, fname,
    9191                            entry.len) != EOK) {
    9292                                (void) ops->destroy(fn);
     
    104104                        free(fname);
    105105                       
    106                         if (block_seqread(dev, bufpos, buflen, pos, &size,
     106                        if (block_seqread(dsid, bufpos, buflen, pos, &size,
    107107                            sizeof(size)) != EOK)
    108108                                return false;
     
    116116                       
    117117                        nodep->size = size;
    118                         if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
     118                        if (block_seqread(dsid, bufpos, buflen, pos, nodep->data,
    119119                            size) != EOK)
    120120                                return false;
     
    126126                                return false;
    127127                       
    128                         rc = ops->create(&fn, dev, L_DIRECTORY);
     128                        rc = ops->create(&fn, dsid, L_DIRECTORY);
    129129                        if (rc != EOK || fn == NULL) {
    130130                                free(fname);
     
    132132                        }
    133133                       
    134                         if (block_seqread(dev, bufpos, buflen, pos, fname,
     134                        if (block_seqread(dsid, bufpos, buflen, pos, fname,
    135135                            entry.len) != EOK) {
    136136                                (void) ops->destroy(fn);
     
    148148                        free(fname);
    149149                       
    150                         if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
     150                        if (!tmpfs_restore_recursion(dsid, bufpos, buflen, pos,
    151151                            fn))
    152152                                return false;
     
    161161}
    162162
    163 bool tmpfs_restore(devmap_handle_t dev)
     163bool tmpfs_restore(service_id_t dsid)
    164164{
    165165        libfs_ops_t *ops = &tmpfs_libfs_ops;
     
    167167        int rc;
    168168
    169         rc = block_init(EXCHANGE_SERIALIZE, dev, TMPFS_COMM_SIZE);
     169        rc = block_init(EXCHANGE_SERIALIZE, dsid, TMPFS_COMM_SIZE);
    170170        if (rc != EOK)
    171171                return false;
     
    176176       
    177177        char tag[6];
    178         if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5) != EOK)
     178        if (block_seqread(dsid, &bufpos, &buflen, &pos, tag, 5) != EOK)
    179179                goto error;
    180180       
     
    183183                goto error;
    184184       
    185         rc = ops->root_get(&fn, dev);
     185        rc = ops->root_get(&fn, dsid);
    186186        if (rc != EOK)
    187187                goto error;
    188188
    189         if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
    190                 goto error;
    191                
    192         block_fini(dev);
     189        if (!tmpfs_restore_recursion(dsid, &bufpos, &buflen, &pos, fn))
     190                goto error;
     191               
     192        block_fini(dsid);
    193193        return true;
    194194       
    195195error:
    196         block_fini(dev);
     196        block_fini(dsid);
    197197        return false;
    198198}
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    rd2c67e7 r8ff0bd2  
    6969/* Forward declarations of static functions. */
    7070static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
    71 static int tmpfs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
     71static int tmpfs_node_get(fs_node_t **, service_id_t, fs_index_t);
    7272static int tmpfs_node_open(fs_node_t *);
    7373static int tmpfs_node_put(fs_node_t *);
    74 static int tmpfs_create_node(fs_node_t **, devmap_handle_t, int);
     74static int tmpfs_create_node(fs_node_t **, service_id_t, int);
    7575static int tmpfs_destroy_node(fs_node_t *);
    7676static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
     
    7878
    7979/* Implementation of helper functions. */
    80 static int tmpfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
    81 {
    82         return tmpfs_node_get(rfn, devmap_handle, TMPFS_SOME_ROOT);
     80static int tmpfs_root_get(fs_node_t **rfn, service_id_t service_id)
     81{
     82        return tmpfs_node_get(rfn, service_id, TMPFS_SOME_ROOT);
    8383}
    8484
    8585static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
    8686{
    87         *has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
     87        *has_children = !list_empty(&TMPFS_NODE(fn)->cs_list);
    8888        return EOK;
    8989}
     
    104104}
    105105
    106 static char tmpfs_plb_get_char(unsigned pos)
    107 {
    108         return tmpfs_reg.plb_ro[pos % PLB_SIZE];
    109 }
    110 
    111106static bool tmpfs_is_directory(fs_node_t *fn)
    112107{
     
    119114}
    120115
    121 static devmap_handle_t tmpfs_device_get(fs_node_t *fn)
     116static service_id_t tmpfs_device_get(fs_node_t *fn)
    122117{
    123118        return 0;
     
    139134        .size_get = tmpfs_size_get,
    140135        .lnkcnt_get = tmpfs_lnkcnt_get,
    141         .plb_get_char = tmpfs_plb_get_char,
    142136        .is_directory = tmpfs_is_directory,
    143137        .is_file = tmpfs_is_file,
     
    164158        switch (keys) {
    165159        case 1:
    166                 return (nodep->devmap_handle == key[NODES_KEY_DEV]);
     160                return (nodep->service_id == key[NODES_KEY_DEV]);
    167161        case 2:
    168                 return ((nodep->devmap_handle == key[NODES_KEY_DEV]) &&
     162                return ((nodep->service_id == key[NODES_KEY_DEV]) &&
    169163                    (nodep->index == key[NODES_KEY_INDEX]));
    170164        default:
     
    180174            nh_link);
    181175
    182         while (!list_empty(&nodep->cs_head)) {
    183                 tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
    184                     tmpfs_dentry_t, link);
     176        while (!list_empty(&nodep->cs_list)) {
     177                tmpfs_dentry_t *dentryp = list_get_instance(
     178                    list_first(&nodep->cs_list), tmpfs_dentry_t, link);
    185179
    186180                assert(nodep->type == TMPFS_DIRECTORY);
     
    208202        nodep->bp = NULL;
    209203        nodep->index = 0;
    210         nodep->devmap_handle = 0;
     204        nodep->service_id = 0;
    211205        nodep->type = TMPFS_NONE;
    212206        nodep->lnkcnt = 0;
     
    214208        nodep->data = NULL;
    215209        link_initialize(&nodep->nh_link);
    216         list_initialize(&nodep->cs_head);
     210        list_initialize(&nodep->cs_list);
    217211}
    218212
     
    232226}
    233227
    234 static bool tmpfs_instance_init(devmap_handle_t devmap_handle)
     228static bool tmpfs_instance_init(service_id_t service_id)
    235229{
    236230        fs_node_t *rfn;
    237231        int rc;
    238232       
    239         rc = tmpfs_create_node(&rfn, devmap_handle, L_DIRECTORY);
     233        rc = tmpfs_create_node(&rfn, service_id, L_DIRECTORY);
    240234        if (rc != EOK || !rfn)
    241235                return false;
     
    244238}
    245239
    246 static void tmpfs_instance_done(devmap_handle_t devmap_handle)
    247 {
    248         unsigned long key[] = {
    249                 [NODES_KEY_DEV] = devmap_handle
     240static void tmpfs_instance_done(service_id_t service_id)
     241{
     242        unsigned long key[] = {
     243                [NODES_KEY_DEV] = service_id
    250244        };
    251245        /*
     
    262256{
    263257        tmpfs_node_t *parentp = TMPFS_NODE(pfn);
    264         link_t *lnk;
    265 
    266         for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
    267             lnk = lnk->next) {
     258
     259        list_foreach(parentp->cs_list, lnk) {
    268260                tmpfs_dentry_t *dentryp;
    269261                dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
     
    278270}
    279271
    280 int tmpfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
    281 {
    282         unsigned long key[] = {
    283                 [NODES_KEY_DEV] = devmap_handle,
     272int tmpfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
     273{
     274        unsigned long key[] = {
     275                [NODES_KEY_DEV] = service_id,
    284276                [NODES_KEY_INDEX] = index
    285277        };
     
    307299}
    308300
    309 int tmpfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
     301int tmpfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
    310302{
    311303        fs_node_t *rootfn;
     
    326318        nodep->bp->data = nodep;        /* link the FS and TMPFS nodes */
    327319
    328         rc = tmpfs_root_get(&rootfn, devmap_handle);
     320        rc = tmpfs_root_get(&rootfn, service_id);
    329321        assert(rc == EOK);
    330322        if (!rootfn)
     
    332324        else
    333325                nodep->index = tmpfs_next_index++;
    334         nodep->devmap_handle = devmap_handle;
     326        nodep->service_id = service_id;
    335327        if (lflag & L_DIRECTORY)
    336328                nodep->type = TMPFS_DIRECTORY;
     
    340332        /* Insert the new node into the nodes hash table. */
    341333        unsigned long key[] = {
    342                 [NODES_KEY_DEV] = nodep->devmap_handle,
     334                [NODES_KEY_DEV] = nodep->service_id,
    343335                [NODES_KEY_INDEX] = nodep->index
    344336        };
     
    353345       
    354346        assert(!nodep->lnkcnt);
    355         assert(list_empty(&nodep->cs_head));
    356 
    357         unsigned long key[] = {
    358                 [NODES_KEY_DEV] = nodep->devmap_handle,
     347        assert(list_empty(&nodep->cs_list));
     348
     349        unsigned long key[] = {
     350                [NODES_KEY_DEV] = nodep->service_id,
    359351                [NODES_KEY_INDEX] = nodep->index
    360352        };
     
    373365        tmpfs_node_t *childp = TMPFS_NODE(cfn);
    374366        tmpfs_dentry_t *dentryp;
    375         link_t *lnk;
    376367
    377368        assert(parentp->type == TMPFS_DIRECTORY);
    378369
    379370        /* Check for duplicit entries. */
    380         for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
    381             lnk = lnk->next) {
     371        list_foreach(parentp->cs_list, lnk) {
    382372                dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
    383373                if (!str_cmp(dentryp->name, nm))
     
    401391        dentryp->node = childp;
    402392        childp->lnkcnt++;
    403         list_append(&dentryp->link, &parentp->cs_head);
     393        list_append(&dentryp->link, &parentp->cs_list);
    404394
    405395        return EOK;
     
    411401        tmpfs_node_t *childp = NULL;
    412402        tmpfs_dentry_t *dentryp;
    413         link_t *lnk;
    414403
    415404        if (!parentp)
    416405                return EBUSY;
    417406       
    418         for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
    419             lnk = lnk->next) {
     407        list_foreach(parentp->cs_list, lnk) {
    420408                dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
    421409                if (!str_cmp(dentryp->name, nm)) {
     
    423411                        assert(FS_NODE(childp) == cfn);
    424412                        break;
    425                 }       
     413                }
    426414        }
    427415
     
    429417                return ENOENT;
    430418               
    431         if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
     419        if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_list))
    432420                return ENOTEMPTY;
    433421
     
    439427}
    440428
    441 void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    442 {
    443         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     429/*
     430 * Implementation of the VFS_OUT interface.
     431 */
     432
     433static int
     434tmpfs_mounted(service_id_t service_id, const char *opts,
     435    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
     436{
    444437        fs_node_t *rootfn;
    445438        int rc;
    446439       
    447         /* Accept the mount options. */
    448         char *opts;
    449         rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
    450         if (rc != EOK) {
    451                 async_answer_0(rid, rc);
    452                 return;
    453         }
    454 
    455440        /* Check if this device is not already mounted. */
    456         rc = tmpfs_root_get(&rootfn, devmap_handle);
     441        rc = tmpfs_root_get(&rootfn, service_id);
    457442        if ((rc == EOK) && (rootfn)) {
    458443                (void) tmpfs_node_put(rootfn);
    459                 free(opts);
    460                 async_answer_0(rid, EEXIST);
    461                 return;
     444                return EEXIST;
    462445        }
    463446
    464447        /* Initialize TMPFS instance. */
    465         if (!tmpfs_instance_init(devmap_handle)) {
    466                 free(opts);
    467                 async_answer_0(rid, ENOMEM);
    468                 return;
    469         }
    470 
    471         rc = tmpfs_root_get(&rootfn, devmap_handle);
     448        if (!tmpfs_instance_init(service_id))
     449                return ENOMEM;
     450
     451        rc = tmpfs_root_get(&rootfn, service_id);
    472452        assert(rc == EOK);
    473453        tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
    474454        if (str_cmp(opts, "restore") == 0) {
    475                 if (tmpfs_restore(devmap_handle))
    476                         async_answer_3(rid, EOK, rootp->index, rootp->size,
    477                             rootp->lnkcnt);
    478                 else
    479                         async_answer_0(rid, ELIMIT);
    480         } else {
    481                 async_answer_3(rid, EOK, rootp->index, rootp->size,
    482                     rootp->lnkcnt);
    483         }
    484         free(opts);
    485 }
    486 
    487 void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
    488 {
    489         libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
    490 }
    491 
    492 void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
    493 {
    494         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    495 
    496         tmpfs_instance_done(devmap_handle);
    497         async_answer_0(rid, EOK);
    498 }
    499 
    500 void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
    501 {
    502         libfs_unmount(&tmpfs_libfs_ops, rid, request);
    503 }
    504 
    505 void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    506 {
    507         libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
    508 }
    509 
    510 void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
    511 {
    512         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    513         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    514         aoff64_t pos =
    515             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    516        
     455                if (!tmpfs_restore(service_id))
     456                        return ELIMIT;
     457        }
     458
     459        *index = rootp->index;
     460        *size = rootp->size;
     461        *lnkcnt = rootp->lnkcnt;
     462
     463        return EOK;
     464}
     465
     466static int tmpfs_unmounted(service_id_t service_id)
     467{
     468        tmpfs_instance_done(service_id);
     469        return EOK;
     470}
     471
     472static int tmpfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
     473    size_t *rbytes)
     474{
    517475        /*
    518476         * Lookup the respective TMPFS node.
     
    520478        link_t *hlp;
    521479        unsigned long key[] = {
    522                 [NODES_KEY_DEV] = devmap_handle,
     480                [NODES_KEY_DEV] = service_id,
    523481                [NODES_KEY_INDEX] = index
    524482        };
    525483        hlp = hash_table_find(&nodes, key);
    526         if (!hlp) {
    527                 async_answer_0(rid, ENOENT);
    528                 return;
    529         }
     484        if (!hlp)
     485                return ENOENT;
    530486        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    531487            nh_link);
     
    538494        if (!async_data_read_receive(&callid, &size)) {
    539495                async_answer_0(callid, EINVAL);
    540                 async_answer_0(rid, EINVAL);
    541                 return;
     496                return EINVAL;
    542497        }
    543498
     
    550505                tmpfs_dentry_t *dentryp;
    551506                link_t *lnk;
    552                 aoff64_t i;
    553507               
    554508                assert(nodep->type == TMPFS_DIRECTORY);
     
    559513                 * hash table.
    560514                 */
    561                 for (i = 0, lnk = nodep->cs_head.next;
    562                     (i < pos) && (lnk != &nodep->cs_head);
    563                     i++, lnk = lnk->next)
    564                         ;
    565 
    566                 if (lnk == &nodep->cs_head) {
     515                lnk = list_nth(&nodep->cs_list, pos);
     516               
     517                if (lnk == NULL) {
    567518                        async_answer_0(callid, ENOENT);
    568                         async_answer_1(rid, ENOENT, 0);
    569                         return;
     519                        return ENOENT;
    570520                }
    571521
     
    577527        }
    578528
    579         /*
    580          * Answer the VFS_READ call.
    581          */
    582         async_answer_1(rid, EOK, bytes);
    583 }
    584 
    585 void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
    586 {
    587         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    588         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    589         aoff64_t pos =
    590             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    591        
     529        *rbytes = bytes;
     530        return EOK;
     531}
     532
     533static int
     534tmpfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
     535    size_t *wbytes, aoff64_t *nsize)
     536{
    592537        /*
    593538         * Lookup the respective TMPFS node.
     
    595540        link_t *hlp;
    596541        unsigned long key[] = {
    597                 [NODES_KEY_DEV] = devmap_handle,
     542                [NODES_KEY_DEV] = service_id,
    598543                [NODES_KEY_INDEX] = index
    599544        };
    600545        hlp = hash_table_find(&nodes, key);
    601         if (!hlp) {
    602                 async_answer_0(rid, ENOENT);
    603                 return;
    604         }
     546        if (!hlp)
     547                return ENOENT;
    605548        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    606549            nh_link);
     
    613556        if (!async_data_write_receive(&callid, &size)) {
    614557                async_answer_0(callid, EINVAL);
    615                 async_answer_0(rid, EINVAL);
    616                 return;
     558                return EINVAL;
    617559        }
    618560
     
    622564        if (pos + size <= nodep->size) {
    623565                /* The file size is not changing. */
    624                 (void) async_data_write_finalize(callid, nodep->data + pos, size);
    625                 async_answer_2(rid, EOK, size, nodep->size);
    626                 return;
     566                (void) async_data_write_finalize(callid, nodep->data + pos,
     567                    size);
     568                goto out;
    627569        }
    628570        size_t delta = (pos + size) - nodep->size;
     
    637579        if (!newdata) {
    638580                async_answer_0(callid, ENOMEM);
    639                 async_answer_2(rid, EOK, 0, nodep->size);
    640                 return;
     581                size = 0;
     582                goto out;
    641583        }
    642584        /* Clear any newly allocated memory in order to emulate gaps. */
     
    645587        nodep->data = newdata;
    646588        (void) async_data_write_finalize(callid, nodep->data + pos, size);
    647         async_answer_2(rid, EOK, size, nodep->size);
    648 }
    649 
    650 void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
    651 {
    652         devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    653         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    654         aoff64_t size =
    655             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
    656        
     589
     590out:
     591        *wbytes = size;
     592        *nsize = nodep->size;
     593        return EOK;
     594}
     595
     596static int tmpfs_truncate(service_id_t service_id, fs_index_t index,
     597    aoff64_t size)
     598{
    657599        /*
    658600         * Lookup the respective TMPFS node.
    659601         */
    660602        unsigned long key[] = {
    661                 [NODES_KEY_DEV] = devmap_handle,
     603                [NODES_KEY_DEV] = service_id,
    662604                [NODES_KEY_INDEX] = index
    663605        };
    664606        link_t *hlp = hash_table_find(&nodes, key);
    665         if (!hlp) {
    666                 async_answer_0(rid, ENOENT);
    667                 return;
    668         }
    669         tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    670             nh_link);
    671        
    672         if (size == nodep->size) {
    673                 async_answer_0(rid, EOK);
    674                 return;
    675         }
    676        
    677         if (size > SIZE_MAX) {
    678                 async_answer_0(rid, ENOMEM);
    679                 return;
    680         }
     607        if (!hlp)
     608                return ENOENT;
     609        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
     610       
     611        if (size == nodep->size)
     612                return EOK;
     613       
     614        if (size > SIZE_MAX)
     615                return ENOMEM;
    681616       
    682617        void *newdata = realloc(nodep->data, size);
    683         if (!newdata) {
    684                 async_answer_0(rid, ENOMEM);
    685                 return;
    686         }
     618        if (!newdata)
     619                return ENOMEM;
    687620       
    688621        if (size > nodep->size) {
     
    693626        nodep->size = size;
    694627        nodep->data = newdata;
    695         async_answer_0(rid, EOK);
    696 }
    697 
    698 void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
    699 {
    700         async_answer_0(rid, EOK);
    701 }
    702 
    703 void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
    704 {
    705         devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
    706         fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
    707         int rc;
    708 
     628        return EOK;
     629}
     630
     631static int tmpfs_close(service_id_t service_id, fs_index_t index)
     632{
     633        return EOK;
     634}
     635
     636static int tmpfs_destroy(service_id_t service_id, fs_index_t index)
     637{
    709638        link_t *hlp;
    710639        unsigned long key[] = {
    711                 [NODES_KEY_DEV] = devmap_handle,
     640                [NODES_KEY_DEV] = service_id,
    712641                [NODES_KEY_INDEX] = index
    713642        };
    714643        hlp = hash_table_find(&nodes, key);
    715         if (!hlp) {
    716                 async_answer_0(rid, ENOENT);
    717                 return;
    718         }
     644        if (!hlp)
     645                return ENOENT;
    719646        tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
    720647            nh_link);
    721         rc = tmpfs_destroy_node(FS_NODE(nodep));
    722         async_answer_0(rid, rc);
    723 }
    724 
    725 void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
    726 {
    727         libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
    728 }
    729 
    730 void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
    731 {
    732         libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
    733 }
    734 
    735 void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
     648        return tmpfs_destroy_node(FS_NODE(nodep));
     649}
     650
     651static int tmpfs_sync(service_id_t service_id, fs_index_t index)
    736652{
    737653        /*
     
    739655         * thus the sync operation is a no-op.
    740656         */
    741         async_answer_0(rid, EOK);
    742 }
     657        return EOK;
     658}
     659
     660vfs_out_ops_t tmpfs_ops = {
     661        .mounted = tmpfs_mounted,
     662        .unmounted = tmpfs_unmounted,
     663        .read = tmpfs_read,
     664        .write = tmpfs_write,
     665        .truncate = tmpfs_truncate,
     666        .close = tmpfs_close,
     667        .destroy = tmpfs_destroy,
     668        .sync = tmpfs_sync,
     669};
    743670
    744671/**
    745672 * @}
    746673 */
     674
Note: See TracChangeset for help on using the changeset viewer.