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

Changeset 02ee6bf5 in mainline


Ignore:
Timestamp:
2009-08-27T16:38:05Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
c91f2d1b
Parents:
ddfc39a3
Message:

As a provision for handling I/O errors, block_get() should write back the dirty
block before it changes its identity.

File:
1 edited

Legend:

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

    rddfc39a3 r02ee6bf5  
    328328        link_t *l;
    329329        unsigned long key = boff;
    330         bn_t oboff;
    331330       
    332331        devcon = devcon_search(dev_handle);
     
    336335       
    337336        cache = devcon->cache;
     337
     338retry:
    338339        fibril_mutex_lock(&cache->lock);
    339340        l = hash_table_find(&cache->block_hash, &key);
     
    353354                 */
    354355                int rc;
    355                 bool sync = false;
    356356
    357357                if (cache_can_grow(cache)) {
     
    378378                        assert(!list_empty(&cache->free_head));
    379379                        l = cache->free_head.next;
    380                         list_remove(l);
    381380                        b = list_get_instance(l, block_t, free_link);
    382                         sync = b->dirty;
    383                         oboff = b->boff;
     381
     382                        fibril_mutex_lock(&b->lock);
     383                        if (b->dirty) {
     384                                /*
     385                                 * The block needs to be written back to the
     386                                 * device before it changes identity. Do this
     387                                 * while not holding the cache lock so that
     388                                 * concurrency is not impeded. Also move the
     389                                 * block to the end of the free list so that we
     390                                 * do not slow down other instances of
     391                                 * block_get() draining the free list.
     392                                 */
     393                                list_remove(&b->free_link);
     394                                list_append(&b->free_link, &cache->free_head);
     395                                fibril_mutex_unlock(&cache->lock);
     396                                fibril_mutex_lock(&devcon->com_area_lock);
     397                                memcpy(devcon->com_area, b->data, b->size);
     398                                rc = write_block(devcon, b->boff,
     399                                    cache->block_size);
     400                                fibril_mutex_unlock(&devcon->com_area_lock);
     401                                assert(rc == EOK);
     402                                b->dirty = false;
     403                                if (!fibril_mutex_trylock(&cache->lock)) {
     404                                        /*
     405                                         * Somebody is probably racing with us.
     406                                         * Unlock the block and retry.
     407                                         */
     408                                        fibril_mutex_unlock(&b->lock);
     409                                        goto retry;
     410                                }
     411
     412                        }
     413                        fibril_mutex_unlock(&b->lock);
     414
     415                        /*
     416                         * Unlink the block from the free list and the hash
     417                         * table.
     418                         */
     419                        list_remove(&b->free_link);
    384420                        temp_key = b->boff;
    385421                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     
    400436                fibril_mutex_unlock(&cache->lock);
    401437
    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                 }
    413438                if (!(flags & BLOCK_FLAGS_NOREAD)) {
    414439                        /*
Note: See TracChangeset for help on using the changeset viewer.