Changeset 6a44ee4 in mainline for uspace/lib/block/libblock.c


Ignore:
Timestamp:
2011-07-20T15:26:21Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
efcebe1
Parents:
25bef0ff (diff), a701812 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r25bef0ff r6a44ee4  
    22 * Copyright (c) 2008 Jakub Jermar
    33 * Copyright (c) 2008 Martin Decky
     4 * Copyright (c) 2011 Martin Sucha
    45 * All rights reserved.
    56 *
     
    5960static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
    6061/** Device connection list head. */
    61 static LIST_INITIALIZE(dcl_head);
    62 
    63 #define CACHE_BUCKETS_LOG2              10
    64 #define CACHE_BUCKETS                   (1 << CACHE_BUCKETS_LOG2)
     62static LIST_INITIALIZE(dcl);
     63
     64#define CACHE_BUCKETS_LOG2  10
     65#define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
    6566
    6667typedef struct {
    6768        fibril_mutex_t lock;
    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. */
     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. */
    7273        hash_table_t block_hash;
    73         link_t free_head;
     74        list_t free_list;
    7475        enum cache_mode mode;
    7576} cache_t;
     
    7879        link_t link;
    7980        devmap_handle_t devmap_handle;
    80         int dev_phone;
     81        async_sess_t *sess;
    8182        fibril_mutex_t comm_area_lock;
    8283        void *comm_area;
     
    8485        void *bb_buf;
    8586        aoff64_t bb_addr;
    86         size_t pblock_size;             /**< Physical block size. */
     87        size_t pblock_size;  /**< Physical block size. */
    8788        cache_t *cache;
    8889} devcon_t;
    8990
    90 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
    91 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
    92 static int get_block_size(int dev_phone, size_t *bsize);
    93 static int get_num_blocks(int dev_phone, aoff64_t *nblocks);
    94 static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba);
     91static int read_blocks(devcon_t *, aoff64_t, size_t);
     92static int write_blocks(devcon_t *, aoff64_t, size_t);
     93static int get_block_size(async_sess_t *, size_t *);
     94static int get_num_blocks(async_sess_t *, aoff64_t *);
     95static aoff64_t ba_ltop(devcon_t *, aoff64_t);
    9596
    9697static devcon_t *devcon_search(devmap_handle_t devmap_handle)
    9798{
    98         link_t *cur;
    99 
    10099        fibril_mutex_lock(&dcl_lock);
    101         for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     100       
     101        list_foreach(dcl, cur) {
    102102                devcon_t *devcon = list_get_instance(cur, devcon_t, link);
    103103                if (devcon->devmap_handle == devmap_handle) {
     
    106106                }
    107107        }
     108       
    108109        fibril_mutex_unlock(&dcl_lock);
    109110        return NULL;
    110111}
    111112
    112 static 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;
     113static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess,
     114    size_t bsize, void *comm_area, size_t comm_size)
     115{
    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->dev_phone = dev_phone;
     127        devcon->sess = sess;
    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         for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
     137        list_foreach(dcl, cur) {
    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_head);
     145        list_append(&devcon->link, &dcl);
    146146        fibril_mutex_unlock(&dcl_lock);
    147147        return EOK;
     
    155155}
    156156
    157 int 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,
     157int 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,
    165161            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    166         if (!comm_area) {
     162        if (!comm_area)
    167163                return ENOMEM;
    168         }
    169 
    170         dev_phone = devmap_device_connect(devmap_handle, IPC_FLAG_BLOCKING);
    171         if (dev_phone < 0) {
     164       
     165        async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle,
     166            IPC_FLAG_BLOCKING);
     167        if (!sess) {
    172168                munmap(comm_area, comm_size);
    173                 return dev_phone;
    174         }
    175 
    176         rc = async_share_out_start(dev_phone, comm_area,
     169                return ENOENT;
     170        }
     171       
     172        async_exch_t *exch = async_exchange_begin(sess);
     173        int rc = async_share_out_start(exch, comm_area,
    177174            AS_AREA_READ | AS_AREA_WRITE);
    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);
     175        async_exchange_end(exch);
     176       
    191177        if (rc != EOK) {
    192178                munmap(comm_area, comm_size);
    193                 async_hangup(dev_phone);
     179                async_hangup(sess);
    194180                return rc;
    195181        }
    196 
     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       
    197199        return EOK;
    198200}
     
    205207        if (devcon->cache)
    206208                (void) block_cache_fini(devmap_handle);
    207 
     209       
    208210        devcon_remove(devcon);
    209 
     211       
    210212        if (devcon->bb_buf)
    211213                free(devcon->bb_buf);
    212 
     214       
    213215        munmap(devcon->comm_area, devcon->comm_size);
    214         async_hangup(devcon->dev_phone);
    215 
    216         free(devcon);   
     216        async_hangup(devcon->sess);
     217       
     218        free(devcon);
    217219}
    218220
     
    289291       
    290292        fibril_mutex_initialize(&cache->lock);
    291         list_initialize(&cache->free_head);
     293        list_initialize(&cache->free_list);
    292294        cache->lblock_size = size;
    293295        cache->block_count = blocks;
     
    330332         * bother with the cache and block locks because we are single-threaded.
    331333         */
    332         while (!list_empty(&cache->free_head)) {
    333                 block_t *b = list_get_instance(cache->free_head.next,
     334        while (!list_empty(&cache->free_list)) {
     335                block_t *b = list_get_instance(list_first(&cache->free_list),
    334336                    block_t, free_link);
    335337
     
    362364        if (cache->blocks_cached < CACHE_LO_WATERMARK)
    363365                return true;
    364         if (!list_empty(&cache->free_head))
     366        if (!list_empty(&cache->free_list))
    365367                return false;
    366368        return true;
     
    451453                        unsigned long temp_key;
    452454recycle:
    453                         if (list_empty(&cache->free_head)) {
     455                        if (list_empty(&cache->free_list)) {
    454456                                fibril_mutex_unlock(&cache->lock);
    455457                                rc = ENOMEM;
    456458                                goto out;
    457459                        }
    458                         l = cache->free_head.next;
     460                        l = list_first(&cache->free_list);
    459461                        b = list_get_instance(l, block_t, free_link);
    460462
     
    471473                                 */
    472474                                list_remove(&b->free_link);
    473                                 list_append(&b->free_link, &cache->free_head);
     475                                list_append(&b->free_link, &cache->free_list);
    474476                                fibril_mutex_unlock(&cache->lock);
    475477                                fibril_mutex_lock(&devcon->comm_area_lock);
     
    663665                        goto retry;
    664666                }
    665                 list_append(&block->free_link, &cache->free_head);
     667                list_append(&block->free_link, &cache->free_list);
    666668        }
    667669        fibril_mutex_unlock(&block->lock);
     
    807809        assert(devcon);
    808810       
    809         return get_block_size(devcon->dev_phone, bsize);
     811        return get_block_size(devcon->sess, bsize);
    810812}
    811813
     
    819821int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
    820822{
    821         devcon_t *devcon;
    822 
    823         devcon = devcon_search(devmap_handle);
    824         assert(devcon);
    825        
    826         return get_num_blocks(devcon->dev_phone, nblocks);
     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 */
     838int 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;
    827879}
    828880
     
    838890static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    839891{
    840         int rc;
    841 
    842         assert(devcon);
    843         rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     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),
    844896            UPPER32(ba), cnt);
     897        async_exchange_end(exch);
     898       
    845899        if (rc != EOK) {
    846900                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
     
    851905#endif
    852906        }
     907       
    853908        return rc;
    854909}
     
    865920static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    866921{
    867         int rc;
    868 
    869         assert(devcon);
    870         rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     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),
    871926            UPPER32(ba), cnt);
     927        async_exchange_end(exch);
     928       
    872929        if (rc != EOK) {
    873930                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
     
    877934#endif
    878935        }
     936       
    879937        return rc;
    880938}
    881939
    882940/** Get block size used by the device. */
    883 static int get_block_size(int dev_phone, size_t *bsize)
     941static int get_block_size(async_sess_t *sess, size_t *bsize)
    884942{
    885943        sysarg_t bs;
    886         int rc;
    887 
    888         rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &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       
    889949        if (rc == EOK)
    890950                *bsize = (size_t) bs;
    891 
     951       
    892952        return rc;
    893953}
    894954
    895955/** Get total number of blocks on block device. */
    896 static 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) {
     956static 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)
    903966                *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
    904         }
    905 
     967       
    906968        return rc;
    907969}
Note: See TracChangeset for help on using the changeset viewer.