Changeset d79dcdb in mainline for uspace/srv/vfs/vfs.c


Ignore:
Timestamp:
2007-09-15T08:54:35Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4ec91b2f
Parents:
183b4a0
Message:

VFS work.

Now, each VFS connection fibril will accept requests in a loop. The idea is that
each connection will be potentially reused for multiple requests before it is
closed by the server.

More VFS_REGISTER bits. Make use of the IPC_M_DATA_SEND wrappers introduced in
the previous commit.

Add enum members for more VFS operations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs.c

    r183b4a0 rd79dcdb  
    4040#include <async.h>
    4141#include <errno.h>
     42#include <stdlib.h>
     43#include <bool.h>
    4244#include "vfs.h"
    4345
    44 static void vfs_register(ipc_callid_t iid, ipc_call_t *icall)
     46/** Verify the VFS info structure.
     47 *
     48 * @param info          Info structure to be verified.
     49 *
     50 * @return              Non-zero if the info structure is sane, zero otherwise.
     51 */
     52static int vfs_info_sane(vfs_info_t *info)
     53{
     54        return 1;       /* XXX */
     55}
     56
     57/** VFS_REGISTER protocol function.
     58 *
     59 * @param rid           Hash of the call with the request.
     60 * @param request       Call structure with the request.
     61 */
     62static void vfs_register(ipc_callid_t rid, ipc_call_t *request)
    4563{
    4664        ipc_callid_t callid;
    4765        ipc_call_t call;
     66        int rc;
     67        size_t size;
    4868
    49         callid = async_get_call(&call);
    50         if (IPC_GET_METHOD(call) == IPC_M_DATA_SEND) {
    51                 size_t size = IPC_GET_ARG3(call);
    52                 if (size != sizeof(vfs_info_t)) {
    53                         /*
    54                          * The client is sending us something, which cannot be
    55                          * the info structure.
    56                          */
    57                         ipc_answer_fast(iid, EINVAL, 0, 0);
    58                         ipc_answer_fast(callid, EINVAL, 0, 0);
    59                         return;
    60                 }
    61                 /*
    62                  * XXX: continue here
    63                  * Allocate an info structue, answer the call, check sanity
    64                  * of the copied-in info structure, ...
    65                  */
    66         } else {
     69        /*
     70         * The first call has to be IPC_M_DATA_SEND in which we receive the
     71         * VFS info structure from the client FS.
     72         */
     73        if (!ipc_data_send_accept(&callid, &call, NULL, &size)) {
    6774                /*
    6875                 * The client doesn't obey the same protocol as we do.
    6976                 */
    70                 ipc_answer_fast(iid, EINVAL, 0, 0);
    7177                ipc_answer_fast(callid, EINVAL, 0, 0);
     78                ipc_answer_fast(rid, EINVAL, 0, 0);
    7279                return;
    7380        }
     81       
     82        /*
     83         * We know the size of the info structure. See if the client understands
     84         * this easy concept too.
     85         */
     86        if (size != sizeof(vfs_info_t)) {
     87                /*
     88                 * The client is sending us something, which cannot be
     89                 * the info structure.
     90                 */
     91                ipc_answer_fast(callid, EINVAL, 0, 0);
     92                ipc_answer_fast(rid, EINVAL, 0, 0);
     93                return;
     94        }
     95        vfs_info_t *info;
     96
     97        /*
     98         * Allocate a buffer for the info structure.
     99         */
     100        info = (vfs_info_t *) malloc(sizeof(vfs_info_t));
     101        if (!info) {
     102                ipc_answer_fast(callid, ENOMEM, 0, 0);
     103                ipc_answer_fast(rid, ENOMEM, 0, 0);
     104                return;
     105        }
     106               
     107        rc = ipc_data_send_answer(callid, &call, info, size);
     108        if (!rc) {
     109                free(info);
     110                ipc_answer_fast(callid, rc, 0, 0);
     111                ipc_answer_fast(rid, rc, 0, 0);
     112                return;
     113        }
     114               
     115        if (!vfs_info_sane(info)) {
     116                free(info);
     117                ipc_answer_fast(callid, EINVAL, 0, 0);
     118                ipc_answer_fast(rid, EINVAL, 0, 0);
     119                return;
     120        }
     121               
    74122}
    75123
    76124static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
    77125{
    78         ipcarg_t iarg1, iarg2;
     126        bool keep_on_going = 1;
    79127
    80128        /*
    81129         * The connection was opened via the IPC_CONNECT_ME_TO call.
    82130         * This call needs to be answered.
    83          *
    84          * The protocol is that the requested action is specified in ARG1
    85          * of the opening call. If the request has a single integer argument,
    86          * it is passed in ARG2.
    87131         */
    88         iarg1 = IPC_GET_ARG1(*icall);
    89         iarg2 = IPC_GET_ARG2(*icall);
     132        ipc_answer_fast(iid, EOK, 0, 0);
    90133
    91134        /*
    92          * Now, the connection can either be from an individual FS,
    93          * which is trying to register itself and pass us its capabilities.
    94          * Or, the connection is a regular connection from a client that wants
    95          * us to do something for it (e.g. open a file, mount a fs etc.).
     135         * Here we enter the main connection fibril loop.
     136         * The logic behind this loop and the protocol is that we'd like to keep
     137         * each connection open for a while before we close it. The benefit of
     138         * this is that the client doesn't have to establish a new connection
     139         * upon each request.  On the other hand, the client must be ready to
     140         * re-establish a connection if we hang it up due to reaching of maximum
     141         * number of requests per connection or due to the client timing out.
    96142         */
    97         switch (iarg1) {
    98         case VFS_REGISTER:
    99                 vfs_register(iid, icall);
    100                 break;
    101         case VFS_MOUNT:
    102         case VFS_UNMOUNT:
    103         case VFS_OPEN:
    104         default:
    105                 ipc_answer_fast(iid, ENOTSUP, 0, 0);
    106                 break;
     143         
     144        while (keep_on_going) {
     145                ipc_callid_t callid;
     146                ipc_call_t call;
     147
     148                callid = async_get_call(&call);
     149               
     150                switch (IPC_GET_METHOD(call)) {
     151                case IPC_M_PHONE_HUNGUP:
     152                        keep_on_going = false;
     153                        break;
     154                case VFS_REGISTER:
     155                        vfs_register(callid, &call);
     156                        keep_on_going = false;
     157                        break;
     158                case VFS_MOUNT:
     159                case VFS_UNMOUNT:
     160                case VFS_OPEN:
     161                case VFS_CREATE:
     162                case VFS_CLOSE:
     163                case VFS_READ:
     164                case VFS_WRITE:
     165                case VFS_SEEK:
     166                default:
     167                        ipc_answer_fast(callid, ENOTSUP, 0, 0);
     168                        break;
     169                }
    107170        }
     171
     172        /* TODO: cleanup after the client */
     173       
    108174}
    109175
Note: See TracChangeset for help on using the changeset viewer.