Subversion Repositories HelenOS

Rev

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

Rev 3539 Rev 3540
Line 260... Line 260...
260
        return EEXIST;
260
        return EEXIST;
261
    cache = malloc(sizeof(cache_t));
261
    cache = malloc(sizeof(cache_t));
262
    if (!cache)
262
    if (!cache)
263
        return ENOMEM;
263
        return ENOMEM;
264
   
264
   
265
    futex_initialize(&cache->lock, 0);
265
    futex_initialize(&cache->lock, 1);
266
    list_initialize(&cache->free_head);
266
    list_initialize(&cache->free_head);
267
    cache->block_size = size;
267
    cache->block_size = size;
268
    cache->block_count = blocks;
268
    cache->block_count = blocks;
269
 
269
 
270
    if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
270
    if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
Line 334... Line 334...
334
    }
334
    }
335
   
335
   
336
    return EOK;
336
    return EOK;
337
}
337
}
338
 
338
 
339
block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
339
static bool cache_can_grow(cache_t *cache)
340
{
340
{
341
    /* FIXME */
341
    return true;
-
 
342
}
-
 
343
 
-
 
344
static 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
 */
-
 
361
block_t *block_get(dev_handle_t dev_handle, off_t boff, size_t bs)
-
 
362
{
-
 
363
    devcon_t *devcon;
-
 
364
    cache_t *cache;
342
    block_t *b;
365
    block_t *b;
343
    off_t bufpos = 0;
-
 
344
    size_t buflen = 0;
366
    link_t *l;
345
    off_t pos = offset * bs;
367
    unsigned long key = boff;
346
 
-
 
347
    b = malloc(sizeof(block_t));
-
 
348
    if (!b)
-
 
349
        return NULL;
-
 
350
   
368
   
351
    b->data = malloc(bs);
369
    devcon = devcon_search(dev_handle);
352
    if (!b->data) {
-
 
353
        free(b);
-
 
354
        return NULL;
-
 
355
    }
-
 
356
    b->size = bs;
-
 
357
 
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
         */
358
    if (block_read(dev_handle, &bufpos, &buflen, &pos, b->data,
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;
359
        bs, bs) != EOK) {
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);
360
        free(b->data);
405
            if (!b->data) {
361
        free(b);
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;
-
 
414
recycle:
-
 
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);
362
        return NULL;
431
        assert(rc == EOK);
-
 
432
        hash_table_insert(&cache->block_hash, &key, &b->hash_link);
363
    }
433
    }
364
 
434
 
-
 
435
    futex_up(&cache->lock);
365
    return b;
436
    return b;
366
}
437
}
367
 
438
 
368
void block_put(block_t *block)
439
void block_put(block_t *block)
369
{
440
{
370
    /* FIXME */
441
   
371
    free(block->data);
-
 
372
    free(block);
-
 
373
}
442
}
374
 
443
 
375
/** @}
444
/** @}
376
 */
445
 */