Subversion Repositories HelenOS

Rev

Rev 3543 | Rev 3571 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3543 Rev 3544
Line 322... Line 322...
322
        b = hash_table_get_instance(l, block_t, hash_link);
322
        b = hash_table_get_instance(l, block_t, hash_link);
323
        futex_down(&b->lock);
323
        futex_down(&b->lock);
324
        if (b->refcnt++ == 0)
324
        if (b->refcnt++ == 0)
325
            list_remove(&b->free_link);
325
            list_remove(&b->free_link);
326
        futex_up(&b->lock);
326
        futex_up(&b->lock);
-
 
327
        futex_up(&cache->lock);
327
    } else {
328
    } else {
328
        /*
329
        /*
329
         * The block was not found in the cache.
330
         * The block was not found in the cache.
330
         */
331
         */
331
        int rc;
332
        int rc;
332
        off_t bufpos = 0;
333
        off_t bufpos = 0;
333
        size_t buflen = 0;
334
        size_t buflen = 0;
334
        off_t pos = boff * cache->block_size;
335
        off_t pos = boff * cache->block_size;
-
 
336
        bool sync = false;
335
 
337
 
336
        if (cache_can_grow(cache)) {
338
        if (cache_can_grow(cache)) {
337
            /*
339
            /*
338
             * We can grow the cache by allocating new blocks.
340
             * We can grow the cache by allocating new blocks.
339
             * Should the allocation fail, we fail over and try to
341
             * Should the allocation fail, we fail over and try to
Line 355... Line 357...
355
recycle:
357
recycle:
356
            assert(!list_empty(&cache->free_head));
358
            assert(!list_empty(&cache->free_head));
357
            l = cache->free_head.next;
359
            l = cache->free_head.next;
358
            list_remove(l);
360
            list_remove(l);
359
            b = hash_table_get_instance(l, block_t, hash_link);
361
            b = hash_table_get_instance(l, block_t, hash_link);
360
            assert(!b->dirty);
362
            sync = b->dirty;
361
            temp_key = b->boff;
363
            temp_key = b->boff;
362
            hash_table_remove(&cache->block_hash, &temp_key, 1);
364
            hash_table_remove(&cache->block_hash, &temp_key, 1);
363
        }
365
        }
364
 
366
 
365
        block_initialize(b);
367
        block_initialize(b);
366
        b->dev_handle = dev_handle;
368
        b->dev_handle = dev_handle;
367
        b->size = cache->block_size;
369
        b->size = cache->block_size;
368
        b->boff = boff;
370
        b->boff = boff;
-
 
371
        hash_table_insert(&cache->block_hash, &key, &b->hash_link);
-
 
372
 
-
 
373
        /*
-
 
374
         * Lock the block before releasing the cache lock. Thus we don't
-
 
375
         * kill concurent operations on the cache while doing I/O on the
-
 
376
         * block.
-
 
377
         */
-
 
378
        futex_down(&b->lock);
-
 
379
        futex_up(&cache->lock);
-
 
380
 
-
 
381
        if (sync) {
-
 
382
            /*
-
 
383
             * The block is dirty and needs to be written back to
-
 
384
             * the device before we can read in the new contents.
-
 
385
             */
-
 
386
            abort();    /* TODO: block_write() */
-
 
387
        }
-
 
388
        /*
-
 
389
         * The block contains old or no data. We need to read the new
369
        /* read block from the device */
390
         * contents from the device.
-
 
391
         */
370
        rc = block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
392
        rc = block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
371
            cache->block_size, cache->block_size);
393
            cache->block_size, cache->block_size);
372
        assert(rc == EOK);
394
        assert(rc == EOK);
373
        hash_table_insert(&cache->block_hash, &key, &b->hash_link);
-
 
374
    }
-
 
375
 
395
 
376
    futex_up(&cache->lock);
396
        futex_up(&b->lock);
-
 
397
    }
377
    return b;
398
    return b;
378
}
399
}
379
 
400
 
380
/** Release a reference to a block.
401
/** Release a reference to a block.
381
 *
402
 *
382
 * If the last reference is dropped, the block is put on the free list.  If the
403
 * If the last reference is dropped, the block is put on the free list.
383
 * last reference is dropped and the block is dirty, it is first synced with the
-
 
384
 * block device.
-
 
385
 *
404
 *
386
 * @param block     Block of which a reference is to be released.
405
 * @param block     Block of which a reference is to be released.
387
 */
406
 */
388
void block_put(block_t *block)
407
void block_put(block_t *block)
389
{
408
{
Line 400... Line 419...
400
        /*
419
        /*
401
         * Last reference to the block was dropped, put the block on the
420
         * Last reference to the block was dropped, put the block on the
402
         * free list.
421
         * free list.
403
         */
422
         */
404
        list_append(&block->free_link, &cache->free_head);
423
        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
    }
424
    }
419
    futex_up(&block->lock);
425
    futex_up(&block->lock);
-
 
426
    futex_up(&cache->lock);
420
}
427
}
421
 
428
 
422
/** Read data from a block device.
429
/** Read data from a block device.
423
 *
430
 *
424
 * @param dev_handle    Device handle of the block device.
431
 * @param dev_handle    Device handle of the block device.