Changeset 1313ee9 in mainline for uspace/srv


Ignore:
Timestamp:
2009-12-13T15:17:08Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
963dd91
Parents:
fc6dd18
Message:

introduce device namespaces

  • add support for explicit open in libfs (needed by devfs, but also possibly for other filesystems which need to track some stateful information)
  • extend libfs to be more generic, make proper adjustments to libc, tmpfs and fat
  • various updates to make use of the device namespaces
  • code cleanup
Location:
uspace/srv
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/ata_bd/ata_bd.c

    rfc6dd18 r1313ee9  
    6666#include "ata_bd.h"
    6767
    68 #define NAME "ata_bd"
     68#define NAME       "ata_bd"
     69#define NAMESPACE  "bd"
    6970
    7071/** Physical block size. Should be always 512. */
     
    135136                if (disk[i].present == false)
    136137                        continue;
    137 
    138                 snprintf(name, 16, "disk%d", i);
     138               
     139                snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
    139140                rc = devmap_device_register(name, &disk[i].dev_handle);
    140141                if (rc != EOK) {
    141142                        devmap_hangup_phone(DEVMAP_DRIVER);
    142                         printf(NAME ": Unable to register device %s.\n",
    143                                 name);
     143                        printf(NAME ": Unable to register device %s.\n", name);
    144144                        return rc;
    145145                }
  • uspace/srv/bd/gxe_bd/gxe_bd.c

    rfc6dd18 r1313ee9  
    5050#include <task.h>
    5151
    52 #define NAME "gxe_bd"
     52#define NAME       "gxe_bd"
     53#define NAMESPACE  "bd"
    5354
    5455enum {
     
    141142
    142143        for (i = 0; i < MAX_DISKS; i++) {
    143                 snprintf(name, 16, "disk%d", i);
     144                snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
    144145                rc = devmap_device_register(name, &dev_handle[i]);
    145146                if (rc != EOK) {
    146147                        devmap_hangup_phone(DEVMAP_DRIVER);
    147                         printf(NAME ": Unable to register device %s.\n",
    148                                 name);
     148                        printf(NAME ": Unable to register device %s.\n", name);
    149149                        return rc;
    150150                }
  • uspace/srv/bd/rd/rd.c

    rfc6dd18 r1313ee9  
    228228       
    229229        dev_handle_t dev_handle;
    230         if (devmap_device_register("initrd", &dev_handle) != EOK) {
     230        if (devmap_device_register("bd/initrd", &dev_handle) != EOK) {
    231231                devmap_hangup_phone(DEVMAP_DRIVER);
    232232                printf(NAME ": Unable to register device\n");
  • uspace/srv/console/console.c

    rfc6dd18 r1313ee9  
    5757#include "screenbuffer.h"
    5858
    59 #define NAME  "console"
    60 
    61 #define MAX_DEVICE_NAME  32
     59#define NAME       "console"
     60#define NAMESPACE  "term"
    6261
    6362/** Phone to the keyboard driver. */
     
    6968        ipcarg_t cols;  /**< Framebuffer columns */
    7069        ipcarg_t rows;  /**< Framebuffer rows */
    71         int color_cap;  /**< Color capabilities (FB_CCAP_xxx) */
     70        int color_cap;  /**< Color capabilities (FB_CCAP_xxx) */
    7271} fb_info;
    7372
     
    740739                        consoles[i].refcount = 0;
    741740                       
    742                         char vc[MAX_DEVICE_NAME];
    743                         snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
     741                        char vc[DEVMAP_NAME_MAXLEN + 1];
     742                        snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%u", NAMESPACE, i);
    744743                       
    745744                        if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
  • uspace/srv/devmap/devmap.c

    rfc6dd18 r1313ee9  
    6868} devmap_driver_t;
    6969
     70/** Info about registered namespaces
     71 *
     72 */
     73typedef struct {
     74        /** Pointer to the previous and next device in the list of all namespaces */
     75        link_t namespaces;
     76        /** Unique namespace identifier */
     77        dev_handle_t handle;
     78        /** Namespace name */
     79        char *name;
     80        /** Reference count */
     81        size_t refcnt;
     82} devmap_namespace_t;
     83
    7084/** Info about registered device
    7185 *
     
    7791            owned by one driver */
    7892        link_t driver_devices;
    79         /** Unique device identifier  */
     93        /** Unique device identifier */
    8094        dev_handle_t handle;
     95        /** Device namespace */
     96        devmap_namespace_t *namespace;
    8197        /** Device name */
    8298        char *name;
     
    86102
    87103LIST_INITIALIZE(devices_list);
     104LIST_INITIALIZE(namespaces_list);
    88105LIST_INITIALIZE(drivers_list);
    89106
     
    117134}
    118135
     136/** Convert fully qualified device name to namespace and device name.
     137 *
     138 * A fully qualified device name can be either a plain device name
     139 * (then the namespace is considered to be an empty string) or consist
     140 * of two components separated by a slash. No more than one slash
     141 * is allowed.
     142 *
     143 */
     144static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
     145{
     146        size_t cnt = 0;
     147        size_t slash_offset = 0;
     148        size_t slash_after = 0;
     149       
     150        size_t offset = 0;
     151        size_t offset_prev = 0;
     152        wchar_t c;
     153       
     154        while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
     155                if (c == '/') {
     156                        cnt++;
     157                        slash_offset = offset_prev;
     158                        slash_after = offset;
     159                }
     160                offset_prev = offset;
     161        }
     162       
     163        /* More than one slash */
     164        if (cnt > 1)
     165                return false;
     166       
     167        /* No slash -> namespace is empty */
     168        if (cnt == 0) {
     169                *ns_name = str_dup("");
     170                if (*ns_name == NULL)
     171                        return false;
     172               
     173                *name = str_dup(fqdn);
     174                if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
     175                        free(*ns_name);
     176                        return false;
     177                }
     178               
     179                return true;
     180        }
     181       
     182        /* Exactly one slash */
     183        *ns_name = str_ndup(fqdn, slash_offset);
     184        if (*ns_name == NULL)
     185                return false;
     186       
     187        *name = str_dup(fqdn + slash_after);
     188        if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
     189                free(*ns_name);
     190                return false;
     191        }
     192       
     193        return true;
     194}
     195
     196/** Find namespace with given name.
     197 *
     198 * The devices_list_mutex should be already held when
     199 * calling this function.
     200 *
     201 */
     202static devmap_namespace_t *devmap_namespace_find_name(const char *name)
     203{
     204        link_t *item = namespaces_list.next;
     205       
     206        while (item != &namespaces_list) {
     207                devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
     208                if (str_cmp(namespace->name, name) == 0)
     209                        return namespace;
     210                item = item->next;
     211        }
     212       
     213        return NULL;
     214}
     215
     216/** Find namespace with given handle.
     217 *
     218 * The devices_list_mutex should be already held when
     219 * calling this function.
     220 *
     221 * @todo: use hash table
     222 *
     223 */
     224static devmap_namespace_t *devmap_namespace_find_handle(dev_handle_t handle)
     225{
     226        link_t *item = namespaces_list.next;
     227       
     228        while (item != &namespaces_list) {
     229                devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
     230                if (namespace->handle == handle)
     231                        return namespace;
     232               
     233                item = item->next;
     234        }
     235       
     236        return NULL;
     237}
     238
    119239/** Find device with given name.
    120240 *
    121  */
    122 static devmap_device_t *devmap_device_find_name(const char *name)
     241 * The devices_list_mutex should be already held when
     242 * calling this function.
     243 *
     244 */
     245static devmap_device_t *devmap_device_find_name(const char *ns_name,
     246    const char *name)
    123247{
    124248        link_t *item = devices_list.next;
    125         devmap_device_t *device = NULL;
    126249       
    127250        while (item != &devices_list) {
    128                 device = list_get_instance(item, devmap_device_t, devices);
    129                 if (str_cmp(device->name, name) == 0)
    130                         break;
     251                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
     252                if ((str_cmp(device->namespace->name, ns_name) == 0) && (str_cmp(device->name, name) == 0))
     253                        return device;
    131254                item = item->next;
    132255        }
    133256       
    134         if (item == &devices_list)
     257        return NULL;
     258}
     259
     260/** Find device with given handle.
     261 *
     262 * The devices_list_mutex should be already held when
     263 * calling this function.
     264 *
     265 * @todo: use hash table
     266 *
     267 */
     268static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
     269{
     270        link_t *item = devices_list.next;
     271       
     272        while (item != &devices_list) {
     273                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
     274                if (device->handle == handle)
     275                        return device;
     276               
     277                item = item->next;
     278        }
     279       
     280        return NULL;
     281}
     282
     283/** Create a namespace (if not already present)
     284 *
     285 * The devices_list_mutex should be already held when
     286 * calling this function.
     287 *
     288 */
     289static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
     290{
     291        devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
     292        if (namespace != NULL)
     293                return namespace;
     294       
     295        namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
     296        if (namespace == NULL)
    135297                return NULL;
    136298       
    137         device = list_get_instance(item, devmap_device_t, devices);
    138         return device;
    139 }
    140 
    141 /** Find device with given handle.
    142  *
    143  * @todo: use hash table
    144  *
    145  */
    146 static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
    147 {
    148         fibril_mutex_lock(&devices_list_mutex);
    149        
    150         link_t *item = (&devices_list)->next;
    151         devmap_device_t *device = NULL;
    152        
    153         while (item != &devices_list) {
    154                 device = list_get_instance(item, devmap_device_t, devices);
    155                 if (device->handle == handle)
    156                         break;
    157                 item = item->next;
    158         }
    159        
    160         if (item == &devices_list) {
    161                 fibril_mutex_unlock(&devices_list_mutex);
     299        namespace->name = str_dup(ns_name);
     300        if (namespace->name == NULL) {
     301                free(namespace);
    162302                return NULL;
    163303        }
    164304       
    165         device = list_get_instance(item, devmap_device_t, devices);
    166        
    167         fibril_mutex_unlock(&devices_list_mutex);
    168        
    169         return device;
    170 }
    171 
    172 /**
    173  * Unregister device and free it. It's assumed that driver's device list is
    174  * already locked.
    175  */
    176 static int devmap_device_unregister_core(devmap_device_t *device)
    177 {
     305        namespace->handle = devmap_create_handle();
     306        namespace->refcnt = 0;
     307       
     308        /*
     309         * Insert new namespace into list of registered namespaces
     310         */
     311        list_append(&(namespace->namespaces), &namespaces_list);
     312       
     313        return namespace;
     314}
     315
     316/** Destroy a namespace (if it is no longer needed)
     317 *
     318 * The devices_list_mutex should be already held when
     319 * calling this function.
     320 *
     321 */
     322static void devmap_namespace_destroy(devmap_namespace_t *namespace)
     323{
     324        if (namespace->refcnt == 0) {
     325                list_remove(&(namespace->namespaces));
     326               
     327                free(namespace->name);
     328                free(namespace);
     329        }
     330}
     331
     332/** Increase namespace reference count by including device
     333 *
     334 * The devices_list_mutex should be already held when
     335 * calling this function.
     336 *
     337 */
     338static void devmap_namespace_addref(devmap_namespace_t *namespace,
     339    devmap_device_t *device)
     340{
     341        device->namespace = namespace;
     342        namespace->refcnt++;
     343}
     344
     345/** Decrease namespace reference count
     346 *
     347 * The devices_list_mutex should be already held when
     348 * calling this function.
     349 *
     350 */
     351static void devmap_namespace_delref(devmap_namespace_t *namespace)
     352{
     353        namespace->refcnt--;
     354        devmap_namespace_destroy(namespace);
     355}
     356
     357/** Unregister device and free it
     358 *
     359 * The devices_list_mutex should be already held when
     360 * calling this function.
     361 *
     362 */
     363static void devmap_device_unregister_core(devmap_device_t *device)
     364{
     365        devmap_namespace_delref(device->namespace);
    178366        list_remove(&(device->devices));
    179367        list_remove(&(device->driver_devices));
    180368       
     369        free(device->namespace);
    181370        free(device->name);
    182371        free(device);
    183        
    184         return EOK;
    185372}
    186373
     
    189376 * drivers.
    190377 */
    191 static void devmap_driver_register(devmap_driver_t **odriver)
    192 {
    193         *odriver = NULL;
    194        
     378static devmap_driver_t *devmap_driver_register(void)
     379{
    195380        ipc_call_t icall;
    196381        ipc_callid_t iid = async_get_call(&icall);
     
    198383        if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
    199384                ipc_answer_0(iid, EREFUSED);
    200                 return;
     385                return NULL;
    201386        }
    202387       
     
    205390        if (driver == NULL) {
    206391                ipc_answer_0(iid, ENOMEM);
    207                 return;
     392                return NULL;
    208393        }
    209394       
     
    211396         * Get driver name
    212397         */
    213         ipc_callid_t callid;
    214         size_t name_size;
    215         if (!async_data_write_receive(&callid, &name_size)) {
     398        int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
     399        if (rc != EOK) {
    216400                free(driver);
    217                 ipc_answer_0(callid, EREFUSED);
    218                 ipc_answer_0(iid, EREFUSED);
    219                 return;
    220         }
    221        
    222         if (name_size > DEVMAP_NAME_MAXLEN) {
    223                 free(driver);
    224                 ipc_answer_0(callid, EINVAL);
    225                 ipc_answer_0(iid, EREFUSED);
    226                 return;
    227         }
    228        
    229         /*
    230          * Allocate buffer for device name.
    231          */
    232         driver->name = (char *) malloc(name_size + 1);
    233         if (driver->name == NULL) {
    234                 free(driver);
    235                 ipc_answer_0(callid, ENOMEM);
    236                 ipc_answer_0(iid, EREFUSED);
    237                 return;
    238         }
    239        
    240         /*
    241          * Send confirmation to sender and get data into buffer.
    242          */
    243         if (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
    244                 free(driver->name);
    245                 free(driver);
    246                 ipc_answer_0(iid, EREFUSED);
    247                 return;
    248         }
    249        
    250         driver->name[name_size] = 0;
     401                ipc_answer_0(iid, rc);
     402                return NULL;
     403        }
    251404       
    252405        /* Initialize mutex for list of devices owned by this driver */
     
    262415         */
    263416        ipc_call_t call;
    264         callid = async_get_call(&call);
     417        ipc_callid_t callid = async_get_call(&call);
    265418       
    266419        if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
     
    270423                free(driver);
    271424                ipc_answer_0(iid, ENOTSUP);
    272                 return;
     425                return NULL;
    273426        }
    274427       
     
    293446        ipc_answer_0(iid, EOK);
    294447       
    295         *odriver = driver;
     448        return driver;
    296449}
    297450
     
    355508        }
    356509       
    357         /* Get device name */
    358         ipc_callid_t callid;
    359         size_t size;
    360         if (!async_data_write_receive(&callid, &size)) {
     510        /* Get fqdn */
     511        char *fqdn;
     512        int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
     513        if (rc != EOK) {
    361514                free(device);
    362                 ipc_answer_0(iid, EREFUSED);
    363                 return;
    364         }
    365        
    366         if (size > DEVMAP_NAME_MAXLEN) {
     515                ipc_answer_0(iid, rc);
     516                return;
     517        }
     518       
     519        char *ns_name;
     520        if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
     521                free(fqdn);
    367522                free(device);
    368                 ipc_answer_0(callid, EINVAL);
    369                 ipc_answer_0(iid, EREFUSED);
    370                 return;
    371         }
    372        
    373         /* +1 for terminating \0 */
    374         device->name = (char *) malloc(size + 1);
    375        
    376         if (device->name == NULL) {
     523                ipc_answer_0(iid, EINVAL);
     524                return;
     525        }
     526       
     527        free(fqdn);
     528       
     529        fibril_mutex_lock(&devices_list_mutex);
     530       
     531        devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
     532        free(ns_name);
     533        if (!namespace) {
     534                fibril_mutex_unlock(&devices_list_mutex);
    377535                free(device);
    378                 ipc_answer_0(callid, ENOMEM);
    379                 ipc_answer_0(iid, EREFUSED);
    380                 return;
    381         }
    382        
    383         async_data_write_finalize(callid, device->name, size);
    384         device->name[size] = 0;
     536                ipc_answer_0(iid, ENOMEM);
     537                return;
     538        }
    385539       
    386540        list_initialize(&(device->devices));
    387541        list_initialize(&(device->driver_devices));
    388542       
    389         fibril_mutex_lock(&devices_list_mutex);
    390        
    391         /* Check that device with such name is not already registered */
    392         if (NULL != devmap_device_find_name(device->name)) {
    393                 printf(NAME ": Device '%s' already registered\n", device->name);
     543        /* Check that device is not already registered */
     544        if (devmap_device_find_name(namespace->name, device->name) != NULL) {
     545                printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
     546                devmap_namespace_destroy(namespace);
    394547                fibril_mutex_unlock(&devices_list_mutex);
     548                free(device->namespace);
    395549                free(device->name);
    396550                free(device);
     
    402556        device->handle = devmap_create_handle();
    403557       
     558        devmap_namespace_addref(namespace, device);
    404559        device->driver = driver;
    405560       
     
    437592static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
    438593{
     594        fibril_mutex_lock(&devices_list_mutex);
     595       
    439596        /*
    440597         * Get handle from request
     
    450607        ipc_forward_fast(callid, dev->driver->phone, dev->handle,
    451608            IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
     609       
     610        fibril_mutex_unlock(&devices_list_mutex);
    452611}
    453612
     
    458617 *
    459618 */
    460 static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    461 {
    462         /*
    463          * Wait for incoming message with device name (but do not
    464          * read the name itself until the buffer is allocated).
    465          */
    466         ipc_callid_t callid;
    467         size_t size;
    468         if (!async_data_write_receive(&callid, &size)) {
    469                 ipc_answer_0(callid, EREFUSED);
    470                 ipc_answer_0(iid, EREFUSED);
    471                 return;
    472         }
    473        
    474         if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
    475                 ipc_answer_0(callid, EINVAL);
    476                 ipc_answer_0(iid, EREFUSED);
    477                 return;
    478         }
    479        
    480         /*
    481          * Allocate buffer for device name.
    482          */
    483         char *name = (char *) malloc(size + 1);
    484         if (name == NULL) {
    485                 ipc_answer_0(callid, ENOMEM);
    486                 ipc_answer_0(iid, EREFUSED);
    487                 return;
    488         }
    489        
    490         /*
    491          * Send confirmation to sender and get data into buffer.
    492          */
    493         ipcarg_t retval = async_data_write_finalize(callid, name, size);
    494         if (retval != EOK) {
    495                 ipc_answer_0(iid, EREFUSED);
    496                 free(name);
    497                 return;
    498         }
    499         name[size] = '\0';
     619static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     620{
     621        char *fqdn;
     622       
     623        /* Get fqdn */
     624        int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
     625        if (rc != EOK) {
     626                ipc_answer_0(iid, rc);
     627                return;
     628        }
     629       
     630        char *ns_name;
     631        char *name;
     632        if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
     633                free(fqdn);
     634                ipc_answer_0(iid, EINVAL);
     635                return;
     636        }
     637       
     638        free(fqdn);
    500639       
    501640        fibril_mutex_lock(&devices_list_mutex);
    502641        const devmap_device_t *dev;
     642       
    503643recheck:
    504 
     644       
    505645        /*
    506646         * Find device name in the list of known devices.
    507647         */
    508         dev = devmap_device_find_name(name);
     648        dev = devmap_device_find_name(ns_name, name);
    509649       
    510650        /*
     
    520660               
    521661                ipc_answer_0(iid, ENOENT);
     662                free(ns_name);
    522663                free(name);
    523664                fibril_mutex_unlock(&devices_list_mutex);
     
    527668       
    528669        ipc_answer_1(iid, EOK, dev->handle);
     670        free(ns_name);
    529671        free(name);
    530672}
    531673
    532 /** Find name of device identified by id and send it to caller.
    533  *
    534  */
    535 static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
    536 {
    537         const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
     674/** Find handle for namespace identified by name.
     675 *
     676 * In answer will be send EOK and device handle in arg1 or a error
     677 * code from errno.h.
     678 *
     679 */
     680static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     681{
     682        char *name;
     683       
     684        /* Get device name */
     685        int rc = async_data_string_receive(&name, DEVMAP_NAME_MAXLEN);
     686        if (rc != EOK) {
     687                ipc_answer_0(iid, rc);
     688                return;
     689        }
     690       
     691        fibril_mutex_lock(&devices_list_mutex);
     692        const devmap_namespace_t *namespace;
     693       
     694recheck:
    538695       
    539696        /*
    540          * Device not found.
     697         * Find namespace name in the list of known namespaces.
    541698         */
    542         if (device == NULL) {
     699        namespace = devmap_namespace_find_name(name);
     700       
     701        /*
     702         * Namespace was not found.
     703         */
     704        if (namespace == NULL) {
     705                if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
     706                        /* Blocking lookup */
     707                        fibril_condvar_wait(&devices_list_cv,
     708                            &devices_list_mutex);
     709                        goto recheck;
     710                }
     711               
    543712                ipc_answer_0(iid, ENOENT);
    544                 return;
    545         }
    546        
    547         ipc_answer_0(iid, EOK);
    548        
    549         /* FIXME:
    550          * We have no channel from DEVMAP to client, therefore
    551          * sending must be initiated by client.
    552          *
    553          * size_t name_size = str_size(device->name);
    554          *
    555          * int rc = async_data_write_send(phone, device->name, name_size);
    556          * if (rc != EOK) {
    557          *     async_wait_for(req, NULL);
    558          *     return rc;
    559          * }
    560          */
    561        
    562         /* TODO: send name in response */
    563 }
    564 
    565 static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
     713                free(name);
     714                fibril_mutex_unlock(&devices_list_mutex);
     715                return;
     716        }
     717        fibril_mutex_unlock(&devices_list_mutex);
     718       
     719        ipc_answer_1(iid, EOK, namespace->handle);
     720        free(name);
     721}
     722
     723static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
    566724{
    567725        fibril_mutex_lock(&devices_list_mutex);
    568         ipc_answer_1(iid, EOK, list_count(&devices_list));
     726       
     727        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     728        if (namespace == NULL) {
     729                devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
     730                if (dev == NULL)
     731                        ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
     732                else
     733                        ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
     734        } else
     735                ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
     736       
    569737        fibril_mutex_unlock(&devices_list_mutex);
    570738}
    571739
    572 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     740static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
    573741{
    574742        fibril_mutex_lock(&devices_list_mutex);
    575        
     743        ipc_answer_1(iid, EOK, list_count(&namespaces_list));
     744        fibril_mutex_unlock(&devices_list_mutex);
     745}
     746
     747static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
     748{
     749        fibril_mutex_lock(&devices_list_mutex);
     750       
     751        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     752        if (namespace == NULL)
     753                ipc_answer_0(iid, EEXISTS);
     754        else
     755                ipc_answer_1(iid, EOK, namespace->refcnt);
     756       
     757        fibril_mutex_unlock(&devices_list_mutex);
     758}
     759
     760static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
     761{
    576762        ipc_callid_t callid;
    577763        size_t size;
     
    584770        if ((size % sizeof(dev_desc_t)) != 0) {
    585771                ipc_answer_0(callid, EINVAL);
     772                ipc_answer_0(iid, EINVAL);
     773                return;
     774        }
     775       
     776        fibril_mutex_lock(&devices_list_mutex);
     777       
     778        size_t count = size / sizeof(dev_desc_t);
     779        if (count != list_count(&namespaces_list)) {
     780                ipc_answer_0(callid, EOVERFLOW);
     781                ipc_answer_0(iid, EOVERFLOW);
     782                return;
     783        }
     784       
     785        dev_desc_t *desc = (dev_desc_t *) malloc(size);
     786        if (desc == NULL) {
     787                ipc_answer_0(callid, ENOMEM);
     788                ipc_answer_0(iid, ENOMEM);
     789                return;
     790        }
     791       
     792        link_t *item = namespaces_list.next;
     793        size_t pos = 0;
     794        while (item != &namespaces_list) {
     795                devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
     796               
     797                desc[pos].handle = namespace->handle;
     798                str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
     799                pos++;
     800               
     801                item = item->next;
     802        }
     803       
     804        ipcarg_t retval = async_data_read_finalize(callid, desc, size);
     805       
     806        free(desc);
     807        fibril_mutex_unlock(&devices_list_mutex);
     808       
     809        ipc_answer_0(iid, retval);
     810}
     811
     812static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
     813{
     814        /* FIXME: Use faster algorithm which can make better use
     815           of namespaces */
     816       
     817        ipc_callid_t callid;
     818        size_t size;
     819        if (!async_data_read_receive(&callid, &size)) {
     820                ipc_answer_0(callid, EREFUSED);
    586821                ipc_answer_0(iid, EREFUSED);
    587822                return;
    588823        }
    589824       
     825        if ((size % sizeof(dev_desc_t)) != 0) {
     826                ipc_answer_0(callid, EINVAL);
     827                ipc_answer_0(iid, EINVAL);
     828                return;
     829        }
     830       
     831        fibril_mutex_lock(&devices_list_mutex);
     832       
     833        devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
     834        if (namespace == NULL) {
     835                fibril_mutex_unlock(&devices_list_mutex);
     836                ipc_answer_0(callid, ENOENT);
     837                ipc_answer_0(iid, ENOENT);
     838                return;
     839        }
     840       
    590841        size_t count = size / sizeof(dev_desc_t);
     842        if (count != namespace->refcnt) {
     843                ipc_answer_0(callid, EOVERFLOW);
     844                ipc_answer_0(iid, EOVERFLOW);
     845                return;
     846        }
     847       
    591848        dev_desc_t *desc = (dev_desc_t *) malloc(size);
    592849        if (desc == NULL) {
     
    596853        }
    597854       
     855        link_t *item = devices_list.next;
    598856        size_t pos = 0;
    599         link_t *item = devices_list.next;
    600        
    601         while ((item != &devices_list) && (pos < count)) {
     857        while (item != &devices_list) {
    602858                devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
    603859               
    604                 desc[pos].handle = device->handle;
    605                 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
    606                 pos++;
     860                if (device->namespace == namespace) {
     861                        desc[pos].handle = device->handle;
     862                        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
     863                        pos++;
     864                }
     865               
    607866                item = item->next;
    608867        }
    609868       
    610         ipcarg_t retval = async_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
    611         if (retval != EOK) {
    612                 ipc_answer_0(iid, EREFUSED);
    613                 free(desc);
    614                 return;
    615         }
     869        ipcarg_t retval = async_data_read_finalize(callid, desc, size);
    616870       
    617871        free(desc);
    618        
    619872        fibril_mutex_unlock(&devices_list_mutex);
    620873       
    621         ipc_answer_1(iid, EOK, pos);
     874        ipc_answer_0(iid, retval);
    622875}
    623876
     
    642895        }
    643896       
    644         /* Create NULL device entry */
     897        char null[DEVMAP_NAME_MAXLEN];
     898        snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
     899       
     900        char *dev_name = str_dup(null);
     901        if (dev_name == NULL) {
     902                fibril_mutex_unlock(&null_devices_mutex);
     903                ipc_answer_0(iid, ENOMEM);
     904                return;
     905        }
     906       
    645907        devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
    646908        if (device == NULL) {
     
    650912        }
    651913       
    652         char null[DEVMAP_NAME_MAXLEN];
    653         snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
    654        
    655         device->name = str_dup(null);
    656         if (device->name == NULL) {
     914        fibril_mutex_lock(&devices_list_mutex);
     915       
     916        devmap_namespace_t *namespace = devmap_namespace_create("null");
     917        if (!namespace) {
     918                fibril_mutex_lock(&devices_list_mutex);
    657919                fibril_mutex_unlock(&null_devices_mutex);
    658                 free(device);
    659920                ipc_answer_0(iid, ENOMEM);
    660921                return;
     
    663924        list_initialize(&(device->devices));
    664925        list_initialize(&(device->driver_devices));
    665        
    666         fibril_mutex_lock(&devices_list_mutex);
    667926       
    668927        /* Get unique device handle */
    669928        device->handle = devmap_create_handle();
    670929        device->driver = NULL;
     930       
     931        devmap_namespace_addref(namespace, device);
     932        device->name = dev_name;
    671933       
    672934        /* Insert device into list of all devices
     
    692954        }
    693955       
     956        fibril_mutex_lock(&devices_list_mutex);
    694957        devmap_device_unregister_core(null_devices[i]);
     958        fibril_mutex_unlock(&devices_list_mutex);
     959       
    695960        null_devices[i] = NULL;
    696961       
     
    725990        ipc_answer_0(iid, EOK);
    726991       
    727         devmap_driver_t *driver = NULL;
    728         devmap_driver_register(&driver);
    729        
    730         if (NULL == driver)
     992        devmap_driver_t *driver = devmap_driver_register();
     993        if (driver == NULL)
    731994                return;
    732995       
     
    7551018                        break;
    7561019                case DEVMAP_DEVICE_GET_HANDLE:
    757                         devmap_get_handle(callid, &call);
    758                         break;
    759                 case DEVMAP_DEVICE_GET_NAME:
    760                         devmap_get_name(callid, &call);
     1020                        devmap_device_get_handle(callid, &call);
     1021                        break;
     1022                case DEVMAP_NAMESPACE_GET_HANDLE:
     1023                        devmap_namespace_get_handle(callid, &call);
    7611024                        break;
    7621025                default:
     
    7931056                        continue;
    7941057                case DEVMAP_DEVICE_GET_HANDLE:
    795                         devmap_get_handle(callid, &call);
    796                         break;
    797                 case DEVMAP_DEVICE_GET_NAME:
    798                         devmap_get_name(callid, &call);
    799                         break;
    800                 case DEVMAP_DEVICE_NULL_CREATE:
     1058                        devmap_device_get_handle(callid, &call);
     1059                        break;
     1060                case DEVMAP_NAMESPACE_GET_HANDLE:
     1061                        devmap_namespace_get_handle(callid, &call);
     1062                        break;
     1063                case DEVMAP_HANDLE_PROBE:
     1064                        devmap_handle_probe(callid, &call);
     1065                        break;
     1066                case DEVMAP_NULL_CREATE:
    8011067                        devmap_null_create(callid, &call);
    8021068                        break;
    803                 case DEVMAP_DEVICE_NULL_DESTROY:
     1069                case DEVMAP_NULL_DESTROY:
    8041070                        devmap_null_destroy(callid, &call);
    8051071                        break;
    806                 case DEVMAP_DEVICE_GET_COUNT:
    807                         devmap_get_count(callid, &call);
    808                         break;
    809                 case DEVMAP_DEVICE_GET_DEVICES:
     1072                case DEVMAP_GET_NAMESPACE_COUNT:
     1073                        devmap_get_namespace_count(callid, &call);
     1074                        break;
     1075                case DEVMAP_GET_DEVICE_COUNT:
     1076                        devmap_get_device_count(callid, &call);
     1077                        break;
     1078                case DEVMAP_GET_NAMESPACES:
     1079                        devmap_get_namespaces(callid, &call);
     1080                        break;
     1081                case DEVMAP_GET_DEVICES:
    8101082                        devmap_get_devices(callid, &call);
    8111083                        break;
  • uspace/srv/fs/devfs/devfs_ops.c

    rfc6dd18 r1313ee9  
    4444#include <fibril_synch.h>
    4545#include <adt/hash_table.h>
     46#include <ipc/devmap.h>
    4647#include <sys/stat.h>
     48#include <libfs.h>
     49#include <assert.h>
    4750#include "devfs.h"
    4851#include "devfs_ops.h"
    4952
    50 #define PLB_GET_CHAR(pos)  (devfs_reg.plb_ro[pos % PLB_SIZE])
     53typedef struct {
     54        devmap_handle_type_t type;
     55        dev_handle_t handle;
     56} devfs_node_t;
    5157
    5258/** Opened devices structure */
     
    9197};
    9298
     99static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
     100    dev_handle_t handle)
     101{
     102        devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
     103        if (node == NULL) {
     104                *rfn = NULL;
     105                return ENOMEM;
     106        }
     107       
     108        *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
     109        if (*rfn == NULL) {
     110                free(node);
     111                *rfn = NULL;
     112                return ENOMEM;
     113        }
     114       
     115        fs_node_initialize(*rfn);
     116        node->type = type;
     117        node->handle = handle;
     118       
     119        (*rfn)->data = node;
     120        return EOK;
     121}
     122
     123static int devfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
     124{
     125        return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
     126}
     127
     128static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
     129{
     130        devfs_node_t *node = (devfs_node_t *) pfn->data;
     131       
     132        if (node->handle == 0) {
     133                /* Root directory */
     134               
     135                dev_desc_t *devs;
     136                size_t count = devmap_get_namespaces(&devs);
     137               
     138                if (count > 0) {
     139                        size_t pos;
     140                        for (pos = 0; pos < count; pos++) {
     141                                /* Ignore root namespace */
     142                                if (str_cmp(devs[pos].name, "") == 0)
     143                                        continue;
     144                               
     145                                if (str_cmp(devs[pos].name, component) == 0) {
     146                                        free(devs);
     147                                        return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
     148                                }
     149                        }
     150                       
     151                        free(devs);
     152                }
     153               
     154                /* Search root namespace */
     155                dev_handle_t namespace;
     156                if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
     157                        count = devmap_get_devices(namespace, &devs);
     158                       
     159                        if (count > 0) {
     160                                size_t pos;
     161                                for (pos = 0; pos < count; pos++) {
     162                                        if (str_cmp(devs[pos].name, component) == 0) {
     163                                                free(devs);
     164                                                return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
     165                                        }
     166                                }
     167                               
     168                                free(devs);
     169                        }
     170                }
     171               
     172                *rfn = NULL;
     173                return EOK;
     174        }
     175       
     176        if (node->type == DEV_HANDLE_NAMESPACE) {
     177                /* Namespace directory */
     178               
     179                dev_desc_t *devs;
     180                size_t count = devmap_get_devices(node->handle, &devs);
     181                if (count > 0) {
     182                        size_t pos;
     183                        for (pos = 0; pos < count; pos++) {
     184                                if (str_cmp(devs[pos].name, component) == 0) {
     185                                        free(devs);
     186                                        return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
     187                                }
     188                        }
     189                       
     190                        free(devs);
     191                }
     192               
     193                *rfn = NULL;
     194                return EOK;
     195        }
     196       
     197        *rfn = NULL;
     198        return EOK;
     199}
     200
     201static int devfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
     202{
     203        return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
     204}
     205
     206static int devfs_node_open(fs_node_t *fn)
     207{
     208        devfs_node_t *node = (devfs_node_t *) fn->data;
     209       
     210        if (node->handle == 0) {
     211                /* Root directory */
     212                return EOK;
     213        }
     214       
     215        devmap_handle_type_t type = devmap_handle_probe(node->handle);
     216       
     217        if (type == DEV_HANDLE_NAMESPACE) {
     218                /* Namespace directory */
     219                return EOK;
     220        }
     221       
     222        if (type == DEV_HANDLE_DEVICE) {
     223                /* Device node */
     224               
     225                unsigned long key[] = {
     226                        [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
     227                };
     228               
     229                fibril_mutex_lock(&devices_mutex);
     230                link_t *lnk = hash_table_find(&devices, key);
     231                if (lnk == NULL) {
     232                        device_t *dev = (device_t *) malloc(sizeof(device_t));
     233                        if (dev == NULL) {
     234                                fibril_mutex_unlock(&devices_mutex);
     235                                return ENOMEM;
     236                        }
     237                       
     238                        int phone = devmap_device_connect(node->handle, 0);
     239                        if (phone < 0) {
     240                                fibril_mutex_unlock(&devices_mutex);
     241                                free(dev);
     242                                return ENOENT;
     243                        }
     244                       
     245                        dev->handle = node->handle;
     246                        dev->phone = phone;
     247                        dev->refcount = 1;
     248                       
     249                        hash_table_insert(&devices, key, &dev->link);
     250                } else {
     251                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
     252                        dev->refcount++;
     253                }
     254               
     255                fibril_mutex_unlock(&devices_mutex);
     256               
     257                return EOK;
     258        }
     259       
     260        return ENOENT;
     261}
     262
     263static int devfs_node_put(fs_node_t *fn)
     264{
     265        free(fn->data);
     266        free(fn);
     267        return EOK;
     268}
     269
     270static int devfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag)
     271{
     272        assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
     273       
     274        *rfn = NULL;
     275        return ENOTSUP;
     276}
     277
     278static int devfs_destroy_node(fs_node_t *fn)
     279{
     280        return ENOTSUP;
     281}
     282
     283static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     284{
     285        return ENOTSUP;
     286}
     287
     288static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
     289{
     290        return ENOTSUP;
     291}
     292
     293static int devfs_has_children(bool *has_children, fs_node_t *fn)
     294{
     295        devfs_node_t *node = (devfs_node_t *) fn->data;
     296       
     297        if (node->handle == 0) {
     298                size_t count = devmap_count_namespaces();
     299                if (count > 0) {
     300                        *has_children = true;
     301                        return EOK;
     302                }
     303               
     304                /* Root namespace */
     305                dev_handle_t namespace;
     306                if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
     307                        count = devmap_count_devices(namespace);
     308                        if (count > 0) {
     309                                *has_children = true;
     310                                return EOK;
     311                        }
     312                }
     313               
     314                *has_children = false;
     315                return EOK;
     316        }
     317       
     318        if (node->type == DEV_HANDLE_NAMESPACE) {
     319                size_t count = devmap_count_devices(node->handle);
     320                if (count > 0) {
     321                        *has_children = true;
     322                        return EOK;
     323                }
     324               
     325                *has_children = false;
     326                return EOK;
     327        }
     328       
     329        *has_children = false;
     330        return EOK;
     331}
     332
     333static fs_index_t devfs_index_get(fs_node_t *fn)
     334{
     335        devfs_node_t *node = (devfs_node_t *) fn->data;
     336        return node->handle;
     337}
     338
     339static size_t devfs_size_get(fs_node_t *fn)
     340{
     341        return 0;
     342}
     343
     344static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
     345{
     346        devfs_node_t *node = (devfs_node_t *) fn->data;
     347       
     348        if (node->handle == 0)
     349                return 0;
     350       
     351        return 1;
     352}
     353
     354static char devfs_plb_get_char(unsigned pos)
     355{
     356        return devfs_reg.plb_ro[pos % PLB_SIZE];
     357}
     358
     359static bool devfs_is_directory(fs_node_t *fn)
     360{
     361        devfs_node_t *node = (devfs_node_t *) fn->data;
     362       
     363        return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
     364}
     365
     366static bool devfs_is_file(fs_node_t *fn)
     367{
     368        devfs_node_t *node = (devfs_node_t *) fn->data;
     369       
     370        return (node->type == DEV_HANDLE_DEVICE);
     371}
     372
     373static dev_handle_t devfs_device_get(fs_node_t *fn)
     374{
     375        devfs_node_t *node = (devfs_node_t *) fn->data;
     376       
     377        if (node->type == DEV_HANDLE_DEVICE)
     378                return node->handle;
     379       
     380        return 0;
     381}
     382
     383/** libfs operations */
     384libfs_ops_t devfs_libfs_ops = {
     385        .root_get = devfs_root_get,
     386        .match = devfs_match,
     387        .node_get = devfs_node_get,
     388        .node_open = devfs_node_open,
     389        .node_put = devfs_node_put,
     390        .create = devfs_create_node,
     391        .destroy = devfs_destroy_node,
     392        .link = devfs_link_node,
     393        .unlink = devfs_unlink_node,
     394        .has_children = devfs_has_children,
     395        .index_get = devfs_index_get,
     396        .size_get = devfs_size_get,
     397        .lnkcnt_get = devfs_lnkcnt_get,
     398        .plb_get_char = devfs_plb_get_char,
     399        .is_directory = devfs_is_directory,
     400        .is_file = devfs_is_file,
     401        .device_get = devfs_device_get
     402};
     403
    93404bool devfs_init(void)
    94405{
     
    105416void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    106417{
     418        char *opts;
     419       
    107420        /* Accept the mount options */
    108         ipc_callid_t callid;
    109         size_t size;
    110         if (!async_data_write_receive(&callid, &size)) {
    111                 ipc_answer_0(callid, EINVAL);
    112                 ipc_answer_0(rid, EINVAL);
    113                 return;
    114         }
    115        
    116         char *opts = malloc(size + 1);
    117         if (!opts) {
    118                 ipc_answer_0(callid, ENOMEM);
    119                 ipc_answer_0(rid, ENOMEM);
    120                 return;
    121         }
    122        
    123         ipcarg_t retval = async_data_write_finalize(callid, opts, size);
     421        ipcarg_t retval = async_data_string_receive(&opts, 0);
    124422        if (retval != EOK) {
    125423                ipc_answer_0(rid, retval);
    126                 free(opts);
    127424                return;
    128425        }
    129426       
    130427        free(opts);
    131        
    132428        ipc_answer_3(rid, EOK, 0, 0, 0);
    133429}
     
    135431void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
    136432{
    137         ipc_answer_0(rid, ENOTSUP);
     433        libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    138434}
    139435
    140436void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    141437{
    142         ipcarg_t first = IPC_GET_ARG1(*request);
    143         ipcarg_t last = IPC_GET_ARG2(*request);
    144         dev_handle_t dev_handle = IPC_GET_ARG3(*request);
    145         ipcarg_t lflag = IPC_GET_ARG4(*request);
    146         fs_index_t index = IPC_GET_ARG5(*request);
    147        
    148         /* Hierarchy is flat, no altroot is supported */
    149         if (index != 0) {
    150                 ipc_answer_0(rid, ENOENT);
    151                 return;
    152         }
    153        
    154         if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
    155                 ipc_answer_0(rid, ENOTSUP);
    156                 return;
    157         }
    158        
    159         /* Eat slash */
    160         if (PLB_GET_CHAR(first) == '/') {
    161                 first++;
    162                 first %= PLB_SIZE;
    163         }
    164        
    165         if (first >= last) {
    166                 /* Root entry */
    167                 if (!(lflag & L_FILE))
    168                         ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
    169                 else
    170                         ipc_answer_0(rid, ENOENT);
    171         } else {
    172                 if (!(lflag & L_DIRECTORY)) {
    173                         size_t len;
    174                         if (last >= first)
    175                                 len = last - first + 1;
    176                         else
    177                                 len = first + PLB_SIZE - last + 1;
     438        libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
     439}
     440
     441void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     442{
     443        libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
     444}
     445
     446void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
     447{
     448        libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
     449}
     450
     451void devfs_read(ipc_callid_t rid, ipc_call_t *request)
     452{
     453        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     454        off_t pos = (off_t) IPC_GET_ARG3(*request);
     455       
     456        if (index == 0) {
     457                ipc_callid_t callid;
     458                size_t size;
     459                if (!async_data_read_receive(&callid, &size)) {
     460                        ipc_answer_0(callid, EINVAL);
     461                        ipc_answer_0(rid, EINVAL);
     462                        return;
     463                }
     464               
     465                dev_desc_t *desc;
     466                size_t count = devmap_get_namespaces(&desc);
     467               
     468                /* Get rid of root namespace */
     469                size_t i;
     470                for (i = 0; i < count; i++) {
     471                        if (str_cmp(desc[i].name, "") == 0) {
     472                                if (pos >= i)
     473                                        pos++;
     474                               
     475                                break;
     476                        }
     477                }
     478               
     479                if (pos < count) {
     480                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
     481                        free(desc);
     482                        ipc_answer_1(rid, EOK, 1);
     483                        return;
     484                }
     485               
     486                free(desc);
     487                pos -= count;
     488               
     489                /* Search root namespace */
     490                dev_handle_t namespace;
     491                if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
     492                        count = devmap_get_devices(namespace, &desc);
    178493                       
    179                         char *name = (char *) malloc(len + 1);
    180                         if (name == NULL) {
    181                                 ipc_answer_0(rid, ENOMEM);
     494                        if (pos < count) {
     495                                async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
     496                                free(desc);
     497                                ipc_answer_1(rid, EOK, 1);
    182498                                return;
    183499                        }
    184500                       
    185                         size_t i;
    186                         for (i = 0; i < len; i++)
    187                                 name[i] = PLB_GET_CHAR(first + i);
    188                        
    189                         name[len] = 0;
    190                        
    191                         dev_handle_t handle;
    192                         if (devmap_device_get_handle(name, &handle, 0) != EOK) {
    193                                 free(name);
    194                                 ipc_answer_0(rid, ENOENT);
    195                                 return;
    196                         }
    197                        
    198                         if (lflag & L_OPEN) {
    199                                 unsigned long key[] = {
    200                                         [DEVICES_KEY_HANDLE] = (unsigned long) handle
    201                                 };
    202                                
    203                                 fibril_mutex_lock(&devices_mutex);
    204                                 link_t *lnk = hash_table_find(&devices, key);
    205                                 if (lnk == NULL) {
    206                                         int phone = devmap_device_connect(handle, 0);
    207                                         if (phone < 0) {
    208                                                 fibril_mutex_unlock(&devices_mutex);
    209                                                 free(name);
    210                                                 ipc_answer_0(rid, ENOENT);
    211                                                 return;
    212                                         }
    213                                        
    214                                         device_t *dev = (device_t *) malloc(sizeof(device_t));
    215                                         if (dev == NULL) {
    216                                                 fibril_mutex_unlock(&devices_mutex);
    217                                                 free(name);
    218                                                 ipc_answer_0(rid, ENOMEM);
    219                                                 return;
    220                                         }
    221                                        
    222                                         dev->handle = handle;
    223                                         dev->phone = phone;
    224                                         dev->refcount = 1;
    225                                        
    226                                         hash_table_insert(&devices, key, &dev->link);
    227                                 } else {
    228                                         device_t *dev = hash_table_get_instance(lnk, device_t, link);
    229                                         dev->refcount++;
    230                                 }
    231                                 fibril_mutex_unlock(&devices_mutex);
    232                         }
    233                        
    234                         free(name);
    235                        
    236                         ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
    237                 } else
    238                         ipc_answer_0(rid, ENOENT);
    239         }
    240 }
    241 
    242 void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
    243 {
    244         dev_handle_t handle = IPC_GET_ARG2(*request);
    245        
    246         unsigned long key[] = {
    247                 [DEVICES_KEY_HANDLE] = (unsigned long) handle
    248         };
    249        
    250         fibril_mutex_lock(&devices_mutex);
    251         link_t *lnk = hash_table_find(&devices, key);
    252         if (lnk == NULL) {
    253                 int phone = devmap_device_connect(handle, 0);
    254                 if (phone < 0) {
    255                         fibril_mutex_unlock(&devices_mutex);
    256                         ipc_answer_0(rid, ENOENT);
    257                         return;
    258                 }
    259                
    260                 device_t *dev = (device_t *) malloc(sizeof(device_t));
    261                 if (dev == NULL) {
    262                         fibril_mutex_unlock(&devices_mutex);
    263                         ipc_answer_0(rid, ENOMEM);
    264                         return;
    265                 }
    266                
    267                 dev->handle = handle;
    268                 dev->phone = phone;
    269                 dev->refcount = 1;
    270                
    271                 hash_table_insert(&devices, key, &dev->link);
    272         } else {
    273                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
    274                 dev->refcount++;
    275         }
    276         fibril_mutex_unlock(&devices_mutex);
    277        
    278         ipc_answer_3(rid, EOK, 0, 1, L_FILE);
    279 }
    280 
    281 void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
    282 {
    283         dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
    284         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    285        
    286         ipc_callid_t callid;
    287         size_t size;
    288         if (!async_data_read_receive(&callid, &size) ||
    289             size != sizeof(struct stat)) {
    290                 ipc_answer_0(callid, EINVAL);
    291                 ipc_answer_0(rid, EINVAL);
    292                 return;
    293         }
    294 
    295         struct stat stat;
    296         memset(&stat, 0, sizeof(struct stat));
    297 
    298         stat.fs_handle = devfs_reg.fs_handle;
    299         stat.dev_handle = dev_handle;
    300         stat.index = index;
    301         stat.lnkcnt = 1;
    302         stat.is_file = (index != 0);
    303         stat.size = 0;
    304        
    305         if (index != 0) {
    306                 unsigned long key[] = {
    307                         [DEVICES_KEY_HANDLE] = (unsigned long) index
    308                 };
    309                
    310                 fibril_mutex_lock(&devices_mutex);
    311                 link_t *lnk = hash_table_find(&devices, key);
    312                 if (lnk != NULL)
    313                         stat.devfs_stat.device = (dev_handle_t)index;
    314                 fibril_mutex_unlock(&devices_mutex);
    315         }
    316 
    317         async_data_read_finalize(callid, &stat, sizeof(struct stat));
    318         ipc_answer_0(rid, EOK);
    319 }
    320 
    321 void devfs_read(ipc_callid_t rid, ipc_call_t *request)
    322 {
    323         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    324         off_t pos = (off_t) IPC_GET_ARG3(*request);
    325        
    326         if (index != 0) {
     501                        free(desc);
     502                }
     503               
     504                ipc_answer_0(callid, ENOENT);
     505                ipc_answer_1(rid, ENOENT, 0);
     506                return;
     507        }
     508       
     509        devmap_handle_type_t type = devmap_handle_probe(index);
     510       
     511        if (type == DEV_HANDLE_NAMESPACE) {
     512                /* Namespace directory */
     513                ipc_callid_t callid;
     514                size_t size;
     515                if (!async_data_read_receive(&callid, &size)) {
     516                        ipc_answer_0(callid, EINVAL);
     517                        ipc_answer_0(rid, EINVAL);
     518                        return;
     519                }
     520               
     521                dev_desc_t *desc;
     522                size_t count = devmap_get_devices(index, &desc);
     523               
     524                if (pos < count) {
     525                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
     526                        free(desc);
     527                        ipc_answer_1(rid, EOK, 1);
     528                        return;
     529                }
     530               
     531                free(desc);
     532                ipc_answer_0(callid, ENOENT);
     533                ipc_answer_1(rid, ENOENT, 0);
     534                return;
     535        }
     536       
     537        if (type == DEV_HANDLE_DEVICE) {
     538                /* Device node */
     539               
    327540                unsigned long key[] = {
    328541                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    364577                /* Driver reply is the final result of the whole operation */
    365578                ipc_answer_1(rid, rc, bytes);
    366         } else {
    367                 ipc_callid_t callid;
    368                 size_t size;
    369                 if (!async_data_read_receive(&callid, &size)) {
    370                         ipc_answer_0(callid, EINVAL);
    371                         ipc_answer_0(rid, EINVAL);
    372                         return;
    373                 }
    374                
    375                 size_t count = devmap_device_get_count();
    376                 dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
    377                 if (desc == NULL) {
    378                         ipc_answer_0(callid, ENOMEM);
    379                         ipc_answer_1(rid, ENOMEM, 0);
    380                         return;
    381                 }
    382                
    383                 size_t max = devmap_device_get_devices(count, desc);
    384                
    385                 if (pos < max) {
    386                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    387                 } else {
    388                         ipc_answer_0(callid, ENOENT);
    389                         ipc_answer_1(rid, ENOENT, 0);
    390                         return;
    391                 }
    392                
    393                 free(desc);
    394                
    395                 ipc_answer_1(rid, EOK, 1);
    396         }
     579                return;
     580        }
     581       
     582        ipc_answer_0(rid, ENOENT);
    397583}
    398584
     
    402588        off_t pos = (off_t) IPC_GET_ARG3(*request);
    403589       
    404         if (index != 0) {
     590        if (index == 0) {
     591                ipc_answer_0(rid, ENOTSUP);
     592                return;
     593        }
     594       
     595        devmap_handle_type_t type = devmap_handle_probe(index);
     596       
     597        if (type == DEV_HANDLE_NAMESPACE) {
     598                /* Namespace directory */
     599                ipc_answer_0(rid, ENOTSUP);
     600                return;
     601        }
     602       
     603        if (type == DEV_HANDLE_DEVICE) {
     604                /* Device node */
    405605                unsigned long key[] = {
    406606                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    443643                /* Driver reply is the final result of the whole operation */
    444644                ipc_answer_1(rid, rc, bytes);
    445         } else {
    446                 /* Read-only filesystem */
    447                 ipc_answer_0(rid, ENOTSUP);
    448         }
     645                return;
     646        }
     647       
     648        ipc_answer_0(rid, ENOENT);
    449649}
    450650
     
    458658        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    459659       
    460         if (index != 0) {
     660        if (index == 0) {
     661                ipc_answer_0(rid, EOK);
     662                return;
     663        }
     664       
     665        devmap_handle_type_t type = devmap_handle_probe(index);
     666       
     667        if (type == DEV_HANDLE_NAMESPACE) {
     668                /* Namespace directory */
     669                ipc_answer_0(rid, EOK);
     670                return;
     671        }
     672       
     673        if (type == DEV_HANDLE_DEVICE) {
    461674                unsigned long key[] = {
    462675                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    482695               
    483696                ipc_answer_0(rid, EOK);
    484         } else
    485                 ipc_answer_0(rid, ENOTSUP);
     697                return;
     698        }
     699       
     700        ipc_answer_0(rid, ENOENT);
    486701}
    487702
     
    490705        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    491706       
    492         if (index != 0) {
     707        if (index == 0) {
     708                ipc_answer_0(rid, EOK);
     709                return;
     710        }
     711       
     712        devmap_handle_type_t type = devmap_handle_probe(index);
     713       
     714        if (type == DEV_HANDLE_NAMESPACE) {
     715                /* Namespace directory */
     716                ipc_answer_0(rid, EOK);
     717                return;
     718        }
     719       
     720        if (type == DEV_HANDLE_DEVICE) {
    493721                unsigned long key[] = {
    494722                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    518746                /* Driver reply is the final result of the whole operation */
    519747                ipc_answer_0(rid, rc);
    520         } else
    521                 ipc_answer_0(rid, ENOTSUP);
     748                return;
     749        }
     750       
     751        ipc_answer_0(rid, ENOENT);
    522752}
    523753
  • uspace/srv/fs/fat/fat_ops.c

    rfc6dd18 r1313ee9  
    7171static int fat_match(fs_node_t **, fs_node_t *, const char *);
    7272static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);
     73static int fat_node_open(fs_node_t *);
    7374static int fat_node_put(fs_node_t *);
    7475static int fat_create_node(fs_node_t **, dev_handle_t, int);
     
    8384static bool fat_is_directory(fs_node_t *);
    8485static bool fat_is_file(fs_node_t *node);
     86static dev_handle_t fat_device_get(fs_node_t *node);
    8587
    8688/*
     
    407409}
    408410
     411int fat_node_open(fs_node_t *fn)
     412{
     413        /*
     414         * Opening a file is stateless, nothing
     415         * to be done here.
     416         */
     417        return EOK;
     418}
     419
    409420int fat_node_put(fs_node_t *fn)
    410421{
     
    867878}
    868879
     880dev_handle_t fat_device_get(fs_node_t *node)
     881{
     882        return 0;
     883}
     884
    869885/** libfs operations */
    870886libfs_ops_t fat_libfs_ops = {
     
    872888        .match = fat_match,
    873889        .node_get = fat_node_get,
     890        .node_open = fat_node_open,
    874891        .node_put = fat_node_put,
    875892        .create = fat_create_node,
     
    881898        .size_get = fat_size_get,
    882899        .lnkcnt_get = fat_lnkcnt_get,
    883         .plb_get_char = fat_plb_get_char,
     900        .plb_get_char = fat_plb_get_char,
    884901        .is_directory = fat_is_directory,
    885         .is_file = fat_is_file
     902        .is_file = fat_is_file,
     903        .device_get = fat_device_get
    886904};
    887905
  • uspace/srv/fs/tmpfs/tmpfs_ops.c

    rfc6dd18 r1313ee9  
    6969static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
    7070static int tmpfs_node_get(fs_node_t **, dev_handle_t, fs_index_t);
     71static int tmpfs_node_open(fs_node_t *);
    7172static int tmpfs_node_put(fs_node_t *);
    7273static int tmpfs_create_node(fs_node_t **, dev_handle_t, int);
     
    117118}
    118119
     120static dev_handle_t tmpfs_device_get(fs_node_t *fn)
     121{
     122        return 0;
     123}
     124
    119125/** libfs operations */
    120126libfs_ops_t tmpfs_libfs_ops = {
     
    122128        .match = tmpfs_match,
    123129        .node_get = tmpfs_node_get,
     130        .node_open = tmpfs_node_open,
    124131        .node_put = tmpfs_node_put,
    125132        .create = tmpfs_create_node,
     
    133140        .plb_get_char = tmpfs_plb_get_char,
    134141        .is_directory = tmpfs_is_directory,
    135         .is_file = tmpfs_is_file
     142        .is_file = tmpfs_is_file,
     143        .device_get = tmpfs_device_get
    136144};
    137145
     
    241249        }
    242250        return EOK;     
     251}
     252
     253int tmpfs_node_open(fs_node_t *fn)
     254{
     255        /* nothing to do */
     256        return EOK;
    243257}
    244258
Note: See TracChangeset for help on using the changeset viewer.