Changeset 17fd1d4 in mainline


Ignore:
Timestamp:
2009-06-03T18:59:31Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c20aa06
Parents:
05b9912
Message:

devfs rewrite:

  • implement VFS_OPEN_NODE, VFS_DEVICE, VFS_SYNC, VFS_CLOSE
  • connect to underlying device during VFS_LOOKUP (if L_OPEN flag is used) and VFS_OPEN_NODE
  • disconnect from underlying device during VFS_CLOSE
  • forward VFS_READ, VFS_WRITE and VFS_SYNC to the underlying device
  • VFS_DEVICE: return underlying device handle
Location:
uspace/srv/fs/devfs
Files:
3 edited

Legend:

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

    r05b9912 r17fd1d4  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333/**
     
    7575                        devfs_lookup(callid, &call);
    7676                        break;
     77                case VFS_OPEN_NODE:
     78                        devfs_open_node(callid, &call);
     79                        break;
     80                case VFS_DEVICE:
     81                        devfs_device(callid, &call);
     82                        break;
    7783                case VFS_READ:
    7884                        devfs_read(callid, &call);
     
    8389                case VFS_TRUNCATE:
    8490                        devfs_truncate(callid, &call);
     91                        break;
     92                case VFS_CLOSE:
     93                        devfs_close(callid, &call);
     94                        break;
     95                case VFS_SYNC:
     96                        devfs_sync(callid, &call);
    8597                        break;
    8698                case VFS_DESTROY:
     
    123135}
    124136
    125 /** 
     137/**
    126138 * @}
    127139 */
  • uspace/srv/fs/devfs/devfs_ops.c

    r05b9912 r17fd1d4  
    4242#include <string.h>
    4343#include <libfs.h>
     44#include <libadt/hash_table.h>
    4445#include "devfs.h"
    4546#include "devfs_ops.h"
     
    4748#define PLB_GET_CHAR(pos)  (devfs_reg.plb_ro[pos % PLB_SIZE])
    4849
     50/** Opened devices structure */
     51typedef struct {
     52        dev_handle_t handle;
     53        int phone;
     54        size_t refcount;
     55        link_t link;
     56} device_t;
     57
     58/** Hash table of opened devices */
     59static hash_table_t devices;
     60
     61#define DEVICES_KEYS        1
     62#define DEVICES_KEY_HANDLE  0
     63#define DEVICES_BUCKETS     256
     64
     65/* Implementation of hash table interface for the nodes hash table. */
     66static hash_index_t devices_hash(unsigned long key[])
     67{
     68        return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS;
     69}
     70
     71static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
     72{
     73        device_t *dev = hash_table_get_instance(item, device_t, link);
     74        return (dev->handle == (dev_handle_t) key[DEVICES_KEY_HANDLE]);
     75}
     76
     77static void devices_remove_callback(link_t *item)
     78{
     79        free(hash_table_get_instance(item, device_t, link));
     80}
     81
     82static hash_table_operations_t devices_ops = {
     83        .hash = devices_hash,
     84        .compare = devices_compare,
     85        .remove_callback = devices_remove_callback
     86};
     87
    4988bool devfs_init(void)
    5089{
     90        if (!hash_table_create(&devices, DEVICES_BUCKETS,
     91            DEVICES_KEYS, &devices_ops))
     92                return false;
     93       
    5194        if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
    5295                return false;
     
    104147        }
    105148       
    106         /* This is a read-only filesystem */
    107         if ((lflag & L_CREATE) || (lflag & L_LINK) || (lflag & L_UNLINK)) {
     149        if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
    108150                ipc_answer_0(rid, ENOTSUP);
    109151                return;
     
    124166        } else {
    125167                if (lflag & L_FILE) {
    126                         count_t len;
     168                        size_t len;
    127169                        if (last >= first)
    128170                                len = last - first + 1;
     
    136178                        }
    137179                       
    138                         count_t i;
     180                        size_t i;
    139181                        for (i = 0; i < len; i++)
    140182                                name[i] = PLB_GET_CHAR(first + i);
     
    149191                        }
    150192                       
     193                        if (lflag & L_OPEN) {
     194                                unsigned long key[] = {
     195                                        [DEVICES_KEY_HANDLE] = (unsigned long) handle
     196                                };
     197                               
     198                                link_t *lnk = hash_table_find(&devices, key);
     199                                if (lnk == NULL) {
     200                                        int phone = devmap_device_connect(handle, 0);
     201                                        if (phone < 0) {
     202                                                free(name);
     203                                                ipc_answer_0(rid, ENOENT);
     204                                                return;
     205                                        }
     206                                       
     207                                        device_t *dev = (device_t *) malloc(sizeof(device_t));
     208                                        if (dev == NULL) {
     209                                                free(name);
     210                                                ipc_answer_0(rid, ENOMEM);
     211                                                return;
     212                                        }
     213                                       
     214                                        dev->handle = handle;
     215                                        dev->phone = phone;
     216                                        dev->refcount = 1;
     217                                       
     218                                        hash_table_insert(&devices, key, &dev->link);
     219                                } else {
     220                                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
     221                                        dev->refcount++;
     222                                }
     223                        }
     224                       
    151225                        free(name);
    152226                       
     
    157231}
    158232
     233void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     234{
     235        dev_handle_t handle = IPC_GET_ARG2(*request);
     236       
     237        unsigned long key[] = {
     238                [DEVICES_KEY_HANDLE] = (unsigned long) handle
     239        };
     240       
     241        link_t *lnk = hash_table_find(&devices, key);
     242        if (lnk == NULL) {
     243                int phone = devmap_device_connect(handle, 0);
     244                if (phone < 0) {
     245                        ipc_answer_0(rid, ENOENT);
     246                        return;
     247                }
     248               
     249                device_t *dev = (device_t *) malloc(sizeof(device_t));
     250                if (dev == NULL) {
     251                        ipc_answer_0(rid, ENOMEM);
     252                        return;
     253                }
     254               
     255                dev->handle = handle;
     256                dev->phone = phone;
     257                dev->refcount = 1;
     258               
     259                hash_table_insert(&devices, key, &dev->link);
     260        } else {
     261                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     262                dev->refcount++;
     263        }
     264       
     265        ipc_answer_3(rid, EOK, 0, 1, L_FILE);
     266}
     267
     268void devfs_device(ipc_callid_t rid, ipc_call_t *request)
     269{
     270        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     271       
     272        if (index != 0) {
     273                unsigned long key[] = {
     274                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     275                };
     276               
     277                link_t *lnk = hash_table_find(&devices, key);
     278                if (lnk == NULL) {
     279                        ipc_answer_0(rid, ENOENT);
     280                        return;
     281                }
     282               
     283                ipc_answer_1(rid, EOK, (ipcarg_t) index);
     284        } else
     285                ipc_answer_0(rid, ENOTSUP);
     286}
     287
    159288void devfs_read(ipc_callid_t rid, ipc_call_t *request)
    160289{
     
    163292       
    164293        if (index != 0) {
    165                 ipc_answer_1(rid, ENOENT, 0);
    166                 return;
    167         }
    168        
    169         /*
    170          * Receive the read request.
    171          */
    172         ipc_callid_t callid;
    173         size_t size;
    174         if (!ipc_data_read_receive(&callid, &size)) {
    175                 ipc_answer_0(callid, EINVAL);
    176                 ipc_answer_0(rid, EINVAL);
    177                 return;
    178         }
    179        
    180         size_t bytes = 0;
    181         if (index != 0) {
    182                 (void) ipc_data_read_finalize(callid, NULL, bytes);
     294                unsigned long key[] = {
     295                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     296                };
     297               
     298                link_t *lnk = hash_table_find(&devices, key);
     299                if (lnk == NULL) {
     300                        ipc_answer_0(rid, ENOENT);
     301                        return;
     302                }
     303               
     304                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     305               
     306                ipc_callid_t callid;
     307                if (!ipc_data_read_receive(&callid, NULL)) {
     308                        ipc_answer_0(callid, EINVAL);
     309                        ipc_answer_0(rid, EINVAL);
     310                        return;
     311                }
     312               
     313                /* Make a request at the driver */
     314                ipc_call_t answer;
     315                aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
     316                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
     317                    IPC_GET_ARG3(*request), &answer);
     318               
     319                /* Forward the IPC_M_DATA_READ request to the driver */
     320                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     321               
     322                /* Wait for reply from the driver. */
     323                ipcarg_t rc;
     324                async_wait_for(msg, &rc);
     325                size_t bytes = IPC_GET_ARG1(answer);
     326               
     327                /* Driver reply is the final result of the whole operation */
     328                ipc_answer_1(rid, rc, bytes);
    183329        } else {
    184                 count_t count = devmap_device_get_count();
     330                ipc_callid_t callid;
     331                size_t size;
     332                if (!ipc_data_read_receive(&callid, &size)) {
     333                        ipc_answer_0(callid, EINVAL);
     334                        ipc_answer_0(rid, EINVAL);
     335                        return;
     336                }
     337               
     338                size_t count = devmap_device_get_count();
    185339                dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
    186340                if (desc == NULL) {
    187                         ipc_answer_0(callid, ENOENT);
    188                         ipc_answer_1(rid, ENOENT, 0);
    189                         return;
    190                 }
    191                
    192                 count_t max = devmap_device_get_devices(count, desc);
     341                        ipc_answer_0(callid, ENOMEM);
     342                        ipc_answer_1(rid, ENOMEM, 0);
     343                        return;
     344                }
     345               
     346                size_t max = devmap_device_get_devices(count, desc);
    193347               
    194348                if (pos < max) {
     
    201355               
    202356                free(desc);
    203                 bytes = 1;
    204         }
    205        
    206         ipc_answer_1(rid, EOK, bytes);
     357               
     358                ipc_answer_1(rid, EOK, 1);
     359        }
    207360}
    208361
     
    212365        off_t pos = (off_t) IPC_GET_ARG3(*request);
    213366       
    214         /*
    215          * Receive the write request.
    216          */
    217         ipc_callid_t callid;
    218         size_t size;
    219         if (!ipc_data_write_receive(&callid, &size)) {
    220                 ipc_answer_0(callid, EINVAL);
    221                 ipc_answer_0(rid, EINVAL);
    222                 return;
    223         }
    224        
    225         // TODO
    226         ipc_answer_0(callid, ENOENT);
    227         ipc_answer_2(rid, ENOENT, 0, 0);
     367        if (index != 0) {
     368                unsigned long key[] = {
     369                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     370                };
     371               
     372                link_t *lnk = hash_table_find(&devices, key);
     373                if (lnk == NULL) {
     374                        ipc_answer_0(rid, ENOENT);
     375                        return;
     376                }
     377               
     378                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     379               
     380                ipc_callid_t callid;
     381                if (!ipc_data_write_receive(&callid, NULL)) {
     382                        ipc_answer_0(callid, EINVAL);
     383                        ipc_answer_0(rid, EINVAL);
     384                        return;
     385                }
     386               
     387                /* Make a request at the driver */
     388                ipc_call_t answer;
     389                aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
     390                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
     391                    IPC_GET_ARG3(*request), &answer);
     392               
     393                /* Forward the IPC_M_DATA_WRITE request to the driver */
     394                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     395               
     396                /* Wait for reply from the driver. */
     397                ipcarg_t rc;
     398                async_wait_for(msg, &rc);
     399                size_t bytes = IPC_GET_ARG1(answer);
     400               
     401                /* Driver reply is the final result of the whole operation */
     402                ipc_answer_1(rid, rc, bytes);
     403        } else {
     404                /* Read-only filesystem */
     405                ipc_answer_0(rid, ENOTSUP);
     406        }
    228407}
    229408
     
    231410{
    232411        ipc_answer_0(rid, ENOTSUP);
     412}
     413
     414void devfs_close(ipc_callid_t rid, ipc_call_t *request)
     415{
     416        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     417       
     418        if (index != 0) {
     419                unsigned long key[] = {
     420                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     421                };
     422               
     423                link_t *lnk = hash_table_find(&devices, key);
     424                if (lnk == NULL) {
     425                        ipc_answer_0(rid, ENOENT);
     426                        return;
     427                }
     428               
     429                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     430                dev->refcount--;
     431               
     432                if (dev->refcount == 0) {
     433                        ipc_hangup(dev->phone);
     434                        hash_table_remove(&devices, key, DEVICES_KEYS);
     435                }
     436               
     437                ipc_answer_0(rid, EOK);
     438        } else
     439                ipc_answer_0(rid, ENOTSUP);
     440}
     441
     442void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
     443{
     444        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     445       
     446        if (index != 0) {
     447                unsigned long key[] = {
     448                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     449                };
     450               
     451                link_t *lnk = hash_table_find(&devices, key);
     452                if (lnk == NULL) {
     453                        ipc_answer_0(rid, ENOENT);
     454                        return;
     455                }
     456               
     457                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     458               
     459                /* Make a request at the driver */
     460                ipc_call_t answer;
     461                aid_t msg = async_send_2(dev->phone, IPC_GET_METHOD(*request),
     462                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
     463               
     464                /* Wait for reply from the driver */
     465                ipcarg_t rc;
     466                async_wait_for(msg, &rc);
     467               
     468                /* Driver reply is the final result of the whole operation */
     469                ipc_answer_0(rid, rc);
     470        } else
     471                ipc_answer_0(rid, ENOTSUP);
    233472}
    234473
     
    240479/**
    241480 * @}
    242  */ 
     481 */
  • uspace/srv/fs/devfs/devfs_ops.h

    r05b9912 r17fd1d4  
    2929/** @addtogroup fs
    3030 * @{
    31  */ 
     31 */
    3232
    3333#ifndef DEVFS_DEVFS_OPS_H_
     
    4242extern void devfs_mount(ipc_callid_t, ipc_call_t *);
    4343extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
     44extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
     45extern void devfs_device(ipc_callid_t, ipc_call_t *);
     46extern void devfs_sync(ipc_callid_t, ipc_call_t *);
    4447extern void devfs_read(ipc_callid_t, ipc_call_t *);
    4548extern void devfs_write(ipc_callid_t, ipc_call_t *);
    4649extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
     50extern void devfs_close(ipc_callid_t, ipc_call_t *);
    4751extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
    4852
Note: See TracChangeset for help on using the changeset viewer.