Changes in uspace/lib/fs/libfs.c [ffa2c8ef:44451ee] in mainline


Ignore:
File:
1 edited

Legend:

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

    rffa2c8ef r44451ee  
    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)
     96                async_answer_4(rid, EOK, index, LOWER32(size), UPPER32(size),
     97                    lnkcnt);
     98        else
     99                async_answer_0(rid, rc);
     100
     101        free(opts);
     102}
     103
     104static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
     105{
     106        libfs_mount(libfs_ops, reg.fs_handle, rid, req);
     107}
     108
     109static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
     110{
     111        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     112        int rc;
     113
     114        rc = vfs_out_ops->unmounted(devmap_handle);
     115
     116        async_answer_0(rid, rc);
     117}
     118
     119static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
     120{
     121               
     122        libfs_unmount(libfs_ops, rid, req);
     123}
     124
     125static void vfs_out_lookup(ipc_callid_t rid, ipc_call_t *req)
     126{
     127        libfs_lookup(libfs_ops, reg.fs_handle, rid, req);
     128}
     129
     130static void vfs_out_read(ipc_callid_t rid, ipc_call_t *req)
     131{
     132        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     133        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     134        aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     135            IPC_GET_ARG4(*req));
     136        size_t rbytes;
     137        int rc;
     138
     139        rc = vfs_out_ops->read(devmap_handle, index, pos, &rbytes);
     140
     141        if (rc == EOK)
     142                async_answer_1(rid, EOK, rbytes);
     143        else
     144                async_answer_0(rid, rc);
     145}
     146
     147static void vfs_out_write(ipc_callid_t rid, ipc_call_t *req)
     148{
     149        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     150        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     151        aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     152            IPC_GET_ARG4(*req));
     153        size_t wbytes;
     154        aoff64_t nsize;
     155        int rc;
     156
     157        rc = vfs_out_ops->write(devmap_handle, index, pos, &wbytes, &nsize);
     158
     159        if (rc == EOK)
     160                async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
     161        else
     162                async_answer_0(rid, rc);
     163}
     164
     165static void vfs_out_truncate(ipc_callid_t rid, ipc_call_t *req)
     166{
     167        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     168        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     169        aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
     170            IPC_GET_ARG4(*req));
     171        int rc;
     172
     173        rc = vfs_out_ops->truncate(devmap_handle, index, size);
     174
     175        async_answer_0(rid, rc);
     176}
     177
     178static void vfs_out_close(ipc_callid_t rid, ipc_call_t *req)
     179{
     180        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     181        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     182        int rc;
     183
     184        rc = vfs_out_ops->close(devmap_handle, index);
     185
     186        async_answer_0(rid, rc);
     187}
     188
     189static void vfs_out_destroy(ipc_callid_t rid, ipc_call_t *req)
     190{
     191        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     192        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     193        int rc;
     194
     195        rc = vfs_out_ops->destroy(devmap_handle, index);
     196
     197        async_answer_0(rid, rc);
     198}
     199
     200static void vfs_out_open_node(ipc_callid_t rid, ipc_call_t *req)
     201{
     202        libfs_open_node(libfs_ops, reg.fs_handle, rid, req);
     203}
     204
     205static void vfs_out_stat(ipc_callid_t rid, ipc_call_t *req)
     206{
     207        libfs_stat(libfs_ops, reg.fs_handle, rid, req);
     208}
     209
     210static void vfs_out_sync(ipc_callid_t rid, ipc_call_t *req)
     211{
     212        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     213        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
     214        int rc;
     215
     216        rc = vfs_out_ops->sync(devmap_handle, index);
     217
     218        async_answer_0(rid, rc);
     219}
     220
     221static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     222{
     223        if (iid) {
     224                /*
     225                 * This only happens for connections opened by
     226                 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
     227                 * created by IPC_M_CONNECT_TO_ME.
     228                 */
     229                async_answer_0(iid, EOK);
     230        }
     231       
     232        while (true) {
     233                ipc_call_t call;
     234                ipc_callid_t callid = async_get_call(&call);
     235               
     236                if (!IPC_GET_IMETHOD(call))
     237                        return;
     238               
     239                switch (IPC_GET_IMETHOD(call)) {
     240                case VFS_OUT_MOUNTED:
     241                        vfs_out_mounted(callid, &call);
     242                        break;
     243                case VFS_OUT_MOUNT:
     244                        vfs_out_mount(callid, &call);
     245                        break;
     246                case VFS_OUT_UNMOUNTED:
     247                        vfs_out_unmounted(callid, &call);
     248                        break;
     249                case VFS_OUT_UNMOUNT:
     250                        vfs_out_unmount(callid, &call);
     251                        break;
     252                case VFS_OUT_LOOKUP:
     253                        vfs_out_lookup(callid, &call);
     254                        break;
     255                case VFS_OUT_READ:
     256                        vfs_out_read(callid, &call);
     257                        break;
     258                case VFS_OUT_WRITE:
     259                        vfs_out_write(callid, &call);
     260                        break;
     261                case VFS_OUT_TRUNCATE:
     262                        vfs_out_truncate(callid, &call);
     263                        break;
     264                case VFS_OUT_CLOSE:
     265                        vfs_out_close(callid, &call);
     266                        break;
     267                case VFS_OUT_DESTROY:
     268                        vfs_out_destroy(callid, &call);
     269                        break;
     270                case VFS_OUT_OPEN_NODE:
     271                        vfs_out_open_node(callid, &call);
     272                        break;
     273                case VFS_OUT_STAT:
     274                        vfs_out_stat(callid, &call);
     275                        break;
     276                case VFS_OUT_SYNC:
     277                        vfs_out_sync(callid, &call);
     278                        break;
     279                default:
     280                        async_answer_0(callid, ENOTSUP);
     281                        break;
     282                }
     283        }
     284}
     285
    63286/** Register file system server.
    64287 *
     
    67290 * code.
    68291 *
    69  * @param vfs_phone Open phone for communication with VFS.
    70  * @param reg       File system registration structure. It will be
    71  *                  initialized by this function.
    72  * @param info      VFS info structure supplied by the file system
    73  *                  implementation.
    74  * @param conn      Connection fibril for handling all calls originating in
    75  *                  VFS.
     292 * @param sess Session for communication with VFS.
     293 * @param info VFS info structure supplied by the file system
     294 *             implementation.
     295 * @param vops Address of the vfs_out_ops_t structure.
     296 * @param lops Address of the libfs_ops_t structure.
    76297 *
    77298 * @return EOK on success or a non-zero error code on errror.
    78299 *
    79300 */
    80 int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info,
    81     async_client_conn_t conn)
     301int fs_register(async_sess_t *sess, vfs_info_t *info, vfs_out_ops_t *vops,
     302    libfs_ops_t *lops)
    82303{
    83304        /*
     
    86307         * out-of-order, when it knows that the operation succeeded or failed.
    87308         */
     309       
     310        async_exch_t *exch = async_exchange_begin(sess);
     311       
    88312        ipc_call_t answer;
    89         aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
     313        aid_t req = async_send_0(exch, VFS_IN_REGISTER, &answer);
    90314       
    91315        /*
    92316         * Send our VFS info structure to VFS.
    93317         */
    94         int rc = async_data_write_start(vfs_phone, info, sizeof(*info));
     318        int rc = async_data_write_start(exch, info, sizeof(*info));
     319       
    95320        if (rc != EOK) {
     321                async_exchange_end(exch);
    96322                async_wait_for(req, NULL);
    97323                return rc;
     
    99325       
    100326        /*
     327         * Set VFS_OUT and libfs operations.
     328         */
     329        vfs_out_ops = vops;
     330        libfs_ops = lops;
     331
     332        /*
    101333         * Ask VFS for callback connection.
    102334         */
    103         async_connect_to_me(vfs_phone, 0, 0, 0, conn);
     335        async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
    104336       
    105337        /*
    106338         * Allocate piece of address space for PLB.
    107339         */
    108         reg->plb_ro = as_get_mappable_page(PLB_SIZE);
    109         if (!reg->plb_ro) {
     340        reg.plb_ro = as_get_mappable_page(PLB_SIZE);
     341        if (!reg.plb_ro) {
     342                async_exchange_end(exch);
    110343                async_wait_for(req, NULL);
    111344                return ENOMEM;
     
    115348         * Request sharing the Path Lookup Buffer with VFS.
    116349         */
    117         rc = async_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
     350        rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
     351       
     352        async_exchange_end(exch);
     353       
    118354        if (rc) {
    119355                async_wait_for(req, NULL);
     
    125361         */
    126362        async_wait_for(req, NULL);
    127         reg->fs_handle = (int) IPC_GET_ARG1(answer);
     363        reg.fs_handle = (int) IPC_GET_ARG1(answer);
    128364       
    129365        /*
     
    131367         * the same connection fibril as well.
    132368         */
    133         async_set_client_connection(conn);
     369        async_set_client_connection(vfs_connection);
    134370       
    135371        return IPC_GET_RETVAL(answer);
     
    142378
    143379void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    144     ipc_call_t *request)
    145 {
    146         devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    147         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
    148         fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
    149         devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*request);
    150         int res;
    151         sysarg_t rc;
    152        
    153         ipc_call_t call;
    154         ipc_callid_t callid;
    155        
    156         /* Accept the phone */
    157         callid = async_get_call(&call);
    158         int mountee_phone = (int) IPC_GET_ARG1(call);
    159         if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
    160             (mountee_phone < 0)) {
    161                 async_answer_0(callid, EINVAL);
     380    ipc_call_t *req)
     381{
     382        devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     383        fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
     384        fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
     385        devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*req);
     386       
     387        async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
     388        if (mountee_sess == NULL) {
    162389                async_answer_0(rid, EINVAL);
    163390                return;
    164391        }
    165392       
    166         /* Acknowledge the mountee_phone */
    167         async_answer_0(callid, EOK);
    168        
    169393        fs_node_t *fn;
    170         res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
     394        int res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
    171395        if ((res != EOK) || (!fn)) {
    172                 async_hangup(mountee_phone);
     396                async_hangup(mountee_sess);
    173397                async_data_write_void(combine_rc(res, ENOENT));
    174398                async_answer_0(rid, combine_rc(res, ENOENT));
     
    177401       
    178402        if (fn->mp_data.mp_active) {
    179                 async_hangup(mountee_phone);
     403                async_hangup(mountee_sess);
    180404                (void) ops->node_put(fn);
    181405                async_data_write_void(EBUSY);
     
    184408        }
    185409       
    186         rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
    187         if (rc != EOK) {
    188                 async_hangup(mountee_phone);
     410        async_exch_t *exch = async_exchange_begin(mountee_sess);
     411        async_sess_t *sess = async_connect_me(EXCHANGE_PARALLEL, exch);
     412       
     413        if (!sess) {
     414                async_exchange_end(exch);
     415                async_hangup(mountee_sess);
    189416                (void) ops->node_put(fn);
    190                 async_data_write_void(rc);
    191                 async_answer_0(rid, rc);
     417                async_data_write_void(errno);
     418                async_answer_0(rid, errno);
    192419                return;
    193420        }
    194421       
    195422        ipc_call_t answer;
    196         rc = async_data_write_forward_1_1(mountee_phone, VFS_OUT_MOUNTED,
     423        int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED,
    197424            mr_devmap_handle, &answer);
     425        async_exchange_end(exch);
    198426       
    199427        if (rc == EOK) {
     
    201429                fn->mp_data.fs_handle = mr_fs_handle;
    202430                fn->mp_data.devmap_handle = mr_devmap_handle;
    203                 fn->mp_data.phone = mountee_phone;
     431                fn->mp_data.sess = mountee_sess;
    204432        }
    205433       
     
    207435         * Do not release the FS node so that it stays in memory.
    208436         */
    209         async_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
    210             IPC_GET_ARG3(answer));
    211 }
    212 
    213 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
    214 {
    215         devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
    216         fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
     437        async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
     438            IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
     439}
     440
     441void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
     442{
     443        devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*req);
     444        fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
    217445        fs_node_t *fn;
    218446        int res;
     
    236464         * Tell the mounted file system to unmount.
    237465         */
    238         res = async_req_1_0(fn->mp_data.phone, VFS_OUT_UNMOUNTED,
    239             fn->mp_data.devmap_handle);
     466        async_exch_t *exch = async_exchange_begin(fn->mp_data.sess);
     467        res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.devmap_handle);
     468        async_exchange_end(exch);
    240469
    241470        /*
     
    243472         */
    244473        if (res == EOK) {
    245                 async_hangup(fn->mp_data.phone);
     474                async_hangup(fn->mp_data.sess);
    246475                fn->mp_data.mp_active = false;
    247476                fn->mp_data.fs_handle = 0;
    248477                fn->mp_data.devmap_handle = 0;
    249                 fn->mp_data.phone = 0;
     478                fn->mp_data.sess = NULL;
     479               
    250480                /* Drop the reference created in libfs_mount(). */
    251481                (void) ops->node_put(fn);
     
    254484        (void) ops->node_put(fn);
    255485        async_answer_0(rid, res);
     486}
     487
     488static char plb_get_char(unsigned pos)
     489{
     490        return reg.plb_ro[pos % PLB_SIZE];
    256491}
    257492
     
    270505 */
    271506void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
    272     ipc_call_t *request)
    273 {
    274         unsigned int first = IPC_GET_ARG1(*request);
    275         unsigned int last = IPC_GET_ARG2(*request);
     507    ipc_call_t *req)
     508{
     509        unsigned int first = IPC_GET_ARG1(*req);
     510        unsigned int last = IPC_GET_ARG2(*req);
    276511        unsigned int next = first;
    277         devmap_handle_t devmap_handle = IPC_GET_ARG3(*request);
    278         int lflag = IPC_GET_ARG4(*request);
    279         fs_index_t index = IPC_GET_ARG5(*request);
     512        devmap_handle_t devmap_handle = IPC_GET_ARG3(*req);
     513        int lflag = IPC_GET_ARG4(*req);
     514        fs_index_t index = IPC_GET_ARG5(*req);
    280515        char component[NAME_MAX + 1];
    281516        int len;
     
    293528       
    294529        if (cur->mp_data.mp_active) {
    295                 async_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
    296                     next, last, cur->mp_data.devmap_handle, lflag, index,
     530                async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
     531                async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
     532                    cur->mp_data.devmap_handle, lflag, index,
    297533                    IPC_FF_ROUTE_FROM_ME);
     534                async_exchange_end(exch);
     535               
    298536                (void) ops->node_put(cur);
    299537                return;
     
    301539       
    302540        /* Eat slash */
    303         if (ops->plb_get_char(next) == '/')
     541        if (plb_get_char(next) == '/')
    304542                next++;
    305543       
     
    314552                /* Collect the component */
    315553                len = 0;
    316                 while ((next <= last) && (ops->plb_get_char(next) != '/')) {
     554                while ((next <= last) && (plb_get_char(next) != '/')) {
    317555                        if (len + 1 == NAME_MAX) {
    318556                                /* Component length overflow */
     
    320558                                goto out;
    321559                        }
    322                         component[len++] = ops->plb_get_char(next);
     560                        component[len++] = plb_get_char(next);
    323561                        /* Process next character */
    324562                        next++;
     
    351589                                next--;
    352590                       
    353                         async_forward_slow(rid, tmp->mp_data.phone,
    354                             VFS_OUT_LOOKUP, next, last, tmp->mp_data.devmap_handle,
    355                             lflag, index, IPC_FF_ROUTE_FROM_ME);
     591                        async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
     592                        async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
     593                            last, tmp->mp_data.devmap_handle, lflag, index,
     594                            IPC_FF_ROUTE_FROM_ME);
     595                        async_exchange_end(exch);
     596                       
    356597                        (void) ops->node_put(cur);
    357598                        (void) ops->node_put(tmp);
     
    391632                                                if (lflag & L_CREATE)
    392633                                                        (void) ops->destroy(fn);
     634                                                else
     635                                                        (void) ops->node_put(fn);
    393636                                                async_answer_0(rid, rc);
    394637                                        } else {
     
    441684                        len = 0;
    442685                        while (next <= last) {
    443                                 if (ops->plb_get_char(next) == '/') {
     686                                if (plb_get_char(next) == '/') {
    444687                                        /* More than one component */
    445688                                        async_answer_0(rid, ENOENT);
     
    453696                                }
    454697                               
    455                                 component[len++] = ops->plb_get_char(next);
     698                                component[len++] = plb_get_char(next);
    456699                                /* Process next character */
    457700                                next++;
     
    473716                                        if (lflag & L_CREATE)
    474717                                                (void) ops->destroy(fn);
     718                                        else
     719                                                (void) ops->node_put(fn);
    475720                                        async_answer_0(rid, rc);
    476721                                } else {
     
    625870        rc = ops->node_open(fn);
    626871        aoff64_t size = ops->size_get(fn);
    627         async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
     872        async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
     873            ops->lnkcnt_get(fn),
    628874            (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
    629875       
Note: See TracChangeset for help on using the changeset viewer.