Ignore:
File:
1 edited

Legend:

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

    rb72efe8 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
     
    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;
     
    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
     
    364362        if (cache->blocks_cached < CACHE_LO_WATERMARK)
    365363                return true;
    366         if (!list_empty(&cache->free_list))
     364        if (!list_empty(&cache->free_head))
    367365                return false;
    368366        return true;
     
    453451                        unsigned long temp_key;
    454452recycle:
    455                         if (list_empty(&cache->free_list)) {
     453                        if (list_empty(&cache->free_head)) {
    456454                                fibril_mutex_unlock(&cache->lock);
    457455                                rc = ENOMEM;
    458456                                goto out;
    459457                        }
    460                         l = list_first(&cache->free_list);
     458                        l = cache->free_head.next;
    461459                        b = list_get_instance(l, block_t, free_link);
    462460
     
    473471                                 */
    474472                                list_remove(&b->free_link);
    475                                 list_append(&b->free_link, &cache->free_list);
     473                                list_append(&b->free_link, &cache->free_head);
    476474                                fibril_mutex_unlock(&cache->lock);
    477475                                fibril_mutex_lock(&devcon->comm_area_lock);
     
    665663                        goto retry;
    666664                }
    667                 list_append(&block->free_link, &cache->free_list);
     665                list_append(&block->free_link, &cache->free_head);
    668666        }
    669667        fibril_mutex_unlock(&block->lock);
     
    809807        assert(devcon);
    810808       
    811         return get_block_size(devcon->sess, bsize);
     809        return get_block_size(devcon->dev_phone, bsize);
    812810}
    813811
     
    821819int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
    822820{
    823         devcon_t *devcon = devcon_search(devmap_handle);
    824         assert(devcon);
    825        
    826         return get_num_blocks(devcon->sess, nblocks);
    827 }
    828 
    829 /** Read bytes directly from the device (bypass cache)
    830  *
    831  * @param devmap_handle Device handle of the block device.
    832  * @param abs_offset    Absolute offset in bytes where to start reading
    833  * @param bytes                 Number of bytes to read
    834  * @param data                  Buffer that receives the data
    835  *
    836  * @return              EOK on success or negative error code on failure.
    837  */
    838 int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset,
    839     size_t bytes, void *data)
    840 {
    841         int rc;
    842         size_t phys_block_size;
    843         size_t buf_size;
    844         void *buffer;
    845         aoff64_t first_block;
    846         aoff64_t last_block;
    847         size_t blocks;
    848         size_t offset;
    849        
    850         rc = block_get_bsize(devmap_handle, &phys_block_size);
    851         if (rc != EOK) {
    852                 return rc;
    853         }
    854        
    855         /* calculate data position and required space */
    856         first_block = abs_offset / phys_block_size;
    857         offset = abs_offset % phys_block_size;
    858         last_block = (abs_offset + bytes - 1) / phys_block_size;
    859         blocks = last_block - first_block + 1;
    860         buf_size = blocks * phys_block_size;
    861        
    862         /* read the data into memory */
    863         buffer = malloc(buf_size);
    864         if (buffer == NULL) {
    865                 return ENOMEM;
    866         }
    867        
    868         rc = block_read_direct(devmap_handle, first_block, blocks, buffer);
    869         if (rc != EOK) {
    870                 free(buffer);
    871                 return rc;
    872         }
    873        
    874         /* copy the data from the buffer */
    875         memcpy(data, buffer + offset, bytes);
    876         free(buffer);
    877        
    878         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);
    879827}
    880828
     
    890838static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    891839{
    892         assert(devcon);
    893        
    894         async_exch_t *exch = async_exchange_begin(devcon->sess);
    895         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),
    896844            UPPER32(ba), cnt);
    897         async_exchange_end(exch);
    898        
    899845        if (rc != EOK) {
    900846                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
     
    905851#endif
    906852        }
    907        
    908853        return rc;
    909854}
     
    920865static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    921866{
    922         assert(devcon);
    923        
    924         async_exch_t *exch = async_exchange_begin(devcon->sess);
    925         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),
    926871            UPPER32(ba), cnt);
    927         async_exchange_end(exch);
    928        
    929872        if (rc != EOK) {
    930873                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
     
    934877#endif
    935878        }
    936        
    937879        return rc;
    938880}
    939881
    940882/** Get block size used by the device. */
    941 static int get_block_size(async_sess_t *sess, size_t *bsize)
     883static int get_block_size(int dev_phone, size_t *bsize)
    942884{
    943885        sysarg_t bs;
    944        
    945         async_exch_t *exch = async_exchange_begin(sess);
    946         int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);
    947         async_exchange_end(exch);
    948        
     886        int rc;
     887
     888        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
    949889        if (rc == EOK)
    950890                *bsize = (size_t) bs;
    951        
     891
    952892        return rc;
    953893}
    954894
    955895/** Get total number of blocks on block device. */
    956 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)
    957 {
    958         sysarg_t nb_l;
    959         sysarg_t nb_h;
    960        
    961         async_exch_t *exch = async_exchange_begin(sess);
    962         int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
    963         async_exchange_end(exch);
    964        
    965         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) {
    966903                *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
    967        
     904        }
     905
    968906        return rc;
    969907}
Note: See TracChangeset for help on using the changeset viewer.