Changeset efdfebc in mainline for uspace/lib/block/block.c


Ignore:
Timestamp:
2012-11-06T21:03:44Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
338810f
Parents:
de73242 (diff), 94795812 (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 moved

Legend:

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

    rde73242 refdfebc  
    3737 */
    3838
    39 #include "libblock.h"
    4039#include "../../srv/vfs/vfs.h"
    4140#include <ipc/loc.h>
    42 #include <ipc/bd.h>
    4341#include <ipc/services.h>
    4442#include <errno.h>
     
    4745#include <as.h>
    4846#include <assert.h>
     47#include <bd.h>
    4948#include <fibril_synch.h>
    5049#include <adt/list.h>
     
    5655#include <sys/typefmt.h>
    5756#include <stacktrace.h>
     57#include "block.h"
    5858
    5959/** Lock protecting the device connection list */
     
    6262static LIST_INITIALIZE(dcl);
    6363
    64 #define CACHE_BUCKETS_LOG2  10
    65 #define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
    6664
    6765typedef struct {
     
    8078        service_id_t service_id;
    8179        async_sess_t *sess;
    82         fibril_mutex_t comm_area_lock;
    83         void *comm_area;
    84         size_t comm_size;
     80        bd_t *bd;
    8581        void *bb_buf;
    8682        aoff64_t bb_addr;
     
    8985} devcon_t;
    9086
    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 *);
     87static int read_blocks(devcon_t *, aoff64_t, size_t, void *, size_t);
     88static int write_blocks(devcon_t *, aoff64_t, size_t, void *, size_t);
    9589static aoff64_t ba_ltop(devcon_t *, aoff64_t);
    9690
     
    112106
    113107static int devcon_add(service_id_t service_id, async_sess_t *sess,
    114     size_t bsize, void *comm_area, size_t comm_size)
     108    size_t bsize, bd_t *bd)
    115109{
    116110        devcon_t *devcon;
    117        
    118         if (comm_size < bsize)
    119                 return EINVAL;
    120111       
    121112        devcon = malloc(sizeof(devcon_t));
     
    126117        devcon->service_id = service_id;
    127118        devcon->sess = sess;
    128         fibril_mutex_initialize(&devcon->comm_area_lock);
    129         devcon->comm_area = comm_area;
    130         devcon->comm_size = comm_size;
     119        devcon->bd = bd;
    131120        devcon->bb_buf = NULL;
    132121        devcon->bb_addr = 0;
     
    158147    size_t comm_size)
    159148{
    160         void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    161             MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    162         if (!comm_area)
    163                 return ENOMEM;
    164        
     149        bd_t *bd;
     150
    165151        async_sess_t *sess = loc_service_connect(mgmt, service_id,
    166152            IPC_FLAG_BLOCKING);
    167153        if (!sess) {
    168                 munmap(comm_area, comm_size);
    169154                return ENOENT;
    170155        }
    171156       
    172         async_exch_t *exch = async_exchange_begin(sess);
    173         int rc = async_share_out_start(exch, comm_area,
    174             AS_AREA_READ | AS_AREA_WRITE);
    175         async_exchange_end(exch);
    176        
     157        int rc = bd_open(sess, &bd);
    177158        if (rc != EOK) {
    178                 munmap(comm_area, comm_size);
    179159                async_hangup(sess);
    180160                return rc;
     
    182162       
    183163        size_t bsize;
    184         rc = get_block_size(sess, &bsize);
    185        
     164        rc = bd_get_block_size(bd, &bsize);
    186165        if (rc != EOK) {
    187                 munmap(comm_area, comm_size);
     166                bd_close(bd);
    188167                async_hangup(sess);
    189168                return rc;
    190169        }
    191170       
    192         rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);
     171        rc = devcon_add(service_id, sess, bsize, bd);
    193172        if (rc != EOK) {
    194                 munmap(comm_area, comm_size);
     173                bd_close(bd);
    195174                async_hangup(sess);
    196175                return rc;
     
    213192                free(devcon->bb_buf);
    214193       
    215         munmap(devcon->comm_area, devcon->comm_size);
     194        bd_close(devcon->bd);
    216195        async_hangup(devcon->sess);
    217196       
     
    233212                return ENOMEM;
    234213
    235         fibril_mutex_lock(&devcon->comm_area_lock);
    236         rc = read_blocks(devcon, 0, 1);
     214        rc = read_blocks(devcon, 0, 1, bb_buf, devcon->pblock_size);
    237215        if (rc != EOK) {
    238                 fibril_mutex_unlock(&devcon->comm_area_lock);
    239216                free(bb_buf);
    240217                return rc;
    241218        }
    242         memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
    243         fibril_mutex_unlock(&devcon->comm_area_lock);
    244219
    245220        devcon->bb_buf = bb_buf;
     
    256231}
    257232
    258 static hash_index_t cache_hash(unsigned long *key)
    259 {
    260         return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
    261 }
    262 
    263 static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item)
    264 {
    265         block_t *b = hash_table_get_instance(item, block_t, hash_link);
    266         return b->lba == MERGE_LOUP32(key[0], key[1]);
    267 }
    268 
    269 static void cache_remove_callback(link_t *item)
    270 {
    271 }
    272 
    273 static hash_table_operations_t cache_ops = {
     233static size_t cache_key_hash(void *key)
     234{
     235        aoff64_t *lba = (aoff64_t*)key;
     236        return *lba;
     237}
     238
     239static size_t cache_hash(const ht_link_t *item)
     240{
     241        block_t *b = hash_table_get_inst(item, block_t, hash_link);
     242        return b->lba;
     243}
     244
     245static bool cache_key_equal(void *key, const ht_link_t *item)
     246{
     247        aoff64_t *lba = (aoff64_t*)key;
     248        block_t *b = hash_table_get_inst(item, block_t, hash_link);
     249        return b->lba == *lba;
     250}
     251
     252
     253static hash_table_ops_t cache_ops = {
    274254        .hash = cache_hash,
    275         .compare = cache_compare,
    276         .remove_callback = cache_remove_callback
     255        .key_hash = cache_key_hash,
     256        .key_equal = cache_key_equal,
     257        .equal = NULL,
     258        .remove_callback = NULL
    277259};
    278260
     
    305287        cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
    306288
    307         if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
    308             &cache_ops)) {
     289        if (!hash_table_create(&cache->block_hash, 0, 0, &cache_ops)) {
    309290                free(cache);
    310291                return ENOMEM;
     
    338319                list_remove(&b->free_link);
    339320                if (b->dirty) {
    340                         memcpy(devcon->comm_area, b->data, b->size);
    341                         rc = write_blocks(devcon, b->pba, cache->blocks_cluster);
     321                        rc = write_blocks(devcon, b->pba, cache->blocks_cluster,
     322                            b->data, b->size);
    342323                        if (rc != EOK)
    343324                                return rc;
    344325                }
    345326
    346                 unsigned long key[2] = {
    347                         LOWER32(b->lba),
    348                         UPPER32(b->lba)
    349                 };
    350                 hash_table_remove(&cache->block_hash, key, 2);
     327                hash_table_remove_item(&cache->block_hash, &b->hash_link);
    351328               
    352329                free(b->data);
     
    380357        fibril_rwlock_initialize(&b->contents_lock);
    381358        link_initialize(&b->free_link);
    382         link_initialize(&b->hash_link);
    383359}
    384360
     
    400376        cache_t *cache;
    401377        block_t *b;
    402         link_t *l;
    403         unsigned long key[2] = {
    404                 LOWER32(ba),
    405                 UPPER32(ba)
    406         };
     378        link_t *link;
    407379
    408380        int rc;
     
    420392
    421393        fibril_mutex_lock(&cache->lock);
    422         l = hash_table_find(&cache->block_hash, key);
    423         if (l) {
     394        ht_link_t *hlink = hash_table_find(&cache->block_hash, &ba);
     395        if (hlink) {
    424396found:
    425397                /*
    426398                 * We found the block in the cache.
    427399                 */
    428                 b = hash_table_get_instance(l, block_t, hash_link);
     400                b = hash_table_get_inst(hlink, block_t, hash_link);
    429401                fibril_mutex_lock(&b->lock);
    430402                if (b->refcnt++ == 0)
     
    464436                                goto out;
    465437                        }
    466                         l = list_first(&cache->free_list);
    467                         b = list_get_instance(l, block_t, free_link);
     438                        link = list_first(&cache->free_list);
     439                        b = list_get_instance(link, block_t, free_link);
    468440
    469441                        fibril_mutex_lock(&b->lock);
     
    481453                                list_append(&b->free_link, &cache->free_list);
    482454                                fibril_mutex_unlock(&cache->lock);
    483                                 fibril_mutex_lock(&devcon->comm_area_lock);
    484                                 memcpy(devcon->comm_area, b->data, b->size);
    485455                                rc = write_blocks(devcon, b->pba,
    486                                     cache->blocks_cluster);
    487                                 fibril_mutex_unlock(&devcon->comm_area_lock);
     456                                    cache->blocks_cluster, b->data, b->size);
    488457                                if (rc != EOK) {
    489458                                        /*
     
    505474                                        goto retry;
    506475                                }
    507                                 l = hash_table_find(&cache->block_hash, key);
    508                                 if (l) {
     476                                hlink = hash_table_find(&cache->block_hash, &ba);
     477                                if (hlink) {
    509478                                        /*
    510479                                         * Someone else must have already
     
    528497                         */
    529498                        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);
     499                        hash_table_remove_item(&cache->block_hash, &b->hash_link);
    535500                }
    536501
     
    540505                b->lba = ba;
    541506                b->pba = ba_ltop(devcon, b->lba);
    542                 hash_table_insert(&cache->block_hash, key, &b->hash_link);
     507                hash_table_insert(&cache->block_hash, &b->hash_link);
    543508
    544509                /*
     
    555520                         * the new contents from the device.
    556521                         */
    557                         fibril_mutex_lock(&devcon->comm_area_lock);
    558                         rc = read_blocks(devcon, b->pba, cache->blocks_cluster);
    559                         memcpy(b->data, devcon->comm_area, cache->lblock_size);
    560                         fibril_mutex_unlock(&devcon->comm_area_lock);
     522                        rc = read_blocks(devcon, b->pba, cache->blocks_cluster,
     523                            b->data, cache->lblock_size);
    561524                        if (rc != EOK)
    562525                                b->toxic = true;
     
    616579        if (block->dirty && (block->refcnt == 1) &&
    617580            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
    618                 fibril_mutex_lock(&devcon->comm_area_lock);
    619                 memcpy(devcon->comm_area, block->data, block->size);
    620                 rc = write_blocks(devcon, block->pba, cache->blocks_cluster);
    621                 fibril_mutex_unlock(&devcon->comm_area_lock);
     581                rc = write_blocks(devcon, block->pba, cache->blocks_cluster,
     582                    block->data, block->size);
    622583                block->dirty = false;
    623584        }
     
    652613                         * Take the block out of the cache and free it.
    653614                         */
    654                         unsigned long key[2] = {
    655                                 LOWER32(block->lba),
    656                                 UPPER32(block->lba)
    657                         };
    658                         hash_table_remove(&cache->block_hash, key, 2);
     615                        hash_table_remove_item(&cache->block_hash, &block->hash_link);
    659616                        fibril_mutex_unlock(&block->lock);
    660617                        free(block->data);
     
    688645 *
    689646 * @param service_id    Service ID of the block device.
     647 * @param buf           Buffer for holding one block
    690648 * @param bufpos        Pointer to the first unread valid offset within the
    691649 *                      communication buffer.
     
    699657 * @return              EOK on success or a negative return code on failure.
    700658 */
    701 int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,
    702     aoff64_t *pos, void *dst, size_t size)
     659int block_seqread(service_id_t service_id, void *buf, size_t *bufpos,
     660    size_t *buflen, aoff64_t *pos, void *dst, size_t size)
    703661{
    704662        size_t offset = 0;
     
    711669        block_size = devcon->pblock_size;
    712670       
    713         fibril_mutex_lock(&devcon->comm_area_lock);
    714671        while (left > 0) {
    715672                size_t rd;
     
    725682                         * destination buffer.
    726683                         */
    727                         memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
     684                        memcpy(dst + offset, buf + *bufpos, rd);
    728685                        offset += rd;
    729686                        *bufpos += rd;
     
    736693                        int rc;
    737694
    738                         rc = read_blocks(devcon, *pos / block_size, 1);
     695                        rc = read_blocks(devcon, *pos / block_size, 1, buf,
     696                            devcon->pblock_size);
    739697                        if (rc != EOK) {
    740                                 fibril_mutex_unlock(&devcon->comm_area_lock);
    741698                                return rc;
    742699                        }
     
    746703                }
    747704        }
    748         fibril_mutex_unlock(&devcon->comm_area_lock);
    749705       
    750706        return EOK;
     
    763719{
    764720        devcon_t *devcon;
    765         int rc;
    766721
    767722        devcon = devcon_search(service_id);
    768723        assert(devcon);
    769        
    770         fibril_mutex_lock(&devcon->comm_area_lock);
    771 
    772         rc = read_blocks(devcon, ba, cnt);
    773         if (rc == EOK)
    774                 memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
    775 
    776         fibril_mutex_unlock(&devcon->comm_area_lock);
    777 
    778         return rc;
     724
     725        return read_blocks(devcon, ba, cnt, buf, devcon->pblock_size * cnt);
    779726}
    780727
     
    792739{
    793740        devcon_t *devcon;
    794         int rc;
    795741
    796742        devcon = devcon_search(service_id);
    797743        assert(devcon);
    798        
    799         fibril_mutex_lock(&devcon->comm_area_lock);
    800 
    801         memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
    802         rc = write_blocks(devcon, ba, cnt);
    803 
    804         fibril_mutex_unlock(&devcon->comm_area_lock);
    805 
    806         return rc;
     744
     745        return write_blocks(devcon, ba, cnt, (void *)data, devcon->pblock_size * cnt);
    807746}
    808747
     
    820759        devcon = devcon_search(service_id);
    821760        assert(devcon);
    822        
    823         return get_block_size(devcon->sess, bsize);
     761
     762        return bd_get_block_size(devcon->bd, bsize);
    824763}
    825764
     
    836775        assert(devcon);
    837776       
    838         return get_num_blocks(devcon->sess, nblocks);
     777        return bd_get_num_blocks(devcon->bd, nblocks);
    839778}
    840779
     
    903842{
    904843        devcon_t *devcon = devcon_search(service_id);
    905         assert(devcon);
    906        
    907844        toc_block_t *toc = NULL;
    908        
    909         fibril_mutex_lock(&devcon->comm_area_lock);
    910        
    911         async_exch_t *exch = async_exchange_begin(devcon->sess);
    912         int rc = async_req_1_0(exch, BD_READ_TOC, session);
    913         async_exchange_end(exch);
    914        
    915         if (rc == EOK) {
    916                 toc = (toc_block_t *) malloc(sizeof(toc_block_t));
    917                 if (toc != NULL) {
    918                         memset(toc, 0, sizeof(toc_block_t));
    919                         memcpy(toc, devcon->comm_area,
    920                             min(devcon->pblock_size, sizeof(toc_block_t)));
    921                 }
    922         }
    923        
    924        
    925         fibril_mutex_unlock(&devcon->comm_area_lock);
     845        int rc;
     846       
     847        assert(devcon);
     848       
     849        toc = (toc_block_t *) malloc(sizeof(toc_block_t));
     850        if (toc == NULL)
     851                return NULL;
     852       
     853        rc = bd_read_toc(devcon->bd, session, toc, sizeof(toc_block_t));
     854        if (rc != EOK) {
     855                free(toc);
     856                return NULL;
     857        }
    926858       
    927859        return toc;
     
    937869 * @return              EOK on success or negative error code on failure.
    938870 */
    939 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    940 {
    941         assert(devcon);
    942        
    943         async_exch_t *exch = async_exchange_begin(devcon->sess);
    944         int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba),
    945             UPPER32(ba), cnt);
    946         async_exchange_end(exch);
    947        
     871static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *buf,
     872    size_t size)
     873{
     874        assert(devcon);
     875       
     876        int rc = bd_read_blocks(devcon->bd, ba, cnt, buf, size);
    948877        if (rc != EOK) {
    949878                printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
     
    967896 * @return              EOK on success or negative error code on failure.
    968897 */
    969 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
    970 {
    971         assert(devcon);
    972        
    973         async_exch_t *exch = async_exchange_begin(devcon->sess);
    974         int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba),
    975             UPPER32(ba), cnt);
    976         async_exchange_end(exch);
    977        
     898static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *data,
     899    size_t size)
     900{
     901        assert(devcon);
     902       
     903        int rc = bd_write_blocks(devcon->bd, ba, cnt, data, size);
    978904        if (rc != EOK) {
    979905                printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
     
    987913}
    988914
    989 /** Get block size used by the device. */
    990 static int get_block_size(async_sess_t *sess, size_t *bsize)
    991 {
    992         sysarg_t bs;
    993        
    994         async_exch_t *exch = async_exchange_begin(sess);
    995         int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);
    996         async_exchange_end(exch);
    997        
    998         if (rc == EOK)
    999                 *bsize = (size_t) bs;
    1000        
    1001         return rc;
    1002 }
    1003 
    1004 /** Get total number of blocks on block device. */
    1005 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)
    1006 {
    1007         sysarg_t nb_l;
    1008         sysarg_t nb_h;
    1009        
    1010         async_exch_t *exch = async_exchange_begin(sess);
    1011         int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
    1012         async_exchange_end(exch);
    1013        
    1014         if (rc == EOK)
    1015                 *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
    1016        
    1017         return rc;
    1018 }
    1019 
    1020915/** Convert logical block address to physical block address. */
    1021916static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
Note: See TracChangeset for help on using the changeset viewer.