Ignore:
File:
1 edited

Legend:

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

    r228e490 rcfd630af  
    3636 */
    3737
    38 #include <ipc/ipc.h>
    3938#include <macros.h>
    4039#include <bool.h>
     
    6059typedef struct {
    6160        devmap_handle_t handle;
    62         int phone;
     61        int phone;              /**< When < 0, the structure is incomplete. */
    6362        size_t refcount;
    6463        link_t link;
     64        fibril_condvar_t cv;    /**< Broadcast when completed. */
    6565} device_t;
    6666
     
    130130{
    131131        devfs_node_t *node = (devfs_node_t *) pfn->data;
     132        int ret;
    132133       
    133134        if (node->handle == 0) {
     
    145146                               
    146147                                if (str_cmp(devs[pos].name, component) == 0) {
     148                                        ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
    147149                                        free(devs);
    148                                         return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
     150                                        return ret;
    149151                                }
    150152                        }
     
    162164                                for (pos = 0; pos < count; pos++) {
    163165                                        if (str_cmp(devs[pos].name, component) == 0) {
     166                                                ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    164167                                                free(devs);
    165                                                 return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
     168                                                return ret;
    166169                                        }
    167170                                }
     
    184187                        for (pos = 0; pos < count; pos++) {
    185188                                if (str_cmp(devs[pos].name, component) == 0) {
     189                                        ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    186190                                        free(devs);
    187                                         return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
     191                                        return ret;
    188192                                }
    189193                        }
     
    227231                        [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
    228232                };
    229                
     233                link_t *lnk;
     234
    230235                fibril_mutex_lock(&devices_mutex);
    231                 link_t *lnk = hash_table_find(&devices, key);
     236restart:
     237                lnk = hash_table_find(&devices, key);
    232238                if (lnk == NULL) {
    233239                        device_t *dev = (device_t *) malloc(sizeof(device_t));
     
    237243                        }
    238244                       
     245                        dev->handle = node->handle;
     246                        dev->phone = -1;        /* mark as incomplete */
     247                        dev->refcount = 1;
     248                        fibril_condvar_initialize(&dev->cv);
     249
     250                        /*
     251                         * Insert the incomplete device structure so that other
     252                         * fibrils will not race with us when we drop the mutex
     253                         * below.
     254                         */
     255                        hash_table_insert(&devices, key, &dev->link);
     256
     257                        /*
     258                         * Drop the mutex to allow recursive devfs requests.
     259                         */
     260                        fibril_mutex_unlock(&devices_mutex);
     261
    239262                        int phone = devmap_device_connect(node->handle, 0);
     263
     264                        fibril_mutex_lock(&devices_mutex);
     265
     266                        /*
     267                         * Notify possible waiters about this device structure
     268                         * being completed (or destroyed).
     269                         */
     270                        fibril_condvar_broadcast(&dev->cv);
     271
    240272                        if (phone < 0) {
     273                                /*
     274                                 * Connecting failed, need to remove the
     275                                 * entry and free the device structure.
     276                                 */
     277                                hash_table_remove(&devices, key, DEVICES_KEYS);
    241278                                fibril_mutex_unlock(&devices_mutex);
    242                                 free(dev);
     279
    243280                                return ENOENT;
    244281                        }
    245282                       
    246                         dev->handle = node->handle;
     283                        /* Set the correct phone. */
    247284                        dev->phone = phone;
    248                         dev->refcount = 1;
    249                        
    250                         hash_table_insert(&devices, key, &dev->link);
    251285                } else {
    252286                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
     287
     288                        if (dev->phone < 0) {
     289                                /*
     290                                 * Wait until the device structure is completed
     291                                 * and start from the beginning as the device
     292                                 * structure might have entirely disappeared
     293                                 * while we were not holding the mutex in
     294                                 * fibril_condvar_wait().
     295                                 */
     296                                fibril_condvar_wait(&dev->cv, &devices_mutex);
     297                                goto restart;
     298                        }
     299
    253300                        dev->refcount++;
    254301                }
     
    409456                return false;
    410457       
    411         if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
    412                 return false;
    413        
    414458        return true;
    415459}
     
    423467            0, NULL);
    424468        if (retval != EOK) {
    425                 ipc_answer_0(rid, retval);
     469                async_answer_0(rid, retval);
    426470                return;
    427471        }
    428472       
    429473        free(opts);
    430         ipc_answer_3(rid, EOK, 0, 0, 0);
     474        async_answer_3(rid, EOK, 0, 0, 0);
    431475}
    432476
     
    438482void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
    439483{
    440         ipc_answer_0(rid, ENOTSUP);
     484        async_answer_0(rid, ENOTSUP);
    441485}
    442486
     
    471515                size_t size;
    472516                if (!async_data_read_receive(&callid, &size)) {
    473                         ipc_answer_0(callid, EINVAL);
    474                         ipc_answer_0(rid, EINVAL);
     517                        async_answer_0(callid, EINVAL);
     518                        async_answer_0(rid, EINVAL);
    475519                        return;
    476520                }
     
    493537                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    494538                        free(desc);
    495                         ipc_answer_1(rid, EOK, 1);
     539                        async_answer_1(rid, EOK, 1);
    496540                        return;
    497541                }
     
    508552                                async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    509553                                free(desc);
    510                                 ipc_answer_1(rid, EOK, 1);
     554                                async_answer_1(rid, EOK, 1);
    511555                                return;
    512556                        }
     
    515559                }
    516560               
    517                 ipc_answer_0(callid, ENOENT);
    518                 ipc_answer_1(rid, ENOENT, 0);
     561                async_answer_0(callid, ENOENT);
     562                async_answer_1(rid, ENOENT, 0);
    519563                return;
    520564        }
     
    527571                size_t size;
    528572                if (!async_data_read_receive(&callid, &size)) {
    529                         ipc_answer_0(callid, EINVAL);
    530                         ipc_answer_0(rid, EINVAL);
     573                        async_answer_0(callid, EINVAL);
     574                        async_answer_0(rid, EINVAL);
    531575                        return;
    532576                }
     
    538582                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    539583                        free(desc);
    540                         ipc_answer_1(rid, EOK, 1);
     584                        async_answer_1(rid, EOK, 1);
    541585                        return;
    542586                }
    543587               
    544588                free(desc);
    545                 ipc_answer_0(callid, ENOENT);
    546                 ipc_answer_1(rid, ENOENT, 0);
     589                async_answer_0(callid, ENOENT);
     590                async_answer_1(rid, ENOENT, 0);
    547591                return;
    548592        }
     
    559603                if (lnk == NULL) {
    560604                        fibril_mutex_unlock(&devices_mutex);
    561                         ipc_answer_0(rid, ENOENT);
     605                        async_answer_0(rid, ENOENT);
    562606                        return;
    563607                }
    564608               
    565609                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     610                assert(dev->phone >= 0);
    566611               
    567612                ipc_callid_t callid;
    568613                if (!async_data_read_receive(&callid, NULL)) {
    569614                        fibril_mutex_unlock(&devices_mutex);
    570                         ipc_answer_0(callid, EINVAL);
    571                         ipc_answer_0(rid, EINVAL);
     615                        async_answer_0(callid, EINVAL);
     616                        async_answer_0(rid, EINVAL);
    572617                        return;
    573618                }
     
    580625               
    581626                /* Forward the IPC_M_DATA_READ request to the driver */
    582                 ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     627                async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    583628                fibril_mutex_unlock(&devices_mutex);
    584629               
     
    589634               
    590635                /* Driver reply is the final result of the whole operation */
    591                 ipc_answer_1(rid, rc, bytes);
    592                 return;
    593         }
    594        
    595         ipc_answer_0(rid, ENOENT);
     636                async_answer_1(rid, rc, bytes);
     637                return;
     638        }
     639       
     640        async_answer_0(rid, ENOENT);
    596641}
    597642
     
    600645        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    601646        if (index == 0) {
    602                 ipc_answer_0(rid, ENOTSUP);
     647                async_answer_0(rid, ENOTSUP);
    603648                return;
    604649        }
     
    608653        if (type == DEV_HANDLE_NAMESPACE) {
    609654                /* Namespace directory */
    610                 ipc_answer_0(rid, ENOTSUP);
     655                async_answer_0(rid, ENOTSUP);
    611656                return;
    612657        }
     
    622667                if (lnk == NULL) {
    623668                        fibril_mutex_unlock(&devices_mutex);
    624                         ipc_answer_0(rid, ENOENT);
     669                        async_answer_0(rid, ENOENT);
    625670                        return;
    626671                }
    627672               
    628673                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     674                assert(dev->phone >= 0);
    629675               
    630676                ipc_callid_t callid;
    631677                if (!async_data_write_receive(&callid, NULL)) {
    632678                        fibril_mutex_unlock(&devices_mutex);
    633                         ipc_answer_0(callid, EINVAL);
    634                         ipc_answer_0(rid, EINVAL);
     679                        async_answer_0(callid, EINVAL);
     680                        async_answer_0(rid, EINVAL);
    635681                        return;
    636682                }
     
    643689               
    644690                /* Forward the IPC_M_DATA_WRITE request to the driver */
    645                 ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     691                async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    646692               
    647693                fibril_mutex_unlock(&devices_mutex);
     
    653699               
    654700                /* Driver reply is the final result of the whole operation */
    655                 ipc_answer_1(rid, rc, bytes);
    656                 return;
    657         }
    658        
    659         ipc_answer_0(rid, ENOENT);
     701                async_answer_1(rid, rc, bytes);
     702                return;
     703        }
     704       
     705        async_answer_0(rid, ENOENT);
    660706}
    661707
    662708void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
    663709{
    664         ipc_answer_0(rid, ENOTSUP);
     710        async_answer_0(rid, ENOTSUP);
    665711}
    666712
     
    670716       
    671717        if (index == 0) {
    672                 ipc_answer_0(rid, EOK);
     718                async_answer_0(rid, EOK);
    673719                return;
    674720        }
     
    678724        if (type == DEV_HANDLE_NAMESPACE) {
    679725                /* Namespace directory */
    680                 ipc_answer_0(rid, EOK);
     726                async_answer_0(rid, EOK);
    681727                return;
    682728        }
     
    691737                if (lnk == NULL) {
    692738                        fibril_mutex_unlock(&devices_mutex);
    693                         ipc_answer_0(rid, ENOENT);
     739                        async_answer_0(rid, ENOENT);
    694740                        return;
    695741                }
    696742               
    697743                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     744                assert(dev->phone >= 0);
    698745                dev->refcount--;
    699746               
    700747                if (dev->refcount == 0) {
    701                         ipc_hangup(dev->phone);
     748                        async_hangup(dev->phone);
    702749                        hash_table_remove(&devices, key, DEVICES_KEYS);
    703750                }
     
    705752                fibril_mutex_unlock(&devices_mutex);
    706753               
    707                 ipc_answer_0(rid, EOK);
    708                 return;
    709         }
    710        
    711         ipc_answer_0(rid, ENOENT);
     754                async_answer_0(rid, EOK);
     755                return;
     756        }
     757       
     758        async_answer_0(rid, ENOENT);
    712759}
    713760
     
    717764       
    718765        if (index == 0) {
    719                 ipc_answer_0(rid, EOK);
     766                async_answer_0(rid, EOK);
    720767                return;
    721768        }
     
    725772        if (type == DEV_HANDLE_NAMESPACE) {
    726773                /* Namespace directory */
    727                 ipc_answer_0(rid, EOK);
     774                async_answer_0(rid, EOK);
    728775                return;
    729776        }
     
    738785                if (lnk == NULL) {
    739786                        fibril_mutex_unlock(&devices_mutex);
    740                         ipc_answer_0(rid, ENOENT);
     787                        async_answer_0(rid, ENOENT);
    741788                        return;
    742789                }
    743790               
    744791                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     792                assert(dev->phone >= 0);
    745793               
    746794                /* Make a request at the driver */
     
    756804               
    757805                /* Driver reply is the final result of the whole operation */
    758                 ipc_answer_0(rid, rc);
    759                 return;
    760         }
    761        
    762         ipc_answer_0(rid, ENOENT);
     806                async_answer_0(rid, rc);
     807                return;
     808        }
     809       
     810        async_answer_0(rid, ENOENT);
    763811}
    764812
    765813void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
    766814{
    767         ipc_answer_0(rid, ENOTSUP);
     815        async_answer_0(rid, ENOTSUP);
    768816}
    769817
Note: See TracChangeset for help on using the changeset viewer.