Ignore:
File:
1 edited

Legend:

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

    r0da4e41 rd68e4d5  
    5050#include <adt/list.h>
    5151#include <adt/hash_table.h>
    52 #include <macros.h>
    5352#include <mem.h>
    5453
     
    6362typedef struct {
    6463        fibril_mutex_t lock;
    65         size_t lblock_size;             /**< Logical block size. */
     64        size_t block_size;              /**< Block size. */
    6665        unsigned block_count;           /**< Total number of blocks. */
    6766        unsigned blocks_cached;         /**< Number of cached blocks. */
     
    7574        dev_handle_t dev_handle;
    7675        int dev_phone;
    77         fibril_mutex_t comm_area_lock;
    78         void *comm_area;
    79         size_t comm_size;
     76        fibril_mutex_t com_area_lock;
     77        void *com_area;
     78        size_t com_size;
    8079        void *bb_buf;
    81         bn_t bb_addr;
    82         size_t pblock_size;             /**< Physical block size. */
     80        off_t bb_off;
     81        size_t bb_size;
    8382        cache_t *cache;
    8483} devcon_t;
    8584
    86 static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
    87 static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
    88 static int get_block_size(int dev_phone, size_t *bsize);
     85static int read_block(devcon_t *devcon, bn_t boff, size_t block_size);
     86static int write_block(devcon_t *devcon, bn_t boff, size_t block_size);
    8987
    9088static devcon_t *devcon_search(dev_handle_t dev_handle)
     
    104102}
    105103
    106 static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize,
    107     void *comm_area, size_t comm_size)
     104static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
     105   size_t com_size)
    108106{
    109107        link_t *cur;
    110108        devcon_t *devcon;
    111 
    112         if (comm_size < bsize)
    113                 return EINVAL;
    114109
    115110        devcon = malloc(sizeof(devcon_t));
     
    120115        devcon->dev_handle = dev_handle;
    121116        devcon->dev_phone = dev_phone;
    122         fibril_mutex_initialize(&devcon->comm_area_lock);
    123         devcon->comm_area = comm_area;
    124         devcon->comm_size = comm_size;
     117        fibril_mutex_initialize(&devcon->com_area_lock);
     118        devcon->com_area = com_area;
     119        devcon->com_size = com_size;
    125120        devcon->bb_buf = NULL;
    126         devcon->bb_addr = 0;
    127         devcon->pblock_size = bsize;
     121        devcon->bb_off = 0;
     122        devcon->bb_size = 0;
    128123        devcon->cache = NULL;
    129124
     
    149144}
    150145
    151 int block_init(dev_handle_t dev_handle, size_t comm_size)
     146int block_init(dev_handle_t dev_handle, size_t com_size)
    152147{
    153148        int rc;
    154149        int dev_phone;
    155         void *comm_area;
    156         size_t bsize;
    157 
    158         comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
     150        void *com_area;
     151       
     152        com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
    159153            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    160         if (!comm_area) {
     154        if (!com_area) {
    161155                return ENOMEM;
    162156        }
     
    164158        dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
    165159        if (dev_phone < 0) {
    166                 munmap(comm_area, comm_size);
     160                munmap(com_area, com_size);
    167161                return dev_phone;
    168162        }
    169163
    170         rc = async_share_out_start(dev_phone, comm_area,
     164        rc = ipc_share_out_start(dev_phone, com_area,
    171165            AS_AREA_READ | AS_AREA_WRITE);
    172166        if (rc != EOK) {
    173                 munmap(comm_area, comm_size);
     167                munmap(com_area, com_size);
    174168                ipc_hangup(dev_phone);
    175169                return rc;
    176170        }
    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);
     171       
     172        rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
    185173        if (rc != EOK) {
    186                 munmap(comm_area, comm_size);
     174                munmap(com_area, com_size);
    187175                ipc_hangup(dev_phone);
    188176                return rc;
     
    207195        }
    208196
    209         munmap(devcon->comm_area, devcon->comm_size);
     197        munmap(devcon->com_area, devcon->com_size);
    210198        ipc_hangup(devcon->dev_phone);
    211199
     
    213201}
    214202
    215 int block_bb_read(dev_handle_t dev_handle, bn_t ba)
     203int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
    216204{
    217205        void *bb_buf;
     
    223211        if (devcon->bb_buf)
    224212                return EEXIST;
    225         bb_buf = malloc(devcon->pblock_size);
     213        bb_buf = malloc(size);
    226214        if (!bb_buf)
    227215                return ENOMEM;
    228 
    229         fibril_mutex_lock(&devcon->comm_area_lock);
    230         rc = read_blocks(devcon, 0, 1);
     216       
     217        fibril_mutex_lock(&devcon->com_area_lock);
     218        rc = read_block(devcon, 0, size);
    231219        if (rc != EOK) {
    232                 fibril_mutex_unlock(&devcon->comm_area_lock);
     220                fibril_mutex_unlock(&devcon->com_area_lock);
    233221                free(bb_buf);
    234222                return rc;
    235223        }
    236         memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
    237         fibril_mutex_unlock(&devcon->comm_area_lock);
     224        memcpy(bb_buf, devcon->com_area, size);
     225        fibril_mutex_unlock(&devcon->com_area_lock);
    238226
    239227        devcon->bb_buf = bb_buf;
    240         devcon->bb_addr = ba;
     228        devcon->bb_off = off;
     229        devcon->bb_size = size;
    241230
    242231        return EOK;
     
    286275        fibril_mutex_initialize(&cache->lock);
    287276        list_initialize(&cache->free_head);
    288         cache->lblock_size = size;
     277        cache->block_size = size;
    289278        cache->block_count = blocks;
    290279        cache->blocks_cached = 0;
    291280        cache->mode = mode;
    292 
    293         /* No block size translation a.t.m. */
    294         assert(cache->lblock_size == devcon->pblock_size);
    295281
    296282        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     
    320306        b->refcnt = 1;
    321307        b->dirty = false;
    322         b->toxic = false;
    323308        fibril_rwlock_initialize(&b->contents_lock);
    324309        link_initialize(&b->free_link);
     
    328313/** Instantiate a block in memory and get a reference to it.
    329314 *
    330  * @param block                 Pointer to where the function will store the
    331  *                              block pointer on success.
    332315 * @param dev_handle            Device handle of the block device.
    333316 * @param boff                  Block offset.
     
    336319 *                              device.
    337320 *
    338  * @return                      EOK on success or a negative error code.
    339  */
    340 int block_get(block_t **block, dev_handle_t dev_handle, bn_t boff, int flags)
     321 * @return                      Block structure.
     322 */
     323block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags)
    341324{
    342325        devcon_t *devcon;
     
    345328        link_t *l;
    346329        unsigned long key = boff;
    347         int rc;
     330        bn_t oboff;
    348331       
    349332        devcon = devcon_search(dev_handle);
     
    353336       
    354337        cache = devcon->cache;
    355 
    356 retry:
    357         rc = EOK;
    358         b = NULL;
    359 
    360338        fibril_mutex_lock(&cache->lock);
    361339        l = hash_table_find(&cache->block_hash, &key);
     
    368346                if (b->refcnt++ == 0)
    369347                        list_remove(&b->free_link);
    370                 if (b->toxic)
    371                         rc = EIO;
    372348                fibril_mutex_unlock(&b->lock);
    373349                fibril_mutex_unlock(&cache->lock);
     
    376352                 * The block was not found in the cache.
    377353                 */
     354                int rc;
     355                bool sync = false;
     356
    378357                if (cache_can_grow(cache)) {
    379358                        /*
     
    385364                        if (!b)
    386365                                goto recycle;
    387                         b->data = malloc(cache->lblock_size);
     366                        b->data = malloc(cache->block_size);
    388367                        if (!b->data) {
    389368                                free(b);
     
    397376                        unsigned long temp_key;
    398377recycle:
    399                         if (list_empty(&cache->free_head)) {
    400                                 fibril_mutex_unlock(&cache->lock);
    401                                 rc = ENOMEM;
    402                                 goto out;
    403                         }
     378                        assert(!list_empty(&cache->free_head));
    404379                        l = cache->free_head.next;
     380                        list_remove(l);
    405381                        b = list_get_instance(l, block_t, free_link);
    406 
    407                         fibril_mutex_lock(&b->lock);
    408                         if (b->dirty) {
    409                                 /*
    410                                  * The block needs to be written back to the
    411                                  * device before it changes identity. Do this
    412                                  * while not holding the cache lock so that
    413                                  * concurrency is not impeded. Also move the
    414                                  * block to the end of the free list so that we
    415                                  * do not slow down other instances of
    416                                  * block_get() draining the free list.
    417                                  */
    418                                 list_remove(&b->free_link);
    419                                 list_append(&b->free_link, &cache->free_head);
    420                                 fibril_mutex_unlock(&cache->lock);
    421                                 fibril_mutex_lock(&devcon->comm_area_lock);
    422                                 memcpy(devcon->comm_area, b->data, b->size);
    423                                 rc = write_blocks(devcon, b->boff, 1);
    424                                 fibril_mutex_unlock(&devcon->comm_area_lock);
    425                                 if (rc != EOK) {
    426                                         /*
    427                                          * We did not manage to write the block
    428                                          * to the device. Keep it around for
    429                                          * another try. Hopefully, we will grab
    430                                          * another block next time.
    431                                          */
    432                                         fibril_mutex_unlock(&b->lock);
    433                                         goto retry;
    434                                 }
    435                                 b->dirty = false;
    436                                 if (!fibril_mutex_trylock(&cache->lock)) {
    437                                         /*
    438                                          * Somebody is probably racing with us.
    439                                          * Unlock the block and retry.
    440                                          */
    441                                         fibril_mutex_unlock(&b->lock);
    442                                         goto retry;
    443                                 }
    444 
    445                         }
    446                         fibril_mutex_unlock(&b->lock);
    447 
    448                         /*
    449                          * Unlink the block from the free list and the hash
    450                          * table.
    451                          */
    452                         list_remove(&b->free_link);
     382                        sync = b->dirty;
     383                        oboff = b->boff;
    453384                        temp_key = b->boff;
    454385                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     
    457388                block_initialize(b);
    458389                b->dev_handle = dev_handle;
    459                 b->size = cache->lblock_size;
     390                b->size = cache->block_size;
    460391                b->boff = boff;
    461392                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     
    463394                /*
    464395                 * Lock the block before releasing the cache lock. Thus we don't
    465                  * kill concurrent operations on the cache while doing I/O on
    466                  * the block.
     396                 * kill concurent operations on the cache while doing I/O on the
     397                 * block.
    467398                 */
    468399                fibril_mutex_lock(&b->lock);
    469400                fibril_mutex_unlock(&cache->lock);
    470401
     402                if (sync) {
     403                        /*
     404                         * The block is dirty and needs to be written back to
     405                         * the device before we can read in the new contents.
     406                         */
     407                        fibril_mutex_lock(&devcon->com_area_lock);
     408                        memcpy(devcon->com_area, b->data, b->size);
     409                        rc = write_block(devcon, oboff, cache->block_size);
     410                        assert(rc == EOK);
     411                        fibril_mutex_unlock(&devcon->com_area_lock);
     412                }
    471413                if (!(flags & BLOCK_FLAGS_NOREAD)) {
    472414                        /*
     
    474416                         * the new contents from the device.
    475417                         */
    476                         fibril_mutex_lock(&devcon->comm_area_lock);
    477                         rc = read_blocks(devcon, b->boff, 1);
    478                         memcpy(b->data, devcon->comm_area, cache->lblock_size);
    479                         fibril_mutex_unlock(&devcon->comm_area_lock);
    480                         if (rc != EOK)
    481                                 b->toxic = true;
    482                 } else
    483                         rc = EOK;
     418                        fibril_mutex_lock(&devcon->com_area_lock);
     419                        rc = read_block(devcon, b->boff, cache->block_size);
     420                        assert(rc == EOK);
     421                        memcpy(b->data, devcon->com_area, cache->block_size);
     422                        fibril_mutex_unlock(&devcon->com_area_lock);
     423                }
    484424
    485425                fibril_mutex_unlock(&b->lock);
    486426        }
    487 out:
    488         if ((rc != EOK) && b) {
    489                 assert(b->toxic);
    490                 (void) block_put(b);
    491                 b = NULL;
    492         }
    493         *block = b;
    494         return rc;
     427        return b;
    495428}
    496429
     
    500433 *
    501434 * @param block         Block of which a reference is to be released.
    502  *
    503  * @return              EOK on success or a negative error code.
    504  */
    505 int block_put(block_t *block)
     435 */
     436void block_put(block_t *block)
    506437{
    507438        devcon_t *devcon = devcon_search(block->dev_handle);
    508439        cache_t *cache;
    509         unsigned blocks_cached;
    510         enum cache_mode mode;
    511         int rc = EOK;
     440        int rc;
    512441
    513442        assert(devcon);
     
    515444
    516445        cache = devcon->cache;
    517 
    518 retry:
    519         fibril_mutex_lock(&cache->lock);
    520         blocks_cached = cache->blocks_cached;
    521         mode = cache->mode;
    522         fibril_mutex_unlock(&cache->lock);
    523 
    524         /*
    525          * Determine whether to sync the block. Syncing the block is best done
    526          * when not holding the cache lock as it does not impede concurrency.
    527          * Since the situation may have changed when we unlocked the cache, the
    528          * blocks_cached and mode variables are mere hints. We will recheck the
    529          * conditions later when the cache lock is held again.
    530          */
    531         fibril_mutex_lock(&block->lock);
    532         if (block->toxic)
    533                 block->dirty = false;   /* will not write back toxic block */
    534         if (block->dirty && (block->refcnt == 1) &&
    535             (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
    536                 fibril_mutex_lock(&devcon->comm_area_lock);
    537                 memcpy(devcon->comm_area, block->data, block->size);
    538                 rc = write_blocks(devcon, block->boff, 1);
    539                 fibril_mutex_unlock(&devcon->comm_area_lock);
    540                 block->dirty = false;
    541         }
    542         fibril_mutex_unlock(&block->lock);
    543 
    544446        fibril_mutex_lock(&cache->lock);
    545447        fibril_mutex_lock(&block->lock);
     
    547449                /*
    548450                 * Last reference to the block was dropped. Either free the
    549                  * block or put it on the free list. In case of an I/O error,
    550                  * free the block.
     451                 * block or put it on the free list.
    551452                 */
    552                 if ((cache->blocks_cached > CACHE_HI_WATERMARK) ||
    553                     (rc != EOK)) {
     453                if (cache->blocks_cached > CACHE_HI_WATERMARK) {
    554454                        /*
    555                          * Currently there are too many cached blocks or there
    556                          * was an I/O error when writing the block back to the
    557                          * device.
     455                         * Currently there are too many cached blocks.
    558456                         */
    559457                        if (block->dirty) {
    560                                 /*
    561                                  * We cannot sync the block while holding the
    562                                  * cache lock. Release everything and retry.
    563                                  */
    564                                 block->refcnt++;
    565                                 fibril_mutex_unlock(&block->lock);
    566                                 fibril_mutex_unlock(&cache->lock);
    567                                 goto retry;
     458                                fibril_mutex_lock(&devcon->com_area_lock);
     459                                memcpy(devcon->com_area, block->data,
     460                                    block->size);
     461                                rc = write_block(devcon, block->boff,
     462                                    block->size);
     463                                assert(rc == EOK);
     464                                fibril_mutex_unlock(&devcon->com_area_lock);
    568465                        }
    569466                        /*
     
    576473                        cache->blocks_cached--;
    577474                        fibril_mutex_unlock(&cache->lock);
    578                         return rc;
     475                        return;
    579476                }
    580477                /*
    581478                 * Put the block on the free list.
    582479                 */
     480                list_append(&block->free_link, &cache->free_head);
    583481                if (cache->mode != CACHE_MODE_WB && block->dirty) {
    584                         /*
    585                          * We cannot sync the block while holding the cache
    586                          * lock. Release everything and retry.
    587                          */
    588                         block->refcnt++;
    589                         fibril_mutex_unlock(&block->lock);
    590                         fibril_mutex_unlock(&cache->lock);
    591                         goto retry;
    592                 }
    593                 list_append(&block->free_link, &cache->free_head);
     482                        fibril_mutex_lock(&devcon->com_area_lock);
     483                        memcpy(devcon->com_area, block->data, block->size);
     484                        rc = write_block(devcon, block->boff, block->size);
     485                        assert(rc == EOK);
     486                        fibril_mutex_unlock(&devcon->com_area_lock);
     487
     488                        block->dirty = false;
     489                }
    594490        }
    595491        fibril_mutex_unlock(&block->lock);
    596492        fibril_mutex_unlock(&cache->lock);
    597 
    598         return rc;
    599493}
    600494
     
    614508 */
    615509int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
    616     off_t *pos, void *dst, size_t size)
     510    off_t *pos, void *dst, size_t size, size_t block_size)
    617511{
    618512        off_t offset = 0;
    619513        size_t left = size;
    620         size_t block_size;
    621         devcon_t *devcon;
    622 
    623         devcon = devcon_search(dev_handle);
     514        devcon_t *devcon = devcon_search(dev_handle);
    624515        assert(devcon);
    625         block_size = devcon->pblock_size;
    626        
    627         fibril_mutex_lock(&devcon->comm_area_lock);
     516       
     517        fibril_mutex_lock(&devcon->com_area_lock);
    628518        while (left > 0) {
    629519                size_t rd;
     
    639529                         * destination buffer.
    640530                         */
    641                         memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
     531                        memcpy(dst + offset, devcon->com_area + *bufpos, rd);
    642532                        offset += rd;
    643533                        *bufpos += rd;
     
    650540                        int rc;
    651541
    652                         rc = read_blocks(devcon, *pos / block_size, 1);
     542                        rc = read_block(devcon, *pos / block_size, block_size);
    653543                        if (rc != EOK) {
    654                                 fibril_mutex_unlock(&devcon->comm_area_lock);
     544                                fibril_mutex_unlock(&devcon->com_area_lock);
    655545                                return rc;
    656546                        }
     
    660550                }
    661551        }
    662         fibril_mutex_unlock(&devcon->comm_area_lock);
     552        fibril_mutex_unlock(&devcon->com_area_lock);
    663553       
    664554        return EOK;
    665555}
    666556
    667 /** Read blocks directly from device (bypass cache).
    668  *
    669  * @param dev_handle    Device handle of the block device.
    670  * @param ba            Address of first block.
    671  * @param cnt           Number of blocks.
     557/** Read block from block device.
     558 *
     559 * @param devcon        Device connection.
     560 * @param boff          Block index.
     561 * @param block_size    Block size.
    672562 * @param src           Buffer for storing the data.
    673563 *
    674564 * @return              EOK on success or negative error code on failure.
    675565 */
    676 int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
    677 {
    678         devcon_t *devcon;
     566static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
     567{
     568        ipcarg_t retval;
    679569        int rc;
    680570
    681         devcon = devcon_search(dev_handle);
    682571        assert(devcon);
    683        
    684         fibril_mutex_lock(&devcon->comm_area_lock);
    685 
    686         rc = read_blocks(devcon, ba, cnt);
    687         if (rc == EOK)
    688                 memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
    689 
    690         fibril_mutex_unlock(&devcon->comm_area_lock);
    691 
    692         return rc;
    693 }
    694 
    695 /** Write blocks directly to device (bypass cache).
    696  *
    697  * @param dev_handle    Device handle of the block device.
    698  * @param ba            Address of first block.
    699  * @param cnt           Number of blocks.
    700  * @param src           The data to be written.
     572        rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size,
     573            &retval);
     574        if ((rc != EOK) || (retval != EOK))
     575                return (rc != EOK ? rc : (int) retval);
     576
     577        return EOK;
     578}
     579
     580/** Write block to block device.
     581 *
     582 * @param devcon        Device connection.
     583 * @param boff          Block index.
     584 * @param block_size    Block size.
     585 * @param src           Buffer containing the data to write.
    701586 *
    702587 * @return              EOK on success or negative error code on failure.
    703588 */
    704 int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
    705     const void *data)
    706 {
    707         devcon_t *devcon;
     589static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
     590{
     591        ipcarg_t retval;
    708592        int rc;
    709593
    710         devcon = devcon_search(dev_handle);
    711594        assert(devcon);
    712        
    713         fibril_mutex_lock(&devcon->comm_area_lock);
    714 
    715         memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
    716         rc = read_blocks(devcon, ba, cnt);
    717 
    718         fibril_mutex_unlock(&devcon->comm_area_lock);
    719 
    720         return rc;
    721 }
    722 
    723 /** Get device block size.
    724  *
    725  * @param dev_handle    Device handle of the block device.
    726  * @param bsize         Output block size.
    727  *
    728  * @return              EOK on success or negative error code on failure.
    729  */
    730 int block_get_bsize(dev_handle_t dev_handle, size_t *bsize)
    731 {
    732         devcon_t *devcon;
    733 
    734         devcon = devcon_search(dev_handle);
    735         assert(devcon);
    736        
    737         return get_block_size(devcon->dev_phone, bsize);
    738 }
    739 
    740 /** Read blocks from block device.
    741  *
    742  * @param devcon        Device connection.
    743  * @param ba            Address of first block.
    744  * @param cnt           Number of blocks.
    745  * @param src           Buffer for storing the data.
    746  *
    747  * @return              EOK on success or negative error code on failure.
    748  */
    749 static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
    750 {
    751         int rc;
    752 
    753         assert(devcon);
    754         rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
    755             UPPER32(ba), cnt);
    756         return rc;
    757 }
    758 
    759 /** Write block to block device.
    760  *
    761  * @param devcon        Device connection.
    762  * @param ba            Address of first block.
    763  * @param cnt           Number of blocks.
    764  * @param src           Buffer containing the data to write.
    765  *
    766  * @return              EOK on success or negative error code on failure.
    767  */
    768 static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
    769 {
    770         int rc;
    771 
    772         assert(devcon);
    773         rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
    774             UPPER32(ba), cnt);
    775         return rc;
    776 }
    777 
    778 /** Get block size used by the device. */
    779 static int get_block_size(int dev_phone, size_t *bsize)
    780 {
    781         ipcarg_t bs;
    782         int rc;
    783 
    784         rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
    785         if (rc == EOK)
    786                 *bsize = (size_t) bs;
    787 
    788         return rc;
     595        rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size,
     596            &retval);
     597        if ((rc != EOK) || (retval != EOK))
     598                return (rc != EOK ? rc : (int) retval);
     599
     600        return EOK;
    789601}
    790602
Note: See TracChangeset for help on using the changeset viewer.