Changeset 8dc72b64 in mainline


Ignore:
Timestamp:
2009-03-02T17:37:19Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
16da5f8e
Parents:
6519d6f
Message:

support for pending (blocking) mounts (waiting for the presence of the filesystem implementation)
the mount point and filesystem type arguments of VFS_MOUNT were swapped, the IPC_M_PING was eliminated
small cleanups

Location:
uspace/srv/vfs
Files:
4 edited

Legend:

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

    r6519d6f r8dc72b64  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
    34  * @file        vfs.c
    35  * @brief       VFS service for HelenOS.
     34 * @file vfs.c
     35 * @brief VFS service for HelenOS.
    3636 */
    3737
     
    5252static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
    5353{
    54         bool keep_on_going = 1;
    55 
     54        bool keep_on_going = true;
     55       
    5656        /*
    5757         * The connection was opened via the IPC_CONNECT_ME_TO call.
     
    5959         */
    6060        ipc_answer_0(iid, EOK);
    61 
     61       
    6262        /*
    6363         * Here we enter the main connection fibril loop.
     
    7171         */
    7272        while (keep_on_going) {
    73                 ipc_callid_t callid;
    7473                ipc_call_t call;
     74                ipc_callid_t callid = async_get_call(&call);
     75               
     76                fs_handle_t fs_handle;
    7577                int phone;
    76                 fs_handle_t fs_handle;
    77 
    78                 callid = async_get_call(&call);
    79 
     78               
    8079                switch (IPC_GET_METHOD(call)) {
    8180                case IPC_M_PHONE_HUNGUP:
     
    140139                }
    141140        }
    142 
     141       
    143142        /* TODO: cleanup after the client */
    144        
    145143}
    146144
    147145int main(int argc, char **argv)
    148146{
    149         ipcarg_t phonead;
    150 
    151147        printf(NAME ": HelenOS VFS server\n");
    152 
     148       
    153149        /*
    154150         * Initialize the list of registered file systems.
    155151         */
    156152        list_initialize(&fs_head);
    157 
     153       
    158154        /*
    159155         * Initialize VFS node hash table.
     
    163159                return ENOMEM;
    164160        }
    165 
     161       
    166162        /*
    167163         * Allocate and initialize the Path Lookup Buffer.
     
    173169                return ENOMEM;
    174170        }
     171       
    175172        if (as_area_create(plb, PLB_SIZE, AS_AREA_READ | AS_AREA_WRITE |
    176173            AS_AREA_CACHEABLE) != plb) {
     
    184181         */
    185182        async_set_client_connection(vfs_connection);
    186 
     183       
    187184        /*
    188185         * Register at the naming service.
    189186         */
     187        ipcarg_t phonead;
    190188        ipc_connect_to_me(PHONE_NS, SERVICE_VFS, 0, 0, &phonead);
    191 
     189       
    192190        /*
    193191         * Start accepting connections.
     
    200198/**
    201199 * @}
    202  */ 
     200 */
  • uspace/srv/vfs/vfs.h

    r6519d6f r8dc72b64  
    283283extern void vfs_node_delref(vfs_node_t *);
    284284
     285extern void vfs_process_pending_mount(void);
    285286extern void vfs_register(ipc_callid_t, ipc_call_t *);
    286287extern void vfs_mount(ipc_callid_t, ipc_call_t *);
  • uspace/srv/vfs/vfs_ops.c

    r6519d6f r8dc72b64  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
    34  * @file        vfs_ops.c
    35  * @brief       Operations that VFS offers to its clients.
     34 * @file vfs_ops.c
     35 * @brief Operations that VFS offers to its clients.
    3636 */
    3737
     
    5656static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);
    5757
     58/** Pending mount structure. */
     59typedef struct {
     60        link_t link;
     61        char *fs_name;            /**< File system name */
     62        char *mp;                 /**< Mount point */
     63        ipc_callid_t callid;      /**< Call ID waiting for the mount */
     64        ipc_callid_t rid;         /**< Request ID */
     65        dev_handle_t dev_handle;  /**< Device handle */
     66} pending_req_t;
     67
     68LIST_INITIALIZE(pending_req);
     69
    5870/**
    5971 * This rwlock prevents the race between a triplet-to-VFS-node resolution and a
     
    6880};
    6981
    70 void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
    71 {
    72         dev_handle_t dev_handle;
     82static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle,
     83    fs_handle_t fs_handle, char *mp)
     84{
     85        /* Resolve the path to the mountpoint. */
     86        vfs_lookup_res_t mp_res;
    7387        vfs_node_t *mp_node = NULL;
    74         ipc_callid_t callid;
    75         ipc_call_t data;
    7688        int rc;
    7789        int phone;
    78         size_t size;
    79 
    80         /*
    81          * We expect the library to do the device-name to device-handle
    82          * translation for us, thus the device handle will arrive as ARG1
    83          * in the request.
    84          */
    85         dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
    86 
    87         /*
    88          * For now, don't make use of ARG2 and ARG3, but they can be used to
    89          * carry mount options in the future.
    90          */
    91 
    92         /*
    93          * Now, we expect the client to send us data with the name of the file
    94          * system.
    95          */
    96         if (!ipc_data_write_receive(&callid, &size)) {
    97                 ipc_answer_0(callid, EINVAL);
    98                 ipc_answer_0(rid, EINVAL);
    99                 return;
    100         }
    101 
    102         /*
    103          * Don't receive more than is necessary for storing a full file system
    104          * name.
    105          */
    106         if (size < 1 || size > FS_NAME_MAXLEN) {
    107                 ipc_answer_0(callid, EINVAL);
    108                 ipc_answer_0(rid, EINVAL);
    109                 return;
    110         }
    111 
    112         /* Deliver the file system name. */
    113         char fs_name[FS_NAME_MAXLEN + 1];
    114         (void) ipc_data_write_finalize(callid, fs_name, size);
    115         fs_name[size] = '\0';
    116        
    117         /*
    118          * Wait for IPC_M_PING so that we can return an error if we don't know
    119          * fs_name.
    120          */
    121         callid = async_get_call(&data);
    122         if (IPC_GET_METHOD(data) != IPC_M_PING) {
    123                 ipc_answer_0(callid, ENOTSUP);
    124                 ipc_answer_0(rid, ENOTSUP);
    125                 return;
    126         }
    127 
    128         /*
    129          * Check if we know a file system with the same name as is in fs_name.
    130          * This will also give us its file system handle.
    131          */
    132         fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
    133         if (!fs_handle) {
    134                 ipc_answer_0(callid, ENOENT);
    135                 ipc_answer_0(rid, ENOENT);
    136                 return;
    137         }
    138 
    139         /* Acknowledge that we know fs_name. */
    140         ipc_answer_0(callid, EOK);
    141 
    142         /* Now, we want the client to send us the mount point. */
    143         if (!ipc_data_write_receive(&callid, &size)) {
    144                 ipc_answer_0(callid, EINVAL);
    145                 ipc_answer_0(rid, EINVAL);
    146                 return;
    147         }
    148 
    149         /* Check whether size is reasonable wrt. the mount point. */
    150         if (size < 1 || size > MAX_PATH_LEN) {
    151                 ipc_answer_0(callid, EINVAL);
    152                 ipc_answer_0(rid, EINVAL);
    153                 return;
    154         }
    155         /* Allocate buffer for the mount point data being received. */
    156         char *buf;
    157         buf = malloc(size + 1);
    158         if (!buf) {
    159                 ipc_answer_0(callid, ENOMEM);
    160                 ipc_answer_0(rid, ENOMEM);
    161                 return;
    162         }
    163 
    164         /* Deliver the mount point. */
    165         (void) ipc_data_write_finalize(callid, buf, size);
    166         buf[size] = '\0';
    167 
    168         /* Resolve the path to the mountpoint. */
    169         vfs_lookup_res_t mp_res;
    17090        futex_down(&rootfs_futex);
    17191        if (rootfs.fs_handle) {
    17292                /* We already have the root FS. */
    17393                rwlock_write_lock(&namespace_rwlock);
    174                 if ((size == 1) && (buf[0] == '/')) {
     94                if ((strlen(mp) == 1) && (mp[0] == '/')) {
    17595                        /* Trying to mount root FS over root FS */
    17696                        rwlock_write_unlock(&namespace_rwlock);
    17797                        futex_up(&rootfs_futex);
    178                         free(buf);
    17998                        ipc_answer_0(rid, EBUSY);
    18099                        return;
    181100                }
    182                 rc = vfs_lookup_internal(buf, L_DIRECTORY, &mp_res, NULL);
     101               
     102                rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
    183103                if (rc != EOK) {
    184104                        /* The lookup failed for some reason. */
    185105                        rwlock_write_unlock(&namespace_rwlock);
    186106                        futex_up(&rootfs_futex);
    187                         free(buf);
    188107                        ipc_answer_0(rid, rc);
    189108                        return;
    190109                }
     110               
    191111                mp_node = vfs_node_get(&mp_res);
    192112                if (!mp_node) {
    193113                        rwlock_write_unlock(&namespace_rwlock);
    194114                        futex_up(&rootfs_futex);
    195                         free(buf);
    196115                        ipc_answer_0(rid, ENOMEM);
    197116                        return;
    198117                }
     118               
    199119                /*
    200120                 * Now we hold a reference to mp_node.
     
    205125        } else {
    206126                /* We still don't have the root file system mounted. */
    207                 if ((size == 1) && (buf[0] == '/')) {
     127                if ((strlen(mp) == 1) && (mp[0] == '/')) {
    208128                        vfs_lookup_res_t mr_res;
    209129                        vfs_node_t *mr_node;
     
    211131                        ipcarg_t rsize;
    212132                        ipcarg_t rlnkcnt;
    213                
     133                       
    214134                        /*
    215135                         * For this simple, but important case,
    216136                         * we are almost done.
    217137                         */
    218                         free(buf);
    219138                       
    220139                        /* Tell the mountee that it is being mounted. */
     
    229148                                return;
    230149                        }
    231 
     150                       
    232151                        mr_res.triplet.fs_handle = fs_handle;
    233152                        mr_res.triplet.dev_handle = dev_handle;
     
    236155                        mr_res.lnkcnt = (unsigned) rlnkcnt;
    237156                        mr_res.type = VFS_NODE_DIRECTORY;
    238 
     157                       
    239158                        rootfs.fs_handle = fs_handle;
    240159                        rootfs.dev_handle = dev_handle;
    241160                        futex_up(&rootfs_futex);
    242 
     161                       
    243162                        /* Add reference to the mounted root. */
    244163                        mr_node = vfs_node_get(&mr_res);
    245164                        assert(mr_node);
    246 
     165                       
    247166                        ipc_answer_0(rid, rc);
    248167                        return;
     
    253172                         */
    254173                        futex_up(&rootfs_futex);
    255                         free(buf);
    256174                        ipc_answer_0(rid, ENOENT);
    257175                        return;
     
    260178        futex_up(&rootfs_futex);
    261179       
    262         free(buf);      /* The buffer is not needed anymore. */
    263        
    264180        /*
    265181         * At this point, we have all necessary pieces: file system and device
    266182         * handles, and we know the mount point VFS node.
    267183         */
    268 
     184       
    269185        phone = vfs_grab_phone(mp_res.triplet.fs_handle);
    270186        rc = async_req_4_0(phone, VFS_MOUNT,
     
    274190            (ipcarg_t) dev_handle);
    275191        vfs_release_phone(phone);
    276 
     192       
    277193        if (rc != EOK) {
    278194                /* Mount failed, drop reference to mp_node. */
     
    282198       
    283199        ipc_answer_0(rid, rc);
     200}
     201
     202/** Process pending mount requests */
     203void vfs_process_pending_mount()
     204{
     205        link_t *cur;
     206       
     207loop:
     208        for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
     209                pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
     210               
     211                fs_handle_t fs_handle = fs_name_to_handle(pr->fs_name, true);
     212                if (!fs_handle)
     213                        continue;
     214               
     215                /* Acknowledge that we know fs_name. */
     216                ipc_answer_0(pr->callid, EOK);
     217               
     218                /* Do the mount */
     219                vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp);
     220               
     221                free(pr->fs_name);
     222                free(pr->mp);
     223                list_remove(cur);
     224                free(pr);
     225                goto loop;
     226        }
     227}
     228
     229void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
     230{
     231        /*
     232         * We expect the library to do the device-name to device-handle
     233         * translation for us, thus the device handle will arrive as ARG1
     234         * in the request.
     235         */
     236        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     237       
     238        /*
     239         * Mount flags are passed as ARG2.
     240         */
     241        unsigned int flags = (unsigned int) IPC_GET_ARG2(*request);
     242       
     243        /*
     244         * For now, don't make use of ARG3, but it can be used to
     245         * carry mount options in the future.
     246         */
     247       
     248        /* We want the client to send us the mount point. */
     249        ipc_callid_t callid;
     250        size_t size;
     251        if (!ipc_data_write_receive(&callid, &size)) {
     252                ipc_answer_0(callid, EINVAL);
     253                ipc_answer_0(rid, EINVAL);
     254                return;
     255        }
     256       
     257        /* Check whether size is reasonable wrt. the mount point. */
     258        if ((size < 1) || (size > MAX_PATH_LEN)) {
     259                ipc_answer_0(callid, EINVAL);
     260                ipc_answer_0(rid, EINVAL);
     261                return;
     262        }
     263       
     264        /* Allocate buffer for the mount point data being received. */
     265        char *mp = malloc(size + 1);
     266        if (!mp) {
     267                ipc_answer_0(callid, ENOMEM);
     268                ipc_answer_0(rid, ENOMEM);
     269                return;
     270        }
     271       
     272        /* Deliver the mount point. */
     273        ipcarg_t retval = ipc_data_write_finalize(callid, mp, size);
     274        if (retval != EOK) {
     275                ipc_answer_0(rid, EREFUSED);
     276                free(mp);
     277                return;
     278        }
     279        mp[size] = '\0';
     280       
     281        /*
     282         * Now, we expect the client to send us data with the name of the file
     283         * system.
     284         */
     285        if (!ipc_data_write_receive(&callid, &size)) {
     286                ipc_answer_0(callid, EINVAL);
     287                ipc_answer_0(rid, EINVAL);
     288                free(mp);
     289                return;
     290        }
     291       
     292        /*
     293         * Don't receive more than is necessary for storing a full file system
     294         * name.
     295         */
     296        if ((size < 1) || (size > FS_NAME_MAXLEN)) {
     297                ipc_answer_0(callid, EINVAL);
     298                ipc_answer_0(rid, EINVAL);
     299                free(mp);
     300                return;
     301        }
     302       
     303        /*
     304         * Allocate buffer for file system name.
     305         */
     306        char *fs_name = (char *) malloc(size + 1);
     307        if (fs_name == NULL) {
     308                ipc_answer_0(callid, ENOMEM);
     309                ipc_answer_0(rid, EREFUSED);
     310                free(mp);
     311                return;
     312        }
     313       
     314        /* Deliver the file system name. */
     315        retval = ipc_data_write_finalize(callid, fs_name, size);
     316        if (retval != EOK) {
     317                ipc_answer_0(rid, EREFUSED);
     318                free(mp);
     319                free(fs_name);
     320                return;
     321        }
     322        fs_name[size] = '\0';
     323       
     324        /*
     325         * Check if we know a file system with the same name as is in fs_name.
     326         * This will also give us its file system handle.
     327         */
     328        fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
     329        if (!fs_handle) {
     330                if (flags & IPC_FLAG_BLOCKING) {
     331                        /* Blocking mount, add to pending list */
     332                        pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
     333                        if (!pr) {
     334                                ipc_answer_0(callid, ENOMEM);
     335                                ipc_answer_0(rid, ENOMEM);
     336                                free(mp);
     337                                free(fs_name);
     338                                return;
     339                        }
     340                       
     341                        pr->fs_name = fs_name;
     342                        pr->mp = mp;
     343                        pr->callid = callid;
     344                        pr->rid = rid;
     345                        pr->dev_handle = dev_handle;
     346                        list_append(&pr->link, &pending_req);
     347                        return;
     348                }
     349               
     350                ipc_answer_0(callid, ENOENT);
     351                ipc_answer_0(rid, ENOENT);
     352                free(mp);
     353                free(fs_name);
     354                return;
     355        }
     356       
     357        /* Acknowledge that we know fs_name. */
     358        ipc_answer_0(callid, EOK);
     359       
     360        /* Do the mount */
     361        vfs_mount_internal(rid, dev_handle, fs_handle, mp);
     362        free(mp);
     363        free(fs_name);
    284364}
    285365
  • uspace/srv/vfs/vfs_register.c

    r6519d6f r8dc72b64  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
    34  * @file        vfs_register.c
     34 * @file vfs_register.c
    3535 * @brief
    3636 */
     
    279279        dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
    280280            FS_NAME_MAXLEN, fs_info->vfs_info.name, fs_info->fs_handle);
     281       
     282        /* Process pending mount requests possibly waiting
     283         * for this filesystem implementation.
     284         */
     285        vfs_process_pending_mount();
    281286}
    282287
Note: See TracChangeset for help on using the changeset viewer.