Ignore:
File:
1 edited

Legend:

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

    rc7bbf029 r867e2555  
    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
     
    256258static hash_index_t cache_hash(unsigned long *key)
    257259{
    258         return *key & (CACHE_BUCKETS - 1);
     260        return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
    259261}
    260262
     
    262264{
    263265        block_t *b = hash_table_get_instance(item, block_t, hash_link);
    264         return b->lba == *key;
     266        return b->lba == MERGE_LOUP32(key[0], key[1]);
    265267}
    266268
     
    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;
     
    303305        cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
    304306
    305         if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     307        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
    306308            &cache_ops)) {
    307309                free(cache);
     
    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
     
    342344                }
    343345
    344                 unsigned long key = b->lba;
    345                 hash_table_remove(&cache->block_hash, &key, 1);
     346                unsigned long key[2] = {
     347                        LOWER32(b->lba),
     348                        UPPER32(b->lba)
     349                };
     350                hash_table_remove(&cache->block_hash, key, 2);
    346351               
    347352                free(b->data);
     
    362367        if (cache->blocks_cached < CACHE_LO_WATERMARK)
    363368                return true;
    364         if (!list_empty(&cache->free_head))
     369        if (!list_empty(&cache->free_list))
    365370                return false;
    366371        return true;
     
    396401        block_t *b;
    397402        link_t *l;
    398         unsigned long key = ba;
     403        unsigned long key[2] = {
     404                LOWER32(ba),
     405                UPPER32(ba)
     406        };
     407
    399408        int rc;
    400409       
     
    411420
    412421        fibril_mutex_lock(&cache->lock);
    413         l = hash_table_find(&cache->block_hash, &key);
     422        l = hash_table_find(&cache->block_hash, key);
    414423        if (l) {
    415424found:
     
    449458                         * Try to recycle a block from the free list.
    450459                         */
    451                         unsigned long temp_key;
    452460recycle:
    453                         if (list_empty(&cache->free_head)) {
     461                        if (list_empty(&cache->free_list)) {
    454462                                fibril_mutex_unlock(&cache->lock);
    455463                                rc = ENOMEM;
    456464                                goto out;
    457465                        }
    458                         l = cache->free_head.next;
     466                        l = list_first(&cache->free_list);
    459467                        b = list_get_instance(l, block_t, free_link);
    460468
     
    471479                                 */
    472480                                list_remove(&b->free_link);
    473                                 list_append(&b->free_link, &cache->free_head);
     481                                list_append(&b->free_link, &cache->free_list);
    474482                                fibril_mutex_unlock(&cache->lock);
    475483                                fibril_mutex_lock(&devcon->comm_area_lock);
     
    497505                                        goto retry;
    498506                                }
    499                                 l = hash_table_find(&cache->block_hash, &key);
     507                                l = hash_table_find(&cache->block_hash, key);
    500508                                if (l) {
    501509                                        /*
     
    520528                         */
    521529                        list_remove(&b->free_link);
    522                         temp_key = b->lba;
    523                         hash_table_remove(&cache->block_hash, &temp_key, 1);
     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);
    524535                }
    525536
     
    529540                b->lba = ba;
    530541                b->pba = ba_ltop(devcon, b->lba);
    531                 hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     542                hash_table_insert(&cache->block_hash, key, &b->hash_link);
    532543
    533544                /*
     
    641652                         * Take the block out of the cache and free it.
    642653                         */
    643                         unsigned long key = block->lba;
    644                         hash_table_remove(&cache->block_hash, &key, 1);
     654                        unsigned long key[2] = {
     655                                LOWER32(block->lba),
     656                                UPPER32(block->lba)
     657                        };
     658                        hash_table_remove(&cache->block_hash, key, 2);
    645659                        fibril_mutex_unlock(&block->lock);
    646660                        free(block->data);
     
    663677                        goto retry;
    664678                }
    665                 list_append(&block->free_link, &cache->free_head);
     679                list_append(&block->free_link, &cache->free_list);
    666680        }
    667681        fibril_mutex_unlock(&block->lock);
     
    807821        assert(devcon);
    808822       
    809         return get_block_size(devcon->dev_phone, bsize);
     823        return get_block_size(devcon->sess, bsize);
    810824}
    811825
     
    819833int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
    820834{
    821         devcon_t *devcon;
    822 
    823         devcon = devcon_search(devmap_handle);
    824         assert(devcon);
    825        
    826         return get_num_blocks(devcon->dev_phone, nblocks);
     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 */
     850int 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;
    827891}
    828892
     
    838902static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    839903{
    840         int rc;
    841 
    842         assert(devcon);
    843         rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     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),
    844908            UPPER32(ba), cnt);
     909        async_exchange_end(exch);
     910       
    845911        if (rc != EOK) {
    846912                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
     
    851917#endif
    852918        }
     919       
    853920        return rc;
    854921}
     
    865932static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    866933{
    867         int rc;
    868 
    869         assert(devcon);
    870         rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     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),
    871938            UPPER32(ba), cnt);
     939        async_exchange_end(exch);
     940       
    872941        if (rc != EOK) {
    873942                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
     
    877946#endif
    878947        }
     948       
    879949        return rc;
    880950}
    881951
    882952/** Get block size used by the device. */
    883 static int get_block_size(int dev_phone, size_t *bsize)
     953static int get_block_size(async_sess_t *sess, size_t *bsize)
    884954{
    885955        sysarg_t bs;
    886         int rc;
    887 
    888         rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &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       
    889961        if (rc == EOK)
    890962                *bsize = (size_t) bs;
    891 
     963       
    892964        return rc;
    893965}
    894966
    895967/** 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) {
     968static 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)
    903978                *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
    904         }
    905 
     979       
    906980        return rc;
    907981}
Note: See TracChangeset for help on using the changeset viewer.