Ignore:
File:
1 edited

Legend:

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

    r7a56b1ed r00b1d20e  
    5050#include <adt/list.h>
    5151#include <adt/hash_table.h>
     52#include <macros.h>
    5253#include <mem.h>
    5354
     
    6263typedef struct {
    6364        fibril_mutex_t lock;
    64         size_t block_size;              /**< Block size. */
     65        size_t lblock_size;             /**< Logical block size. */
    6566        unsigned block_count;           /**< Total number of blocks. */
    6667        unsigned blocks_cached;         /**< Number of cached blocks. */
     
    7475        dev_handle_t dev_handle;
    7576        int dev_phone;
    76         fibril_mutex_t com_area_lock;
    77         void *com_area;
    78         size_t com_size;
     77        fibril_mutex_t comm_area_lock;
     78        void *comm_area;
     79        size_t comm_size;
    7980        void *bb_buf;
    80         off_t bb_off;
    81         size_t bb_size;
     81        bn_t bb_addr;
     82        size_t pblock_size;             /**< Physical block size. */
    8283        cache_t *cache;
    8384} devcon_t;
    8485
    85 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size);
    86 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size);
     86static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     87static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     88static int get_block_size(int dev_phone, size_t *bsize);
    8789
    8890static devcon_t *devcon_search(dev_handle_t dev_handle)
     
    102104}
    103105
    104 static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
    105    size_t com_size)
     106static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize,
     107    void *comm_area, size_t comm_size)
    106108{
    107109        link_t *cur;
    108110        devcon_t *devcon;
     111
     112        if (comm_size < bsize)
     113                return EINVAL;
    109114
    110115        devcon = malloc(sizeof(devcon_t));
     
    115120        devcon->dev_handle = dev_handle;
    116121        devcon->dev_phone = dev_phone;
    117         fibril_mutex_initialize(&devcon->com_area_lock);
    118         devcon->com_area = com_area;
    119         devcon->com_size = com_size;
     122        fibril_mutex_initialize(&devcon->comm_area_lock);
     123        devcon->comm_area = comm_area;
     124        devcon->comm_size = comm_size;
    120125        devcon->bb_buf = NULL;
    121         devcon->bb_off = 0;
    122         devcon->bb_size = 0;
     126        devcon->bb_addr = 0;
     127        devcon->pblock_size = bsize;
    123128        devcon->cache = NULL;
    124129
     
    144149}
    145150
    146 int block_init(dev_handle_t dev_handle, size_t com_size)
     151int block_init(dev_handle_t dev_handle, size_t comm_size)
    147152{
    148153        int rc;
    149154        int dev_phone;
    150         void *com_area;
    151        
    152         com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
     155        void *comm_area;
     156        size_t bsize;
     157
     158        comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    153159            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    154         if (!com_area) {
     160        if (!comm_area) {
    155161                return ENOMEM;
    156162        }
     
    158164        dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
    159165        if (dev_phone < 0) {
    160                 munmap(com_area, com_size);
     166                munmap(comm_area, comm_size);
    161167                return dev_phone;
    162168        }
    163169
    164         rc = ipc_share_out_start(dev_phone, com_area,
     170        rc = ipc_share_out_start(dev_phone, comm_area,
    165171            AS_AREA_READ | AS_AREA_WRITE);
    166172        if (rc != EOK) {
    167                 munmap(com_area, com_size);
     173                munmap(comm_area, comm_size);
    168174                ipc_hangup(dev_phone);
    169175                return rc;
    170176        }
    171        
    172         rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
     177
     178        if (get_block_size(dev_phone, &bsize) != EOK) {
     179                munmap(comm_area, comm_size);
     180                ipc_hangup(dev_phone);
     181                return rc;
     182        }
     183       
     184        rc = devcon_add(dev_handle, dev_phone, bsize, comm_area, comm_size);
    173185        if (rc != EOK) {
    174                 munmap(com_area, com_size);
     186                munmap(comm_area, comm_size);
    175187                ipc_hangup(dev_phone);
    176188                return rc;
     
    195207        }
    196208
    197         munmap(devcon->com_area, devcon->com_size);
     209        munmap(devcon->comm_area, devcon->comm_size);
    198210        ipc_hangup(devcon->dev_phone);
    199211
     
    201213}
    202214
    203 int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
     215int block_bb_read(dev_handle_t dev_handle, bn_t ba)
    204216{
    205217        void *bb_buf;
     
    211223        if (devcon->bb_buf)
    212224                return EEXIST;
    213         bb_buf = malloc(size);
     225        bb_buf = malloc(devcon->pblock_size);
    214226        if (!bb_buf)
    215227                return ENOMEM;
    216        
    217         fibril_mutex_lock(&devcon->com_area_lock);
    218         rc = read_block(devcon, 0, size);
     228
     229        fibril_mutex_lock(&devcon->comm_area_lock);
     230        rc = read_blocks(devcon, 0, 1);
    219231        if (rc != EOK) {
    220                 fibril_mutex_unlock(&devcon->com_area_lock);
     232                fibril_mutex_unlock(&devcon->comm_area_lock);
    221233                free(bb_buf);
    222234                return rc;
    223235        }
    224         memcpy(bb_buf, devcon->com_area, size);
    225         fibril_mutex_unlock(&devcon->com_area_lock);
     236        memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
     237        fibril_mutex_unlock(&devcon->comm_area_lock);
    226238
    227239        devcon->bb_buf = bb_buf;
    228         devcon->bb_off = off;
    229         devcon->bb_size = size;
     240        devcon->bb_addr = ba;
    230241
    231242        return EOK;
     
    275286        fibril_mutex_initialize(&cache->lock);
    276287        list_initialize(&cache->free_head);
    277         cache->block_size = size;
     288        cache->lblock_size = size;
    278289        cache->block_count = blocks;
    279290        cache->blocks_cached = 0;
    280291        cache->mode = mode;
     292
     293        /* No block size translation a.t.m. */
     294        assert(cache->lblock_size == devcon->pblock_size);
    281295
    282296        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     
    331345        link_t *l;
    332346        unsigned long key = boff;
    333         int rc;
     347        int rc = EOK;
    334348       
    335349        devcon = devcon_search(dev_handle);
     
    341355
    342356retry:
    343         rc = EOK;
    344         b = NULL;
    345 
    346357        fibril_mutex_lock(&cache->lock);
    347358        l = hash_table_find(&cache->block_hash, &key);
     
    371382                        if (!b)
    372383                                goto recycle;
    373                         b->data = malloc(cache->block_size);
     384                        b->data = malloc(cache->lblock_size);
    374385                        if (!b->data) {
    375386                                free(b);
     
    383394                        unsigned long temp_key;
    384395recycle:
    385                         if (list_empty(&cache->free_head)) {
    386                                 fibril_mutex_unlock(&cache->lock);
    387                                 rc = ENOMEM;
    388                                 goto out;
    389                         }
     396                        assert(!list_empty(&cache->free_head));
    390397                        l = cache->free_head.next;
    391398                        b = list_get_instance(l, block_t, free_link);
     
    405412                                list_append(&b->free_link, &cache->free_head);
    406413                                fibril_mutex_unlock(&cache->lock);
    407                                 fibril_mutex_lock(&devcon->com_area_lock);
    408                                 memcpy(devcon->com_area, b->data, b->size);
    409                                 rc = write_block(devcon, b->boff,
    410                                     cache->block_size);
    411                                 fibril_mutex_unlock(&devcon->com_area_lock);
     414                                fibril_mutex_lock(&devcon->comm_area_lock);
     415                                memcpy(devcon->comm_area, b->data, b->size);
     416                                rc = write_blocks(devcon, b->boff, 1);
     417                                fibril_mutex_unlock(&devcon->comm_area_lock);
    412418                                if (rc != EOK) {
    413419                                        /*
     
    444450                block_initialize(b);
    445451                b->dev_handle = dev_handle;
    446                 b->size = cache->block_size;
     452                b->size = cache->lblock_size;
    447453                b->boff = boff;
    448454                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     
    461467                         * the new contents from the device.
    462468                         */
    463                         fibril_mutex_lock(&devcon->com_area_lock);
    464                         rc = read_block(devcon, b->boff, cache->block_size);
    465                         memcpy(b->data, devcon->com_area, cache->block_size);
    466                         fibril_mutex_unlock(&devcon->com_area_lock);
     469                        fibril_mutex_lock(&devcon->comm_area_lock);
     470                        rc = read_blocks(devcon, b->boff, 1);
     471                        memcpy(b->data, devcon->comm_area, cache->lblock_size);
     472                        fibril_mutex_unlock(&devcon->comm_area_lock);
    467473                        if (rc != EOK)
    468474                                b->toxic = true;
     
    471477
    472478                fibril_mutex_unlock(&b->lock);
    473         }
    474 out:
    475         if ((rc != EOK) && b) {
    476                 assert(b->toxic);
    477                 (void) block_put(b);
    478                 b = NULL;
    479479        }
    480480        *block = b;
     
    521521        if (block->dirty && (block->refcnt == 1) &&
    522522            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
    523                 fibril_mutex_lock(&devcon->com_area_lock);
    524                 memcpy(devcon->com_area, block->data, block->size);
    525                 rc = write_block(devcon, block->boff, block->size);
    526                 fibril_mutex_unlock(&devcon->com_area_lock);
     523                fibril_mutex_lock(&devcon->comm_area_lock);
     524                memcpy(devcon->comm_area, block->data, block->size);
     525                rc = write_blocks(devcon, block->boff, 1);
     526                fibril_mutex_unlock(&devcon->comm_area_lock);
    527527                block->dirty = false;
    528528        }
     
    601601 */
    602602int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
    603     off_t *pos, void *dst, size_t size, size_t block_size)
     603    off_t *pos, void *dst, size_t size)
    604604{
    605605        off_t offset = 0;
    606606        size_t left = size;
    607         devcon_t *devcon = devcon_search(dev_handle);
    608         assert(devcon);
    609        
    610         fibril_mutex_lock(&devcon->com_area_lock);
     607        size_t block_size;
     608        devcon_t *devcon;
     609
     610        devcon = devcon_search(dev_handle);
     611        assert(devcon);
     612        block_size = devcon->pblock_size;
     613       
     614        fibril_mutex_lock(&devcon->comm_area_lock);
    611615        while (left > 0) {
    612616                size_t rd;
     
    622626                         * destination buffer.
    623627                         */
    624                         memcpy(dst + offset, devcon->com_area + *bufpos, rd);
     628                        memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
    625629                        offset += rd;
    626630                        *bufpos += rd;
     
    633637                        int rc;
    634638
    635                         rc = read_block(devcon, *pos / block_size, block_size);
     639                        rc = read_blocks(devcon, *pos / block_size, 1);
    636640                        if (rc != EOK) {
    637                                 fibril_mutex_unlock(&devcon->com_area_lock);
     641                                fibril_mutex_unlock(&devcon->comm_area_lock);
    638642                                return rc;
    639643                        }
     
    643647                }
    644648        }
    645         fibril_mutex_unlock(&devcon->com_area_lock);
     649        fibril_mutex_unlock(&devcon->comm_area_lock);
    646650       
    647651        return EOK;
    648652}
    649653
    650 /** Read block from block device.
     654/** Read blocks directly from device (bypass cache).
     655 *
     656 * @param dev_handle    Device handle of the block device.
     657 * @param ba            Address of first block.
     658 * @param cnt           Number of blocks.
     659 * @param src           Buffer for storing the data.
     660 *
     661 * @return              EOK on success or negative error code on failure.
     662 */
     663int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
     664{
     665        devcon_t *devcon;
     666        int rc;
     667
     668        devcon = devcon_search(dev_handle);
     669        assert(devcon);
     670       
     671        fibril_mutex_lock(&devcon->comm_area_lock);
     672
     673        rc = read_blocks(devcon, ba, cnt);
     674        if (rc == EOK)
     675                memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
     676
     677        fibril_mutex_unlock(&devcon->comm_area_lock);
     678
     679        return rc;
     680}
     681
     682/** Write blocks directly to device (bypass cache).
     683 *
     684 * @param dev_handle    Device handle of the block device.
     685 * @param ba            Address of first block.
     686 * @param cnt           Number of blocks.
     687 * @param src           The data to be written.
     688 *
     689 * @return              EOK on success or negative error code on failure.
     690 */
     691int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
     692    const void *data)
     693{
     694        devcon_t *devcon;
     695        int rc;
     696
     697        devcon = devcon_search(dev_handle);
     698        assert(devcon);
     699       
     700        fibril_mutex_lock(&devcon->comm_area_lock);
     701
     702        memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
     703        rc = read_blocks(devcon, ba, cnt);
     704
     705        fibril_mutex_unlock(&devcon->comm_area_lock);
     706
     707        return rc;
     708}
     709
     710/** Get device block size.
     711 *
     712 * @param dev_handle    Device handle of the block device.
     713 * @param bsize         Output block size.
     714 *
     715 * @return              EOK on success or negative error code on failure.
     716 */
     717int block_get_bsize(dev_handle_t dev_handle, size_t *bsize)
     718{
     719        devcon_t *devcon;
     720
     721        devcon = devcon_search(dev_handle);
     722        assert(devcon);
     723       
     724        return get_block_size(devcon->dev_phone, bsize);
     725}
     726
     727/** Read blocks from block device.
    651728 *
    652729 * @param devcon        Device connection.
    653  * @param boff          Block index.
    654  * @param block_size    Block size.
     730 * @param ba            Address of first block.
     731 * @param cnt           Number of blocks.
    655732 * @param src           Buffer for storing the data.
    656733 *
    657734 * @return              EOK on success or negative error code on failure.
    658735 */
    659 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
    660 {
    661         ipcarg_t retval;
     736static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     737{
    662738        int rc;
    663739
    664740        assert(devcon);
    665         rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size,
    666             &retval);
    667         if ((rc != EOK) || (retval != EOK))
    668                 return (rc != EOK ? rc : (int) retval);
    669 
    670         return EOK;
     741        rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     742            UPPER32(ba), cnt);
     743        return rc;
    671744}
    672745
     
    674747 *
    675748 * @param devcon        Device connection.
    676  * @param boff          Block index.
    677  * @param block_size    Block size.
     749 * @param ba            Address of first block.
     750 * @param cnt           Number of blocks.
    678751 * @param src           Buffer containing the data to write.
    679752 *
    680753 * @return              EOK on success or negative error code on failure.
    681754 */
    682 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
    683 {
    684         ipcarg_t retval;
     755static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     756{
    685757        int rc;
    686758
    687759        assert(devcon);
    688         rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size,
    689             &retval);
    690         if ((rc != EOK) || (retval != EOK))
    691                 return (rc != EOK ? rc : (int) retval);
    692 
    693         return EOK;
     760        rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     761            UPPER32(ba), cnt);
     762        return rc;
     763}
     764
     765/** Get block size used by the device. */
     766static int get_block_size(int dev_phone, size_t *bsize)
     767{
     768        ipcarg_t bs;
     769        int rc;
     770
     771        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
     772        if (rc == EOK)
     773                *bsize = (size_t) bs;
     774
     775        return rc;
    694776}
    695777
Note: See TracChangeset for help on using the changeset viewer.