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. |