Ignore:
File:
1 edited

Legend:

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

    r867e2555 rc7bbf029  
    22 * Copyright (c) 2008 Jakub Jermar
    33 * Copyright (c) 2008 Martin Decky
    4  * Copyright (c) 2011 Martin Sucha
    54 * All rights reserved.
    65 *
     
    6059static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
    6160/** Device connection list head. */
    62 static LIST_INITIALIZE(dcl);
    63 
    64 #define CACHE_BUCKETS_LOG2  10
    65 #define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
     61static LIST_INITIALIZE(dcl_head);
     62
     63#define CACHE_BUCKETS_LOG2              10
     64#define CACHE_BUCKETS                   (1 << CACHE_BUCKETS_LOG2)
    6665
    6766typedef struct {
    6867        fibril_mutex_t lock;
    69         size_t lblock_size;       /**< Logical block size. */
    70         unsigned blocks_cluster;  /**< Physical blocks per block_t */
    71         unsigned block_count;     /**< Total number of blocks. */
    72         unsigned blocks_cached;   /**< Number of cached blocks. */
     68        size_t lblock_size;             /**< Logical block size. */
     69        unsigned blocks_cluster;        /**< Physical blocks per block_t */
     70        unsigned block_count;           /**< Total number of blocks. */
     71        unsigned blocks_cached;         /**< Number of cached blocks. */
    7372        hash_table_t block_hash;
    74         list_t free_list;
     73        link_t free_head;
    7574        enum cache_mode mode;
    7675} cache_t;
     
    7978        link_t link;
    8079        devmap_handle_t devmap_handle;
    81         async_sess_t *sess;
     80        int dev_phone;
    8281        fibril_mutex_t comm_area_lock;
    8382        void *comm_area;
     
    8584        void *bb_buf;
    8685        aoff64_t bb_addr;
    87         size_t pblock_size;  /**< Physical block size. */
     86        size_t pblock_size;             /**< Physical block size. */
    8887        cache_t *cache;
    8988} devcon_t;
    9089
    91 static int read_blocks(devcon_t *, aoff64_t, size_t);
    92 static int write_blocks(devcon_t *, aoff64_t, size_t);
    93 static int get_block_size(async_sess_t *, size_t *);
    94 static int get_num_blocks(async_sess_t *, aoff64_t *);
    95 static aoff64_t ba_ltop(devcon_t *, aoff64_t);
     90static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
     91static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
     92static int get_block_size(int dev_phone, size_t *bsize);
     93static int get_num_blocks(int dev_phone, aoff64_t *nblocks);
     94static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba);
    9695
    9796static devcon_t *devcon_search(devmap_handle_t devmap_handle)
    9897{
     98        link_t *cur;
     99
    99100        fibril_mutex_lock(&dcl_lock);
    100        
    101         list_foreach(dcl, cur) {
     101        for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
    102102                devcon_t *devcon = list_get_instance(cur, devcon_t, link);
    103103                if (devcon->devmap_handle == devmap_handle) {
     
    106106                }
    107107        }
    108        
    109108        fibril_mutex_unlock(&dcl_lock);
    110109        return NULL;
    111110}
    112111
    113 static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess,
    114     size_t bsize, void *comm_area, size_t comm_size)
    115 {
     112static int devcon_add(devmap_handle_t devmap_handle, int dev_phone, size_t bsize,
     113    void *comm_area, size_t comm_size)
     114{
     115        link_t *cur;
    116116        devcon_t *devcon;
    117        
     117
    118118        if (comm_size < bsize)
    119119                return EINVAL;
    120        
     120
    121121        devcon = malloc(sizeof(devcon_t));
    122122        if (!devcon)
     
    125125        link_initialize(&devcon->link);
    126126        devcon->devmap_handle = devmap_handle;
    127         devcon->sess = sess;
     127        devcon->dev_phone = dev_phone;
    128128        fibril_mutex_initialize(&devcon->comm_area_lock);
    129129        devcon->comm_area = comm_area;
     
    133133        devcon->pblock_size = bsize;
    134134        devcon->cache = NULL;
    135        
     135
    136136        fibril_mutex_lock(&dcl_lock);
    137         list_foreach(dcl, cur) {
     137        for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
    138138                devcon_t *d = list_get_instance(cur, devcon_t, link);
    139139                if (d->devmap_handle == devmap_handle) {
     
    143143                }
    144144        }
    145         list_append(&devcon->link, &dcl);
     145        list_append(&devcon->link, &dcl_head);
    146146        fibril_mutex_unlock(&dcl_lock);
    147147        return EOK;
     
    155155}
    156156
    157 int block_init(exch_mgmt_t mgmt, devmap_handle_t devmap_handle,
    158     size_t comm_size)
    159 {
    160         void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
     157int block_init(devmap_handle_t devmap_handle, size_t comm_size)
     158{
     159        int rc;
     160        int dev_phone;
     161        void *comm_area;
     162        size_t bsize;
     163
     164        comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    161165            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    162         if (!comm_area)
     166        if (!comm_area) {
    163167                return ENOMEM;
    164        
    165         async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle,
    166             IPC_FLAG_BLOCKING);
    167         if (!sess) {
     168        }
     169
     170        dev_phone = devmap_device_connect(devmap_handle, IPC_FLAG_BLOCKING);
     171        if (dev_phone < 0) {
    168172                munmap(comm_area, comm_size);
    169                 return ENOENT;
    170         }
    171        
    172         async_exch_t *exch = async_exchange_begin(sess);
    173         int rc = async_share_out_start(exch, comm_area,
     173                return dev_phone;
     174        }
     175
     176        rc = async_share_out_start(dev_phone, comm_area,
    174177            AS_AREA_READ | AS_AREA_WRITE);
    175         async_exchange_end(exch);
    176        
     178        if (rc != EOK) {
     179                munmap(comm_area, comm_size);
     180                async_hangup(dev_phone);
     181                return rc;
     182        }
     183
     184        if (get_block_size(dev_phone, &bsize) != EOK) {
     185                munmap(comm_area, comm_size);
     186                async_hangup(dev_phone);
     187                return rc;
     188        }
     189       
     190        rc = devcon_add(devmap_handle, dev_phone, bsize, comm_area, comm_size);
    177191        if (rc != EOK) {
    178192                munmap(comm_area, comm_size);
    179                 async_hangup(sess);
     193                async_hangup(dev_phone);
    180194                return rc;
    181195        }
    182        
    183         size_t bsize;
    184         rc = get_block_size(sess, &bsize);
    185        
    186         if (rc != EOK) {
    187                 munmap(comm_area, comm_size);
    188                 async_hangup(sess);
    189                 return rc;
    190         }
    191        
    192         rc = devcon_add(devmap_handle, sess, bsize, comm_area, comm_size);
    193         if (rc != EOK) {
    194                 munmap(comm_area, comm_size);
    195                 async_hangup(sess);
    196                 return rc;
    197         }
    198        
     196
    199197        return EOK;
    200198}
     
    207205        if (devcon->cache)
    208206                (void) block_cache_fini(devmap_handle);
    209        
     207
    210208        devcon_remove(devcon);
    211        
     209
    212210        if (devcon->bb_buf)
    213211                free(devcon->bb_buf);
    214        
     212
    215213        munmap(devcon->comm_area, devcon->comm_size);
    216         async_hangup(devcon->sess);
    217        
    218         free(devcon);
     214        async_hangup(devcon->dev_phone);
     215
     216        free(devcon);   
    219217}
    220218
     
    258256static hash_index_t cache_hash(unsigned long *key)
    259257{
    260         return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
     258        return *key & (CACHE_BUCKETS - 1);
    261259}
    262260
     
    264262{
    265263        block_t *b = hash_table_get_instance(item, block_t, hash_link);
    266         return b->lba == MERGE_LOUP32(key[0], key[1]);
     264        return b->lba == *key;
    267265}
    268266
     
    291289       
    292290        fibril_mutex_initialize(&cache->lock);
    293         list_initialize(&cache->free_list);
     291        list_initialize(&cache->free_head);
    294292        cache->lblock_size = size;
    295293        cache->block_count = blocks;
     
    305303        cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
    306304
    307         if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
     305        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
    308306            &cache_ops)) {
    309307                free(cache);
     
    332330         * bother with the cache and block locks because we are single-threaded.
    333331         */
    334         while (!list_empty(&cache->free_list)) {
    335                 block_t *b = list_get_instance(list_first(&cache->free_list),
     332        while (!list_empty(&cache->free_head)) {
     333                block_t *b = list_get_instance(cache->free_head.next,
    336334                    block_t, free_link);
    337335
     
    344342                }
    345343
    346                 unsigned long key[2] = {
    347                         LOWER32(b->lba),
    348                         UPPER32(b->lba)
    349                 };
    350                 hash_table_remove(&cache->block_hash, key, 2);
     344                unsigned long key = b->lba;
     345                hash_table_remove(&cache->block_hash, &key, 1);
    351346               
    352347                free(b->data);
     
    367362        if (cache->blocks_cached < CACHE_LO_WATERMARK)
    368363                return true;
    369         if (!list_empty(&cache->free_list))
     364        if (!list_empty(&cache->free_head))
    370365                return false;
    371366        return true;
     
    401396        block_t *b;
    402397        link_t *l;
    403         unsigned long key[2] = {
    404                 LOWER32(ba),
    405                 UPPER32(ba)
    406         };
    407 
     398        unsigned long key = ba;
    408399        int rc;
    409400       
     
    420411
    421412        fibril_mutex_lock(&cache->lock);
    422         l = hash_table_find(&cache->block_hash, key);
     413        l = hash_table_find(&cache->block_hash, &key);
    423414        if (l) {
    424415found:
     
    458449                         * Try to recycle a block from the free list.
    459450                         */
     451                        unsigned long temp_key;
    460452recycle:
    461                         if (list_empty(&cache->free_list)) {
     453                        if (list_empty(&cache->free_head)) {
    462454                                fibril_mutex_unlock(&cache->lock);
    463455                                rc = ENOMEM;
    464456                                goto out;
    465457                        }
    466                         l = list_first(&cache->free_list);
     458                        l = cache->free_head.next;
    467459                        b = list_get_instance(l, block_t, free_link);
    468460
     
    479471                                 */
    480472                                list_remove(&b->free_link);
    481                                 list_append(&b->free_link, &cache->free_list);
     473                                list_append(&b->free_link, &cache->free_head);
    482474                                fibril_mutex_unlock(&cache->lock);
    483475                                fibril_mutex_lock(&devcon->comm_area_lock);
     
    505497                                        goto retry;
    506498                                }
    507                                 l = hash_table_find(&cache->block_hash, key);
     499                                l = hash_table_find(&cache->block_hash, &key);
    508500                                if (l) {
    509501                                        /*
     
    528520                         */
    529521                        list_remove(&b->free_link);
    530                         unsigned long temp_key[2] = {
    531                                 LOWER32(b->lba),
    532                                 UPPER32(b->lba)
    533                         };
    534                         hash_table_remove(&cache->block_hash, temp_key, 2);
     522                        temp_key = b->lba;
     523                        hash_table_remove(&cache->block_hash, &temp_key, 1);
    535524                }
    536525
     
    540529                b->lba = ba;
    541530                b->pba = ba_ltop(devcon, b->lba);
    542                 hash_table_insert(&cache->block_hash, key, &b->hash_link);
     531                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
    543532
    544533                /*
     
    652641                         * Take the block out of the cache and free it.
    653642                         */
    654                         unsigned long key[2] = {
    655                                 LOWER32(block->lba),
    656                                 UPPER32(block->lba)
    657                         };
    658                         hash_table_remove(&cache->block_hash, key, 2);
     643                        unsigned long key = block->lba;
     644                        hash_table_remove(&cache->block_hash, &key, 1);
    659645                        fibril_mutex_unlock(&block->lock);
    660646                        free(block->data);
     
    677663                        goto retry;
    678664                }
    679                 list_append(&block->free_link, &cache->free_list);
     665                list_append(&block->free_link, &cache->free_head);
    680666        }
    681667        fibril_mutex_unlock(&block->lock);
     
    821807        assert(devcon);
    822808       
    823         return get_block_size(devcon->sess, bsize);
     809        return get_block_size(devcon->dev_phone, bsize);
    824810}
    825811
     
    833819int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
    834820{
    835         devcon_t *devcon = devcon_search(devmap_handle);
    836         assert(devcon);
    837        
    838         return get_num_blocks(devcon->sess, nblocks);
    839 }
    840 
    841 /** Read bytes directly from the device (bypass cache)
    842  *
    843  * @param devmap_handle Device handle of the block device.
    844  * @param abs_offset    Absolute offset in bytes where to start reading
    845  * @param bytes                 Number of bytes to read
    846  * @param data                  Buffer that receives the data
    847  *
    848  * @return              EOK on success or negative error code on failure.
    849  */
    850 int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset,
    851     size_t bytes, void *data)
    852 {
    853         int rc;
    854         size_t phys_block_size;
    855         size_t buf_size;
    856         void *buffer;
    857         aoff64_t first_block;
    858         aoff64_t last_block;
    859         size_t blocks;
    860         size_t offset;
    861        
    862         rc = block_get_bsize(devmap_handle, &phys_block_size);
    863         if (rc != EOK) {
    864                 return rc;
    865         }
    866        
    867         /* calculate data position and required space */
    868         first_block = abs_offset / phys_block_size;
    869         offset = abs_offset % phys_block_size;
    870         last_block = (abs_offset + bytes - 1) / phys_block_size;
    871         blocks = last_block - first_block + 1;
    872         buf_size = blocks * phys_block_size;
    873        
    874         /* read the data into memory */
    875         buffer = malloc(buf_size);
    876         if (buffer == NULL) {
    877                 return ENOMEM;
    878         }
    879        
    880         rc = block_read_direct(devmap_handle, first_block, blocks, buffer);
    881         if (rc != EOK) {
    882                 free(buffer);
    883                 return rc;
    884         }
    885        
    886         /* copy the data from the buffer */
    887         memcpy(data, buffer + offset, bytes);
    888         free(buffer);
    889        
    890         return EOK;
     821        devcon_t *devcon;
     822
     823        devcon = devcon_search(devmap_handle);
     824        assert(devcon);
     825       
     826        return get_num_blocks(devcon->dev_phone, nblocks);
    891827}
    892828
     
    902838static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    903839{
    904         assert(devcon);
    905        
    906         async_exch_t *exch = async_exchange_begin(devcon->sess);
    907         int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba),
     840        int rc;
     841
     842        assert(devcon);
     843        rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
    908844            UPPER32(ba), cnt);
    909         async_exchange_end(exch);
    910        
    911845        if (rc != EOK) {
    912846                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
     
    917851#endif
    918852        }
    919        
    920853        return rc;
    921854}
     
    932865static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    933866{
    934         assert(devcon);
    935        
    936         async_exch_t *exch = async_exchange_begin(devcon->sess);
    937         int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba),
     867        int rc;
     868
     869        assert(devcon);
     870        rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
    938871            UPPER32(ba), cnt);
    939         async_exchange_end(exch);
    940        
    941872        if (rc != EOK) {
    942873                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
     
    946877#endif
    947878        }
    948        
    949879        return rc;
    950880}
    951881
    952882/** Get block size used by the device. */
    953 static int get_block_size(async_sess_t *sess, size_t *bsize)
     883static int get_block_size(int dev_phone, size_t *bsize)
    954884{
    955885        sysarg_t bs;
    956        
    957         async_exch_t *exch = async_exchange_begin(sess);
    958         int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);
    959         async_exchange_end(exch);
    960        
     886        int rc;
     887
     888        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
    961889        if (rc == EOK)
    962890                *bsize = (size_t) bs;
    963        
     891
    964892        return rc;
    965893}
    966894
    967895/** Get total number of blocks on block device. */
    968 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)
    969 {
    970         sysarg_t nb_l;
    971         sysarg_t nb_h;
    972        
    973         async_exch_t *exch = async_exchange_begin(sess);
    974         int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
    975         async_exchange_end(exch);
    976        
    977         if (rc == EOK)
     896static int get_num_blocks(int dev_phone, aoff64_t *nblocks)
     897{
     898        sysarg_t nb_l, nb_h;
     899        int rc;
     900
     901        rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
     902        if (rc == EOK) {
    978903                *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
    979        
     904        }
     905
    980906        return rc;
    981907}
Note: See TracChangeset for help on using the changeset viewer.