Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/block/libblock.c

    r79ae36dd r7a72ce1a  
    3939#include "libblock.h"
    4040#include "../../srv/vfs/vfs.h"
    41 #include <ipc/devmap.h>
     41#include <ipc/loc.h>
    4242#include <ipc/bd.h>
    4343#include <ipc/services.h>
     
    6060static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
    6161/** Device connection list head. */
    62 static LIST_INITIALIZE(dcl_head);
     62static LIST_INITIALIZE(dcl);
    6363
    6464#define CACHE_BUCKETS_LOG2  10
     
    7272        unsigned blocks_cached;   /**< Number of cached blocks. */
    7373        hash_table_t block_hash;
    74         link_t free_head;
     74        list_t free_list;
    7575        enum cache_mode mode;
    7676} cache_t;
     
    7878typedef struct {
    7979        link_t link;
    80         devmap_handle_t devmap_handle;
     80        service_id_t service_id;
    8181        async_sess_t *sess;
    8282        fibril_mutex_t comm_area_lock;
     
    9393static int get_block_size(async_sess_t *, size_t *);
    9494static int get_num_blocks(async_sess_t *, aoff64_t *);
     95static int read_toc(async_sess_t *, uint8_t);
    9596static aoff64_t ba_ltop(devcon_t *, aoff64_t);
    9697
    97 static devcon_t *devcon_search(devmap_handle_t devmap_handle)
    98 {
    99         link_t *cur;
    100        
     98static devcon_t *devcon_search(service_id_t service_id)
     99{
    101100        fibril_mutex_lock(&dcl_lock);
    102101       
    103         for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     102        list_foreach(dcl, cur) {
    104103                devcon_t *devcon = list_get_instance(cur, devcon_t, link);
    105                 if (devcon->devmap_handle == devmap_handle) {
     104                if (devcon->service_id == service_id) {
    106105                        fibril_mutex_unlock(&dcl_lock);
    107106                        return devcon;
     
    113112}
    114113
    115 static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess,
     114static int devcon_add(service_id_t service_id, async_sess_t *sess,
    116115    size_t bsize, void *comm_area, size_t comm_size)
    117116{
    118         link_t *cur;
    119117        devcon_t *devcon;
    120118       
     
    127125       
    128126        link_initialize(&devcon->link);
    129         devcon->devmap_handle = devmap_handle;
     127        devcon->service_id = service_id;
    130128        devcon->sess = sess;
    131129        fibril_mutex_initialize(&devcon->comm_area_lock);
     
    138136       
    139137        fibril_mutex_lock(&dcl_lock);
    140         for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     138        list_foreach(dcl, cur) {
    141139                devcon_t *d = list_get_instance(cur, devcon_t, link);
    142                 if (d->devmap_handle == devmap_handle) {
     140                if (d->service_id == service_id) {
    143141                        fibril_mutex_unlock(&dcl_lock);
    144142                        free(devcon);
     
    146144                }
    147145        }
    148         list_append(&devcon->link, &dcl_head);
     146        list_append(&devcon->link, &dcl);
    149147        fibril_mutex_unlock(&dcl_lock);
    150148        return EOK;
     
    158156}
    159157
    160 int block_init(exch_mgmt_t mgmt, devmap_handle_t devmap_handle,
     158int block_init(exch_mgmt_t mgmt, service_id_t service_id,
    161159    size_t comm_size)
    162160{
     
    166164                return ENOMEM;
    167165       
    168         async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle,
     166        async_sess_t *sess = loc_service_connect(mgmt, service_id,
    169167            IPC_FLAG_BLOCKING);
    170168        if (!sess) {
     
    193191        }
    194192       
    195         rc = devcon_add(devmap_handle, sess, bsize, comm_area, comm_size);
     193        rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);
    196194        if (rc != EOK) {
    197195                munmap(comm_area, comm_size);
     
    203201}
    204202
    205 void block_fini(devmap_handle_t devmap_handle)
    206 {
    207         devcon_t *devcon = devcon_search(devmap_handle);
     203void block_fini(service_id_t service_id)
     204{
     205        devcon_t *devcon = devcon_search(service_id);
    208206        assert(devcon);
    209207       
    210208        if (devcon->cache)
    211                 (void) block_cache_fini(devmap_handle);
     209                (void) block_cache_fini(service_id);
    212210       
    213211        devcon_remove(devcon);
     
    222220}
    223221
    224 int block_bb_read(devmap_handle_t devmap_handle, aoff64_t ba)
     222int block_bb_read(service_id_t service_id, aoff64_t ba)
    225223{
    226224        void *bb_buf;
    227225        int rc;
    228226
    229         devcon_t *devcon = devcon_search(devmap_handle);
     227        devcon_t *devcon = devcon_search(service_id);
    230228        if (!devcon)
    231229                return ENOENT;
     
    252250}
    253251
    254 void *block_bb_get(devmap_handle_t devmap_handle)
    255 {
    256         devcon_t *devcon = devcon_search(devmap_handle);
     252void *block_bb_get(service_id_t service_id)
     253{
     254        devcon_t *devcon = devcon_search(service_id);
    257255        assert(devcon);
    258256        return devcon->bb_buf;
     
    261259static hash_index_t cache_hash(unsigned long *key)
    262260{
    263         return *key & (CACHE_BUCKETS - 1);
     261        return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
    264262}
    265263
     
    267265{
    268266        block_t *b = hash_table_get_instance(item, block_t, hash_link);
    269         return b->lba == *key;
     267        return b->lba == MERGE_LOUP32(key[0], key[1]);
    270268}
    271269
     
    280278};
    281279
    282 int block_cache_init(devmap_handle_t devmap_handle, size_t size, unsigned blocks,
     280int block_cache_init(service_id_t service_id, size_t size, unsigned blocks,
    283281    enum cache_mode mode)
    284282{
    285         devcon_t *devcon = devcon_search(devmap_handle);
     283        devcon_t *devcon = devcon_search(service_id);
    286284        cache_t *cache;
    287285        if (!devcon)
     
    294292       
    295293        fibril_mutex_initialize(&cache->lock);
    296         list_initialize(&cache->free_head);
     294        list_initialize(&cache->free_list);
    297295        cache->lblock_size = size;
    298296        cache->block_count = blocks;
     
    308306        cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
    309307
    310         if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     308        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
    311309            &cache_ops)) {
    312310                free(cache);
     
    318316}
    319317
    320 int block_cache_fini(devmap_handle_t devmap_handle)
    321 {
    322         devcon_t *devcon = devcon_search(devmap_handle);
     318int block_cache_fini(service_id_t service_id)
     319{
     320        devcon_t *devcon = devcon_search(service_id);
    323321        cache_t *cache;
    324322        int rc;
     
    335333         * bother with the cache and block locks because we are single-threaded.
    336334         */
    337         while (!list_empty(&cache->free_head)) {
    338                 block_t *b = list_get_instance(cache->free_head.next,
     335        while (!list_empty(&cache->free_list)) {
     336                block_t *b = list_get_instance(list_first(&cache->free_list),
    339337                    block_t, free_link);
    340338
     
    347345                }
    348346
    349                 unsigned long key = b->lba;
    350                 hash_table_remove(&cache->block_hash, &key, 1);
     347                unsigned long key[2] = {
     348                        LOWER32(b->lba),
     349                        UPPER32(b->lba)
     350                };
     351                hash_table_remove(&cache->block_hash, key, 2);
    351352               
    352353                free(b->data);
     
    367368        if (cache->blocks_cached < CACHE_LO_WATERMARK)
    368369                return true;
    369         if (!list_empty(&cache->free_head))
     370        if (!list_empty(&cache->free_list))
    370371                return false;
    371372        return true;
     
    387388 * @param block                 Pointer to where the function will store the
    388389 *                              block pointer on success.
    389  * @param devmap_handle         Device handle of the block device.
     390 * @param service_id            Service ID of the block device.
    390391 * @param ba                    Block address (logical).
    391392 * @param flags                 If BLOCK_FLAGS_NOREAD is specified, block_get()
     
    395396 * @return                      EOK on success or a negative error code.
    396397 */
    397 int block_get(block_t **block, devmap_handle_t devmap_handle, aoff64_t ba, int flags)
     398int block_get(block_t **block, service_id_t service_id, aoff64_t ba, int flags)
    398399{
    399400        devcon_t *devcon;
     
    401402        block_t *b;
    402403        link_t *l;
    403         unsigned long key = ba;
     404        unsigned long key[2] = {
     405                LOWER32(ba),
     406                UPPER32(ba)
     407        };
     408
    404409        int rc;
    405410       
    406         devcon = devcon_search(devmap_handle);
     411        devcon = devcon_search(service_id);
    407412
    408413        assert(devcon);
     
    416421
    417422        fibril_mutex_lock(&cache->lock);
    418         l = hash_table_find(&cache->block_hash, &key);
     423        l = hash_table_find(&cache->block_hash, key);
    419424        if (l) {
    420425found:
     
    454459                         * Try to recycle a block from the free list.
    455460                         */
    456                         unsigned long temp_key;
    457461recycle:
    458                         if (list_empty(&cache->free_head)) {
     462                        if (list_empty(&cache->free_list)) {
    459463                                fibril_mutex_unlock(&cache->lock);
    460464                                rc = ENOMEM;
    461465                                goto out;
    462466                        }
    463                         l = cache->free_head.next;
     467                        l = list_first(&cache->free_list);
    464468                        b = list_get_instance(l, block_t, free_link);
    465469
     
    476480                                 */
    477481                                list_remove(&b->free_link);
    478                                 list_append(&b->free_link, &cache->free_head);
     482                                list_append(&b->free_link, &cache->free_list);
    479483                                fibril_mutex_unlock(&cache->lock);
    480484                                fibril_mutex_lock(&devcon->comm_area_lock);
     
    502506                                        goto retry;
    503507                                }
    504                                 l = hash_table_find(&cache->block_hash, &key);
     508                                l = hash_table_find(&cache->block_hash, key);
    505509                                if (l) {
    506510                                        /*
     
    525529                         */
    526530                        list_remove(&b->free_link);
    527                         temp_key = b->lba;
    528                         hash_table_remove(&cache->block_hash, &temp_key, 1);
     531                        unsigned long temp_key[2] = {
     532                                LOWER32(b->lba),
     533                                UPPER32(b->lba)
     534                        };
     535                        hash_table_remove(&cache->block_hash, temp_key, 2);
    529536                }
    530537
    531538                block_initialize(b);
    532                 b->devmap_handle = devmap_handle;
     539                b->service_id = service_id;
    533540                b->size = cache->lblock_size;
    534541                b->lba = ba;
    535542                b->pba = ba_ltop(devcon, b->lba);
    536                 hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     543                hash_table_insert(&cache->block_hash, key, &b->hash_link);
    537544
    538545                /*
     
    580587int block_put(block_t *block)
    581588{
    582         devcon_t *devcon = devcon_search(block->devmap_handle);
     589        devcon_t *devcon = devcon_search(block->service_id);
    583590        cache_t *cache;
    584591        unsigned blocks_cached;
     
    646653                         * Take the block out of the cache and free it.
    647654                         */
    648                         unsigned long key = block->lba;
    649                         hash_table_remove(&cache->block_hash, &key, 1);
     655                        unsigned long key[2] = {
     656                                LOWER32(block->lba),
     657                                UPPER32(block->lba)
     658                        };
     659                        hash_table_remove(&cache->block_hash, key, 2);
    650660                        fibril_mutex_unlock(&block->lock);
    651661                        free(block->data);
     
    668678                        goto retry;
    669679                }
    670                 list_append(&block->free_link, &cache->free_head);
     680                list_append(&block->free_link, &cache->free_list);
    671681        }
    672682        fibril_mutex_unlock(&block->lock);
     
    678688/** Read sequential data from a block device.
    679689 *
    680  * @param devmap_handle Device handle of the block device.
     690 * @param service_id    Service ID of the block device.
    681691 * @param bufpos        Pointer to the first unread valid offset within the
    682692 *                      communication buffer.
     
    690700 * @return              EOK on success or a negative return code on failure.
    691701 */
    692 int block_seqread(devmap_handle_t devmap_handle, size_t *bufpos, size_t *buflen,
     702int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,
    693703    aoff64_t *pos, void *dst, size_t size)
    694704{
     
    698708        devcon_t *devcon;
    699709
    700         devcon = devcon_search(devmap_handle);
     710        devcon = devcon_search(service_id);
    701711        assert(devcon);
    702712        block_size = devcon->pblock_size;
     
    744754/** Read blocks directly from device (bypass cache).
    745755 *
    746  * @param devmap_handle Device handle of the block device.
     756 * @param service_id    Service ID of the block device.
    747757 * @param ba            Address of first block (physical).
    748758 * @param cnt           Number of blocks.
     
    751761 * @return              EOK on success or negative error code on failure.
    752762 */
    753 int block_read_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt, void *buf)
     763int block_read_direct(service_id_t service_id, aoff64_t ba, size_t cnt, void *buf)
    754764{
    755765        devcon_t *devcon;
    756766        int rc;
    757767
    758         devcon = devcon_search(devmap_handle);
     768        devcon = devcon_search(service_id);
    759769        assert(devcon);
    760770       
     
    772782/** Write blocks directly to device (bypass cache).
    773783 *
    774  * @param devmap_handle Device handle of the block device.
     784 * @param service_id    Service ID of the block device.
    775785 * @param ba            Address of first block (physical).
    776786 * @param cnt           Number of blocks.
     
    779789 * @return              EOK on success or negative error code on failure.
    780790 */
    781 int block_write_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt,
     791int block_write_direct(service_id_t service_id, aoff64_t ba, size_t cnt,
    782792    const void *data)
    783793{
     
    785795        int rc;
    786796
    787         devcon = devcon_search(devmap_handle);
     797        devcon = devcon_search(service_id);
    788798        assert(devcon);
    789799       
     
    800810/** Get device block size.
    801811 *
    802  * @param devmap_handle Device handle of the block device.
     812 * @param service_id    Service ID of the block device.
    803813 * @param bsize         Output block size.
    804814 *
    805815 * @return              EOK on success or negative error code on failure.
    806816 */
    807 int block_get_bsize(devmap_handle_t devmap_handle, size_t *bsize)
     817int block_get_bsize(service_id_t service_id, size_t *bsize)
    808818{
    809819        devcon_t *devcon;
    810820
    811         devcon = devcon_search(devmap_handle);
     821        devcon = devcon_search(service_id);
    812822        assert(devcon);
    813823       
     
    817827/** Get number of blocks on device.
    818828 *
    819  * @param devmap_handle Device handle of the block device.
     829 * @param service_id    Service ID of the block device.
    820830 * @param nblocks       Output number of blocks.
    821831 *
    822832 * @return              EOK on success or negative error code on failure.
    823833 */
    824 int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
    825 {
    826         devcon_t *devcon = devcon_search(devmap_handle);
     834int block_get_nblocks(service_id_t service_id, aoff64_t *nblocks)
     835{
     836        devcon_t *devcon = devcon_search(service_id);
    827837        assert(devcon);
    828838       
     
    832842/** Read bytes directly from the device (bypass cache)
    833843 *
    834  * @param devmap_handle Device handle of the block device.
     844 * @param service_id    Service ID of the block device.
    835845 * @param abs_offset    Absolute offset in bytes where to start reading
    836846 * @param bytes                 Number of bytes to read
     
    839849 * @return              EOK on success or negative error code on failure.
    840850 */
    841 int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset,
     851int block_read_bytes_direct(service_id_t service_id, aoff64_t abs_offset,
    842852    size_t bytes, void *data)
    843853{
     
    851861        size_t offset;
    852862       
    853         rc = block_get_bsize(devmap_handle, &phys_block_size);
     863        rc = block_get_bsize(service_id, &phys_block_size);
    854864        if (rc != EOK) {
    855865                return rc;
     
    869879        }
    870880       
    871         rc = block_read_direct(devmap_handle, first_block, blocks, buffer);
     881        rc = block_read_direct(service_id, first_block, blocks, buffer);
    872882        if (rc != EOK) {
    873883                free(buffer);
     
    880890       
    881891        return EOK;
     892}
     893
     894/** Get TOC from device.
     895 *
     896 * @param service_id Service ID of the block device.
     897 * @param session    Starting session.
     898 * @param data       Buffer to read TOC into.
     899 *
     900 * @return EOK on success.
     901 * @return Error code on failure.
     902 *
     903 */
     904int block_get_toc(service_id_t service_id, uint8_t session, void *data)
     905{
     906        devcon_t *devcon = devcon_search(service_id);
     907        assert(devcon);
     908       
     909        fibril_mutex_lock(&devcon->comm_area_lock);
     910       
     911        int rc = read_toc(devcon->sess, session);
     912        if (rc == EOK)
     913                memcpy(data, devcon->comm_area, devcon->pblock_size);
     914       
     915        fibril_mutex_unlock(&devcon->comm_area_lock);
     916       
     917        return rc;
    882918}
    883919
     
    903939                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
    904940                    " from device handle %" PRIun "\n", rc, cnt, ba,
    905                     devcon->devmap_handle);
     941                    devcon->service_id);
    906942#ifndef NDEBUG
    907943                stacktrace_print();
     
    932968        if (rc != EOK) {
    933969                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
    934                     " to device handle %" PRIun "\n", rc, cnt, ba, devcon->devmap_handle);
     970                    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
    935971#ifndef NDEBUG
    936972                stacktrace_print();
     
    9721008}
    9731009
     1010/** Get TOC from block device. */
     1011static int read_toc(async_sess_t *sess, uint8_t session)
     1012{
     1013        async_exch_t *exch = async_exchange_begin(sess);
     1014        int rc = async_req_1_0(exch, BD_READ_TOC, session);
     1015        async_exchange_end(exch);
     1016
     1017        return rc;
     1018}
     1019
    9741020/** Convert logical block address to physical block address. */
    9751021static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
Note: See TracChangeset for help on using the changeset viewer.