Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d68e4d5 in mainline for uspace/lib/libblock/libblock.c


Ignore:
Timestamp:
2009-07-04T13:04:13Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
7114d83
Parents:
2a77841d
Message:

Make the libblock cache behave more like a cache and fix some bugs
present in the previously unused code paths.

File:
1 edited

Legend:

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

    r2a77841d rd68e4d5  
    6464        size_t block_size;              /**< Block size. */
    6565        unsigned block_count;           /**< Total number of blocks. */
     66        unsigned blocks_cached;         /**< Number of cached blocks. */
    6667        hash_table_t block_hash;
    6768        link_t free_head;
     
    7374        dev_handle_t dev_handle;
    7475        int dev_phone;
     76        fibril_mutex_t com_area_lock;
    7577        void *com_area;
    7678        size_t com_size;
     
    113115        devcon->dev_handle = dev_handle;
    114116        devcon->dev_phone = dev_phone;
     117        fibril_mutex_initialize(&devcon->com_area_lock);
    115118        devcon->com_area = com_area;
    116119        devcon->com_size = com_size;
     
    212215                return ENOMEM;
    213216       
     217        fibril_mutex_lock(&devcon->com_area_lock);
    214218        rc = read_block(devcon, 0, size);
    215219        if (rc != EOK) {
     220                fibril_mutex_unlock(&devcon->com_area_lock);
    216221                free(bb_buf);
    217222                return rc;
    218223        }
    219 
    220224        memcpy(bb_buf, devcon->com_area, size);
     225        fibril_mutex_unlock(&devcon->com_area_lock);
    221226
    222227        devcon->bb_buf = bb_buf;
     
    272277        cache->block_size = size;
    273278        cache->block_count = blocks;
     279        cache->blocks_cached = 0;
    274280        cache->mode = mode;
    275281
     
    284290}
    285291
     292#define CACHE_LO_WATERMARK      10     
     293#define CACHE_HI_WATERMARK      20     
    286294static bool cache_can_grow(cache_t *cache)
    287295{
     296        if (cache->blocks_cached < CACHE_LO_WATERMARK)
     297                return true;
     298        if (!list_empty(&cache->free_head))
     299                return false;
    288300        return true;
    289301}
     
    316328        link_t *l;
    317329        unsigned long key = boff;
     330        bn_t oboff;
    318331       
    319332        devcon = devcon_search(dev_handle);
     
    356369                                goto recycle;
    357370                        }
     371                        cache->blocks_cached++;
    358372                } else {
    359373                        /*
     
    365379                        l = cache->free_head.next;
    366380                        list_remove(l);
    367                         b = hash_table_get_instance(l, block_t, hash_link);
     381                        b = list_get_instance(l, block_t, free_link);
    368382                        sync = b->dirty;
     383                        oboff = b->boff;
    369384                        temp_key = b->boff;
    370385                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     
    390405                         * the device before we can read in the new contents.
    391406                         */
    392                         abort();        /* TODO: block_write() */
     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);
    393412                }
    394413                if (!(flags & BLOCK_FLAGS_NOREAD)) {
     
    397416                         * the new contents from the device.
    398417                         */
     418                        fibril_mutex_lock(&devcon->com_area_lock);
    399419                        rc = read_block(devcon, b->boff, cache->block_size);
    400420                        assert(rc == EOK);
    401421                        memcpy(b->data, devcon->com_area, cache->block_size);
     422                        fibril_mutex_unlock(&devcon->com_area_lock);
    402423                }
    403424
     
    427448        if (!--block->refcnt) {
    428449                /*
    429                  * Last reference to the block was dropped, put the block on the
    430                  * free list.
     450                 * Last reference to the block was dropped. Either free the
     451                 * block or put it on the free list.
     452                 */
     453                if (cache->blocks_cached > CACHE_HI_WATERMARK) {
     454                        /*
     455                         * Currently there are too many cached blocks.
     456                         */
     457                        if (block->dirty) {
     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);
     465                        }
     466                        /*
     467                         * Take the block out of the cache and free it.
     468                         */
     469                        unsigned long key = block->boff;
     470                        hash_table_remove(&cache->block_hash, &key, 1);
     471                        free(block);
     472                        free(block->data);
     473                        cache->blocks_cached--;
     474                        fibril_mutex_unlock(&cache->lock);
     475                        return;
     476                }
     477                /*
     478                 * Put the block on the free list.
    431479                 */
    432480                list_append(&block->free_link, &cache->free_head);
    433481                if (cache->mode != CACHE_MODE_WB && block->dirty) {
     482                        fibril_mutex_lock(&devcon->com_area_lock);
    434483                        memcpy(devcon->com_area, block->data, block->size);
    435484                        rc = write_block(devcon, block->boff, block->size);
    436485                        assert(rc == EOK);
     486                        fibril_mutex_unlock(&devcon->com_area_lock);
    437487
    438488                        block->dirty = false;
     
    465515        assert(devcon);
    466516       
     517        fibril_mutex_lock(&devcon->com_area_lock);
    467518        while (left > 0) {
    468519                size_t rd;
     
    490541
    491542                        rc = read_block(devcon, *pos / block_size, block_size);
    492                         if (rc != EOK)
     543                        if (rc != EOK) {
     544                                fibril_mutex_unlock(&devcon->com_area_lock);
    493545                                return rc;
     546                        }
    494547                       
    495548                        *bufpos = 0;
     
    497550                }
    498551        }
     552        fibril_mutex_unlock(&devcon->com_area_lock);
    499553       
    500554        return EOK;
Note: See TracChangeset for help on using the changeset viewer.