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

Changeset ddfc39a3 in mainline


Ignore:
Timestamp:
2009-08-27T10:21:59Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
02ee6bf5
Parents:
5ac8918
Message:

block_put() should not hold the cache lock when syncing the block.

File:
1 edited

Legend:

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

    r5ac8918 rddfc39a3  
    438438        devcon_t *devcon = devcon_search(block->dev_handle);
    439439        cache_t *cache;
     440        unsigned blocks_cached;
     441        enum cache_mode mode;
    440442        int rc;
    441443
     
    444446
    445447        cache = devcon->cache;
     448
     449retry:
     450        fibril_mutex_lock(&cache->lock);
     451        blocks_cached = cache->blocks_cached;
     452        mode = cache->mode;
     453        fibril_mutex_unlock(&cache->lock);
     454
     455        /*
     456         * Determine whether to sync the block. Syncing the block is best done
     457         * when not holding the cache lock as it does not impede concurrency.
     458         * Since the situation may have changed when we unlocked the cache, the
     459         * blocks_cached and mode variables are mere hints. We will recheck the
     460         * conditions later when the cache lock is held again.
     461         */
     462        fibril_mutex_lock(&block->lock);
     463        if (block->dirty && (block->refcnt == 1) &&
     464            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
     465                fibril_mutex_lock(&devcon->com_area_lock);
     466                memcpy(devcon->com_area, block->data, block->size);
     467                rc = write_block(devcon, block->boff, block->size);
     468                assert(rc == EOK);
     469                fibril_mutex_unlock(&devcon->com_area_lock);
     470                block->dirty = false;
     471        }
     472        fibril_mutex_unlock(&block->lock);
     473
    446474        fibril_mutex_lock(&cache->lock);
    447475        fibril_mutex_lock(&block->lock);
     
    456484                         */
    457485                        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);
     486                                /*
     487                                 * We cannot sync the block while holding the
     488                                 * cache lock. Release everything and retry.
     489                                 */
     490                                block->refcnt++;
     491                                fibril_mutex_unlock(&block->lock);
     492                                fibril_mutex_unlock(&cache->lock);
     493                                goto retry;
    465494                        }
    466495                        /*
     
    478507                 * Put the block on the free list.
    479508                 */
     509                if (cache->mode != CACHE_MODE_WB && block->dirty) {
     510                        /*
     511                         * We cannot sync the block while holding the cache
     512                         * lock. Release everything and retry.
     513                         */
     514                        block->refcnt++;
     515                        fibril_mutex_unlock(&block->lock);
     516                        fibril_mutex_unlock(&cache->lock);
     517                        goto retry;
     518                }
    480519                list_append(&block->free_link, &cache->free_head);
    481                 if (cache->mode != CACHE_MODE_WB && block->dirty) {
    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                 }
    490520        }
    491521        fibril_mutex_unlock(&block->lock);
Note: See TracChangeset for help on using the changeset viewer.