Changeset e1c88d5 in mainline


Ignore:
Timestamp:
2008-11-02T15:57:30Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9df7918
Parents:
f1ba5d6
Message:

Enable the block cache for block_get().
Boot from FAT is now much faster.

File:
1 edited

Legend:

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

    rf1ba5d6 re1c88d5  
    263263                return ENOMEM;
    264264       
    265         futex_initialize(&cache->lock, 0);
     265        futex_initialize(&cache->lock, 1);
    266266        list_initialize(&cache->free_head);
    267267        cache->block_size = size;
     
    337337}
    338338
    339 block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
    340 {
    341         /* FIXME */
     339static bool cache_can_grow(cache_t *cache)
     340{
     341        return true;
     342}
     343
     344static void block_initialize(block_t *b)
     345{
     346        futex_initialize(&b->lock, 1);
     347        b->refcnt = 1;
     348        b->dirty = false;
     349        rwlock_initialize(&b->contents_lock);
     350        link_initialize(&b->free_link);
     351        link_initialize(&b->hash_link);
     352}
     353
     354/** Instantiate a block in memory and get a reference to it.
     355 *
     356 * @param dev_handle            Device handle of the block device.
     357 * @param boff                  Block offset.
     358 *
     359 * @return                      Block structure.
     360 */
     361block_t *block_get(dev_handle_t dev_handle, off_t boff, size_t bs)
     362{
     363        devcon_t *devcon;
     364        cache_t *cache;
    342365        block_t *b;
    343         off_t bufpos = 0;
    344         size_t buflen = 0;
    345         off_t pos = offset * bs;
    346 
    347         b = malloc(sizeof(block_t));
    348         if (!b)
    349                 return NULL;
    350        
    351         b->data = malloc(bs);
    352         if (!b->data) {
    353                 free(b);
    354                 return NULL;
    355         }
    356         b->size = bs;
    357 
    358         if (block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
    359             bs, bs) != EOK) {
    360                 free(b->data);
    361                 free(b);
    362                 return NULL;
    363         }
    364 
     366        link_t *l;
     367        unsigned long key = boff;
     368       
     369        devcon = devcon_search(dev_handle);
     370
     371        assert(devcon);
     372        assert(devcon->cache);
     373       
     374        cache = devcon->cache;
     375        futex_down(&cache->lock);
     376        l = hash_table_find(&cache->block_hash, &key);
     377        if (l) {
     378                /*
     379                 * We found the block in the cache.
     380                 */
     381                b = hash_table_get_instance(l, block_t, hash_link);
     382                futex_down(&b->lock);
     383                if (b->refcnt++ == 0)
     384                        list_remove(&b->free_link);
     385                futex_up(&b->lock);
     386        } else {
     387                /*
     388                 * The block was not found in the cache.
     389                 */
     390                int rc;
     391                off_t bufpos = 0;
     392                size_t buflen = 0;
     393                off_t pos = boff * cache->block_size;
     394
     395                if (cache_can_grow(cache)) {
     396                        /*
     397                         * We can grow the cache by allocating new blocks.
     398                         * Should the allocation fail, we fail over and try to
     399                         * recycle a block from the cache.
     400                         */
     401                        b = malloc(sizeof(block_t));
     402                        if (!b)
     403                                goto recycle;
     404                        b->data = malloc(cache->block_size);
     405                        if (!b->data) {
     406                                free(b);
     407                                goto recycle;
     408                        }
     409                } else {
     410                        /*
     411                         * Try to recycle a block from the free list.
     412                         */
     413                        unsigned long temp_key;
     414recycle:
     415                        assert(!list_empty(&cache->free_head));
     416                        l = cache->free_head.next;
     417                        list_remove(l);
     418                        b = hash_table_get_instance(l, block_t, hash_link);
     419                        assert(!b->dirty);
     420                        temp_key = b->boff;
     421                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     422                }
     423
     424                block_initialize(b);
     425                b->dev_handle = dev_handle;
     426                b->size = cache->block_size;
     427                b->boff = boff;
     428                /* read block from the device */
     429                rc = block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
     430                    cache->block_size, cache->block_size);
     431                assert(rc == EOK);
     432                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     433        }
     434
     435        futex_up(&cache->lock);
    365436        return b;
    366437}
     
    368439void block_put(block_t *block)
    369440{
    370         /* FIXME */
    371         free(block->data);
    372         free(block);
     441       
    373442}
    374443
Note: See TracChangeset for help on using the changeset viewer.