Changeset efcebe1 in mainline for uspace/lib/fs/libfs.c


Ignore:
Timestamp:
2011-07-24T23:15:42Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
358dc13, 3fb0fec
Parents:
6a44ee4
Message:

Get rid of per filesystem VFS_OUT method switch and IPC unmarshalling.

  • libfs now understands the notion of VFS_OUT operations and provides the single version of the switch
  • libfs now automatically takes care of some libfs provided operations, such as lookup and stat; filesystem need not be even aware of these
  • one filesystem time per libfs instance
  • plb_get_char() no longer a libfs operation
  • filesystem implemenations need not worry about IPC with the exception of VFS_OUT_READ/WRITE methods and filesystems that depend on doing extra IPC in these and similar methods, such as devfs
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/fs/libfs.c

    r6a44ee4 refcebe1  
    4545#include <mem.h>
    4646#include <sys/stat.h>
     47#include <stdlib.h>
    4748
    4849#define on_error(rc, action) \
     
    6162        } while (0)
    6263
     64static fs_reg_t reg;
     65
     66static vfs_out_ops_t *vfs_out_ops = NULL;
     67static libfs_ops_t *libfs_ops = NULL;
     68
     69static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
     70static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
     71static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     72    ipc_call_t *);
     73static void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
     74static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
     75    ipc_call_t *);
     76
     77static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
     78{
     79        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     80        char *opts;
     81        int rc;
     82       
     83        /* Accept the mount options. */
     84        rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
     85        if (rc != EOK) {
     86                async_answer_0(rid, rc);
     87                return;
     88        }
     89
     90        fs_index_t index;
     91        aoff64_t size;
     92        unsigned lnkcnt;
     93        rc = vfs_out_ops->mounted(devmap_handle, opts, &index, &size, &lnkcnt);
     94
     95        if (rc == EOK)  // FIXME: size is 64-bit
     96                async_answer_3(rid, EOK, index, size, lnkcnt);
     97        else
     98                async_answer_0(rid, rc);
     99
     100        free(opts);
     101}
     102
     103static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
     104{
     105        libfs_mount(libfs_ops, reg.fs_handle, rid, req);
     106}
     107
     108static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
     109{
     110        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     111        int rc;
     112
     113        rc = vfs_out_ops->unmounted(devmap_handle);
     114
     115        async_answer_0(rid, rc);
     116}
     117
     118static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
     119{
     120               
     121        libfs_unmount(libfs_ops, rid, req);
     122}
     123
     124static void vfs_out_lookup(ipc_callid_t rid, ipc_call_t *req)
     125{
     126        libfs_lookup(libfs_ops, reg.fs_handle, rid, req);
     127}
     128
     129static void vfs_out_read(ipc_callid_t rid, ipc_call_t *req)
     130{
     131        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     132        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     133        aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     134            IPC_GET_ARG4(*req));
     135        size_t rbytes;
     136        int rc;
     137
     138        rc = vfs_out_ops->read(devmap_handle, index, pos, &rbytes);
     139
     140        if (rc == EOK)
     141                async_answer_1(rid, EOK, rbytes);
     142        else
     143                async_answer_0(rid, rc);
     144}
     145
     146static void vfs_out_write(ipc_callid_t rid, ipc_call_t *req)
     147{
     148        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     149        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     150        aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     151            IPC_GET_ARG4(*req));
     152        size_t wbytes;
     153        aoff64_t nsize;
     154        int rc;
     155
     156        rc = vfs_out_ops->write(devmap_handle, index, pos, &wbytes, &nsize);
     157
     158        if (rc == EOK)  // FIXME: nsize is 64-bit
     159                async_answer_2(rid, EOK, wbytes, nsize);
     160        else
     161                async_answer_0(rid, rc);
     162}
     163
     164static void vfs_out_truncate(ipc_callid_t rid, ipc_call_t *req)
     165{
     166        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     167        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     168        aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     169            IPC_GET_ARG4(*req));
     170        int rc;
     171
     172        rc = vfs_out_ops->truncate(devmap_handle, index, size);
     173
     174        async_answer_0(rid, rc);
     175}
     176
     177static void vfs_out_close(ipc_callid_t rid, ipc_call_t *req)
     178{
     179        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     180        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     181        int rc;
     182
     183        rc = vfs_out_ops->close(devmap_handle, index);
     184
     185        async_answer_0(rid, rc);
     186}
     187
     188static void vfs_out_destroy(ipc_callid_t rid, ipc_call_t *req)
     189{
     190        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     191        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     192        int rc;
     193
     194        rc = vfs_out_ops->destroy(devmap_handle, index);
     195
     196        async_answer_0(rid, rc);
     197}
     198
     199static void vfs_out_open_node(ipc_callid_t rid, ipc_call_t *req)
     200{
     201        libfs_open_node(libfs_ops, reg.fs_handle, rid, req);
     202}
     203
     204static void vfs_out_stat(ipc_callid_t rid, ipc_call_t *req)
     205{
     206        libfs_stat(libfs_ops, reg.fs_handle, rid, req);
     207}
     208
     209static void vfs_out_sync(ipc_callid_t rid, ipc_call_t *req)
     210{
     211        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     212        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     213        int rc;
     214
     215        rc = vfs_out_ops->sync(devmap_handle, index);
     216
     217        async_answer_0(rid, rc);
     218}
     219
     220static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     221{
     222        if (iid) {
     223                /*
     224                 * This only happens for connections opened by
     225                 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
     226                 * created by IPC_M_CONNECT_TO_ME.
     227                 */
     228                async_answer_0(iid, EOK);
     229        }
     230       
     231        while (true) {
     232                ipc_call_t call;
     233                ipc_callid_t callid = async_get_call(&call);
     234               
     235                if (!IPC_GET_IMETHOD(call))
     236                        return;
     237               
     238                switch (IPC_GET_IMETHOD(call)) {
     239                case VFS_OUT_MOUNTED:
     240                        vfs_out_mounted(callid, &call);
     241                        break;
     242                case VFS_OUT_MOUNT:
     243                        vfs_out_mount(callid, &call);
     244                        break;
     245                case VFS_OUT_UNMOUNTED:
     246                        vfs_out_unmounted(callid, &call);
     247                        break;
     248                case VFS_OUT_UNMOUNT:
     249                        vfs_out_unmount(callid, &call);
     250                        break;
     251                case VFS_OUT_LOOKUP:
     252                        vfs_out_lookup(callid, &call);
     253                        break;
     254                case VFS_OUT_READ:
     255                        vfs_out_read(callid, &call);
     256                        break;
     257                case VFS_OUT_WRITE:
     258                        vfs_out_write(callid, &call);
     259                        break;
     260                case VFS_OUT_TRUNCATE:
     261                        vfs_out_truncate(callid, &call);
     262                        break;
     263                case VFS_OUT_CLOSE:
     264                        vfs_out_close(callid, &call);
     265                        break;
     266                case VFS_OUT_DESTROY:
     267                        vfs_out_destroy(callid, &call);
     268                        break;
     269                case VFS_OUT_OPEN_NODE:
     270                        vfs_out_open_node(callid, &call);
     271                        break;
     272                case VFS_OUT_STAT:
     273                        vfs_out_stat(callid, &call);
     274                        break;
     275                case VFS_OUT_SYNC:
     276                        vfs_out_sync(callid, &call);
     277                        break;
     278                default:
     279                        async_answer_0(callid, ENOTSUP);
     280                        break;
     281                }
     282        }
     283}
     284
    63285/** Register file system server.
    64286 *
     
    68290 *
    69291 * @param sess Session for communication with VFS.
    70  * @param reg  File system registration structure. It will be
    71  *             initialized by this function.
    72292 * @param info VFS info structure supplied by the file system
    73293 *             implementation.
    74  * @param conn Connection fibril for handling all calls originating in
    75  *             VFS.
     294 * @param vops Address of the vfs_out_ops_t structure.
     295 * @param lops Address of the libfs_ops_t structure.
    76296 *
    77297 * @return EOK on success or a non-zero error code on errror.
    78298 *
    79299 */
    80 int fs_register(async_sess_t *sess, fs_reg_t *reg, vfs_info_t *info,
    81     async_client_conn_t conn)
     300int fs_register(async_sess_t *sess, vfs_info_t *info, vfs_out_ops_t *vops,
     301    libfs_ops_t *lops)
    82302{
    83303        /*
     
    104324       
    105325        /*
     326         * Set VFS_OUT and libfs operations.
     327         */
     328        vfs_out_ops = vops;
     329        libfs_ops = lops;
     330
     331        /*
    106332         * Ask VFS for callback connection.
    107333         */
    108         async_connect_to_me(exch, 0, 0, 0, conn, NULL);
     334        async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
    109335       
    110336        /*
    111337         * Allocate piece of address space for PLB.
    112338         */
    113         reg->plb_ro = as_get_mappable_page(PLB_SIZE);
    114         if (!reg->plb_ro) {
     339        reg.plb_ro = as_get_mappable_page(PLB_SIZE);
     340        if (!reg.plb_ro) {
    115341                async_exchange_end(exch);
    116342                async_wait_for(req, NULL);
     
    121347         * Request sharing the Path Lookup Buffer with VFS.
    122348         */
    123         rc = async_share_in_start_0_0(exch, reg->plb_ro, PLB_SIZE);
     349        rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
    124350       
    125351        async_exchange_end(exch);
     
    134360         */
    135361        async_wait_for(req, NULL);
    136         reg->fs_handle = (int) IPC_GET_ARG1(answer);
     362        reg.fs_handle = (int) IPC_GET_ARG1(answer);
    137363       
    138364        /*
     
    140366         * the same connection fibril as well.
    141367         */
    142         async_set_client_connection(conn);
     368        async_set_client_connection(vfs_connection);
    143369       
    144370        return IPC_GET_RETVAL(answer);
     
    151377
    152378void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    153     ipc_call_t *request)
    154 {
    155         devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    156         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
    157         fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
    158         devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*request);
     379    ipc_call_t *req)
     380{
     381        devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     382        fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
     383        fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
     384        devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*req);
    159385       
    160386        async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
     
    212438}
    213439
    214 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
    215 {
    216         devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    217         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
     440void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
     441{
     442        devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     443        fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
    218444        fs_node_t *fn;
    219445        int res;
     
    259485}
    260486
     487static char plb_get_char(unsigned pos)
     488{
     489        return reg.plb_ro[pos % PLB_SIZE];
     490}
     491
    261492/** Lookup VFS triplet by name in the file system name space.
    262493 *
     
    273504 */
    274505void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    275     ipc_call_t *request)
    276 {
    277         unsigned int first = IPC_GET_ARG1(*request);
    278         unsigned int last = IPC_GET_ARG2(*request);
     506    ipc_call_t *req)
     507{
     508        unsigned int first = IPC_GET_ARG1(*req);
     509        unsigned int last = IPC_GET_ARG2(*req);
    279510        unsigned int next = first;
    280         devmap_handle_t devmap_handle = IPC_GET_ARG3(*request);
    281         int lflag = IPC_GET_ARG4(*request);
    282         fs_index_t index = IPC_GET_ARG5(*request);
     511        devmap_handle_t devmap_handle = IPC_GET_ARG3(*req);
     512        int lflag = IPC_GET_ARG4(*req);
     513        fs_index_t index = IPC_GET_ARG5(*req);
    283514        char component[NAME_MAX + 1];
    284515        int len;
     
    298529                async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
    299530                async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
    300                     cur->mp_data.devmap_handle, lflag, index, IPC_FF_ROUTE_FROM_ME);
     531                    cur->mp_data.devmap_handle, lflag, index,
     532                    IPC_FF_ROUTE_FROM_ME);
    301533                async_exchange_end(exch);
    302534               
     
    306538       
    307539        /* Eat slash */
    308         if (ops->plb_get_char(next) == '/')
     540        if (plb_get_char(next) == '/')
    309541                next++;
    310542       
     
    319551                /* Collect the component */
    320552                len = 0;
    321                 while ((next <= last) && (ops->plb_get_char(next) != '/')) {
     553                while ((next <= last) && (plb_get_char(next) != '/')) {
    322554                        if (len + 1 == NAME_MAX) {
    323555                                /* Component length overflow */
     
    325557                                goto out;
    326558                        }
    327                         component[len++] = ops->plb_get_char(next);
     559                        component[len++] = plb_get_char(next);
    328560                        /* Process next character */
    329561                        next++;
     
    357589                       
    358590                        async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
    359                         async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
    360                             tmp->mp_data.devmap_handle, lflag, index,
     591                        async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
     592                            last, tmp->mp_data.devmap_handle, lflag, index,
    361593                            IPC_FF_ROUTE_FROM_ME);
    362594                        async_exchange_end(exch);
     
    451683                        len = 0;
    452684                        while (next <= last) {
    453                                 if (ops->plb_get_char(next) == '/') {
     685                                if (plb_get_char(next) == '/') {
    454686                                        /* More than one component */
    455687                                        async_answer_0(rid, ENOENT);
     
    463695                                }
    464696                               
    465                                 component[len++] = ops->plb_get_char(next);
     697                                component[len++] = plb_get_char(next);
    466698                                /* Process next character */
    467699                                next++;
     
    637869        rc = ops->node_open(fn);
    638870        aoff64_t size = ops->size_get(fn);
    639         async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
     871        async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
     872            ops->lnkcnt_get(fn),
    640873            (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
    641874       
Note: See TracChangeset for help on using the changeset viewer.