Changeset d5a720cf in mainline


Ignore:
Timestamp:
2008-11-02T19:28:38Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a6d97fb9
Parents:
6132b59
Message:

Implementation of block_put().

File:
1 edited

Legend:

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

    r6132b59 rd5a720cf  
    275275
    276276        devcon->cache = cache;
    277         return EOK;
    278 }
    279 
    280 /** Read data from a block device.
    281  *
    282  * @param dev_handle    Device handle of the block device.
    283  * @param bufpos        Pointer to the first unread valid offset within the
    284  *                      communication buffer.
    285  * @param buflen        Pointer to the number of unread bytes that are ready in
    286  *                      the communication buffer.
    287  * @param pos           Device position to be read.
    288  * @param dst           Destination buffer.
    289  * @param size          Size of the destination buffer.
    290  * @param block_size    Block size to be used for the transfer.
    291  *
    292  * @return              EOK on success or a negative return code on failure.
    293  */
    294 int
    295 block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
    296     size_t size, size_t block_size)
    297 {
    298         off_t offset = 0;
    299         size_t left = size;
    300         devcon_t *devcon = devcon_search(dev_handle);
    301         assert(devcon);
    302        
    303         while (left > 0) {
    304                 size_t rd;
    305                
    306                 if (*bufpos + left < *buflen)
    307                         rd = left;
    308                 else
    309                         rd = *buflen - *bufpos;
    310                
    311                 if (rd > 0) {
    312                         /*
    313                          * Copy the contents of the communication buffer to the
    314                          * destination buffer.
    315                          */
    316                         memcpy(dst + offset, devcon->com_area + *bufpos, rd);
    317                         offset += rd;
    318                         *bufpos += rd;
    319                         *pos += rd;
    320                         left -= rd;
    321                 }
    322                
    323                 if (*bufpos == *buflen) {
    324                         /* Refill the communication buffer with a new block. */
    325                         ipcarg_t retval;
    326                         int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
    327                             *pos / block_size, block_size, &retval);
    328                         if ((rc != EOK) || (retval != EOK))
    329                                 return (rc != EOK ? rc : retval);
    330                        
    331                         *bufpos = 0;
    332                         *buflen = block_size;
    333                 }
    334         }
    335        
    336277        return EOK;
    337278}
     
    437378}
    438379
     380/** Release a reference to a block.
     381 *
     382 * If the last reference is dropped, the block is put on the free list.  If the
     383 * last reference is dropped and the block is dirty, it is first synced with the
     384 * block device.
     385 *
     386 * @param block         Block of which a reference is to be released.
     387 */
    439388void block_put(block_t *block)
    440389{
    441        
     390        devcon_t *devcon = devcon_search(block->dev_handle);
     391        cache_t *cache;
     392
     393        assert(devcon);
     394        assert(devcon->cache);
     395
     396        cache = devcon->cache;
     397        futex_down(&cache->lock);
     398        futex_down(&block->lock);
     399        if (!--block->refcnt) {
     400                /*
     401                 * Last reference to the block was dropped, put the block on the
     402                 * free list.
     403                 */
     404                list_append(&block->free_link, &cache->free_head);
     405                /* Unlock the cache, but not the block. */
     406                futex_up(&cache->lock);
     407                if (block->dirty) {
     408                        /*
     409                         * The block is dirty and there is no one using it
     410                         * at the moment, write it back to the device.
     411                         */
     412
     413                        /* TODO: block_write() */
     414                        block->dirty = false;
     415                }
     416        } else {
     417                futex_up(&cache->lock);
     418        }
     419        futex_up(&block->lock);
     420}
     421
     422/** Read data from a block device.
     423 *
     424 * @param dev_handle    Device handle of the block device.
     425 * @param bufpos        Pointer to the first unread valid offset within the
     426 *                      communication buffer.
     427 * @param buflen        Pointer to the number of unread bytes that are ready in
     428 *                      the communication buffer.
     429 * @param pos           Device position to be read.
     430 * @param dst           Destination buffer.
     431 * @param size          Size of the destination buffer.
     432 * @param block_size    Block size to be used for the transfer.
     433 *
     434 * @return              EOK on success or a negative return code on failure.
     435 */
     436int
     437block_read(int dev_handle, off_t *bufpos, size_t *buflen, off_t *pos, void *dst,
     438    size_t size, size_t block_size)
     439{
     440        off_t offset = 0;
     441        size_t left = size;
     442        devcon_t *devcon = devcon_search(dev_handle);
     443        assert(devcon);
     444       
     445        while (left > 0) {
     446                size_t rd;
     447               
     448                if (*bufpos + left < *buflen)
     449                        rd = left;
     450                else
     451                        rd = *buflen - *bufpos;
     452               
     453                if (rd > 0) {
     454                        /*
     455                         * Copy the contents of the communication buffer to the
     456                         * destination buffer.
     457                         */
     458                        memcpy(dst + offset, devcon->com_area + *bufpos, rd);
     459                        offset += rd;
     460                        *bufpos += rd;
     461                        *pos += rd;
     462                        left -= rd;
     463                }
     464               
     465                if (*bufpos == *buflen) {
     466                        /* Refill the communication buffer with a new block. */
     467                        ipcarg_t retval;
     468                        int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
     469                            *pos / block_size, block_size, &retval);
     470                        if ((rc != EOK) || (retval != EOK))
     471                                return (rc != EOK ? rc : retval);
     472                       
     473                        *bufpos = 0;
     474                        *buflen = block_size;
     475                }
     476        }
     477       
     478        return EOK;
    442479}
    443480
Note: See TracChangeset for help on using the changeset viewer.