|
AquilaOS documentation
How it works, and its code
|
The block cache: what the disks read and write, kept in 4 KiB blocks. More...
#include <core/system.h>#include <core/string.h>#include <core/arch.h>#include <mm/mm.h>#include <dev/blkcache.h>#include <aquila/errno.h>Go to the source code of this file.
Data Structures | |
| struct | blk |
| A block of the cache. More... | |
Macros | |
| #define | SECTOR_SIZE 512 |
| #define | BLK_SECTORS 8 |
| #define | BLK_SIZE (BLK_SECTORS * SECTOR_SIZE) |
| #define | BLK_ALL 0xFF |
| #define | CACHE_BLOCKS 2048 |
| #define | CACHE_BUCKETS 1024 |
| #define | RUN_MAX 16 |
| #define | DIRTY_MAX (CACHE_BLOCKS / 2) |
| #define | DIRTY_AGE 5000000000ULL |
Functions | |
| static char * | blk_data (struct blk *b) |
| Returns a block's data. | |
| static uint8_t | sector_mask (size_t first, size_t n) |
| Returns the mask of n sectors from sector first of a block. | |
| static struct blk ** | bucket (void *owner, uint64_t nr) |
| Returns the hash chain that block nr of owner is on. | |
| static struct blk * | lookup (void *owner, uint64_t nr) |
| Returns block nr of owner, or NULL if it isn't cached. | |
| static void | lru_unlink (struct blk *b) |
| Takes a block off the list of blocks by use. | |
| static void | lru_push (struct blk *b) |
| Puts a block at the head of the list: the most recently used. | |
| static void | touch (struct blk *b) |
| Marks a block as just used. | |
| static void | evict (struct blk *b) |
| Takes a clean block out of the cache. | |
| static void | make_dirty (struct blk *b, uint8_t mask, blkcache_io write) |
| Marks sectors of a block dirty, to be written with write. | |
| static void | make_clean (struct blk *b, uint8_t mask) |
| Marks sectors of a block clean. | |
| static struct blk * | block_new (void *owner, uint64_t nr) |
| Takes a block for block nr of owner, with nothing valid in it: a free slot, or the clean block used least recently. | |
| static void | prefault (void *buf, size_t size, int write) |
| Maps every page of a buffer, by touching them: a process's buffer isn't mapped until it is used. | |
| static void | overlap (uint64_t nr, uint64_t sector, size_t count, size_t *first, size_t *n, size_t *off) |
| Finds the sectors of block nr that are in the request [sector,
sector + count): n of them, from sector first of the block, at sector off of the request. | |
| static int | full_dirty (struct blk *b) |
| Returns whether a block exists and all its sectors are dirty. | |
| static int | flush_block (struct blk *b) |
| Writes the dirty sectors of b to the disk (with the wholly dirty blocks right after it, in one command), and marks them clean. | |
| int | blkcache_flush (void) |
| Writes every dirty block of the cache to its disk. | |
| static void | flush_old (void) |
| Writes the dirty blocks to the disk if the oldest one is old enough (DIRTY_AGE). | |
| ssize_t | blkcache_read (void *owner, uint64_t sector, size_t count, void *buf, uint64_t nsectors, blkcache_io read) |
| Reads sectors of a disk through the cache. | |
| ssize_t | blkcache_write (void *owner, uint64_t sector, size_t count, void *buf, blkcache_io write) |
| Writes sectors of a disk through the cache: they stay dirty in it until it is flushed. | |
Variables | |
| static struct blk | blks [CACHE_BLOCKS] |
| static char * | arena |
| static struct blk * | buckets [CACHE_BUCKETS] |
| static struct blk * | newest |
| static struct blk * | oldest |
| static size_t | used |
| static size_t | dirty |
| static uint64_t | dirty_since |
| static uint64_t | writes |
The block cache: what the disks read and write, kept in 4 KiB blocks.
Writes stay in the cache (write back) until blkcache_flush() writes them to the disk: for sync(), before restarting or powering off, when too much was written (DIRTY_MAX), or at the next use of the cache once a write is old enough (DIRTY_AGE). Each sector of a block is either valid (it has the disk's data, or newer) or not, and either dirty (newer than the disk's) or not, so a write doesn't need to read the rest of its block. When the cache is full, the clean block used least recently makes room.
Drivers use the cache with absolute sector numbers, after adding the partition's offset, so a sector is cached once, whichever device node it was read through. The blocks that a read needs and the cache doesn't have are read with one command, and adjacent dirty blocks are written with one.
The device's transfers are always to and from the cache's own buffers, never the caller's. The caller's buffer may be a process's, which isn't mapped until it is touched, and mapping it may read the disk: the driver would wait for itself. The caller's buffer is only used once its pages are mapped.
Definition in file blkcache.c.
| #define BLK_ALL 0xFF |
Definition at line 38 of file blkcache.c.
Referenced by flush_block(), and full_dirty().
| #define BLK_SECTORS 8 |
Definition at line 36 of file blkcache.c.
Referenced by blkcache_read(), blkcache_write(), flush_block(), and overlap().
| #define BLK_SIZE (BLK_SECTORS * SECTOR_SIZE) |
Definition at line 37 of file blkcache.c.
Referenced by blk_data(), blkcache_read(), block_new(), and flush_block().
| #define CACHE_BLOCKS 2048 |
Definition at line 41 of file blkcache.c.
Referenced by blkcache_flush(), and block_new().
| #define CACHE_BUCKETS 1024 |
Definition at line 42 of file blkcache.c.
Referenced by bucket().
| #define DIRTY_AGE 5000000000ULL |
Definition at line 50 of file blkcache.c.
Referenced by flush_old().
| #define DIRTY_MAX (CACHE_BLOCKS / 2) |
Definition at line 49 of file blkcache.c.
Referenced by blkcache_write().
| #define RUN_MAX 16 |
Definition at line 45 of file blkcache.c.
Referenced by blkcache_flush(), blkcache_read(), and flush_block().
| #define SECTOR_SIZE 512 |
Definition at line 35 of file blkcache.c.
Referenced by blkcache_read(), blkcache_write(), and flush_block().
|
inlinestatic |
Returns a block's data.
Definition at line 78 of file blkcache.c.
References arena, blk_data(), BLK_SIZE, and blks.
Referenced by blk_data(), blkcache_read(), blkcache_write(), and flush_block().
| int blkcache_flush | ( | void | ) |
Writes every dirty block of the cache to its disk.
Definition at line 309 of file blkcache.c.
References blkcache_flush(), blks, CACHE_BLOCKS, blk::dirty, dirty, flush_block(), full_dirty(), lookup(), blk::nr, blk::owner, RUN_MAX, and blk::write.
Referenced by blkcache_flush(), blkcache_write(), flush_old(), and kdev_sync().
| ssize_t blkcache_read | ( | void * | owner, |
| uint64_t | sector, | ||
| size_t | count, | ||
| void * | buf, | ||
| uint64_t | nsectors, | ||
| blkcache_io | read ) |
Reads sectors of a disk through the cache.
The sectors the cache doesn't have are read with read, and cached.
| owner | the disk (the driver's, for its sectors) |
| sector | the first sector, absolute on the disk |
| count | how many sectors |
| buf | where to put them |
| nsectors | the disk's size in sectors, or 0 if it isn't known |
| read | how the driver reads sectors |
Definition at line 367 of file blkcache.c.
References blk_data(), BLK_SECTORS, BLK_SIZE, blkcache_read(), block_new(), flush_old(), kfree(), kmalloc(), lookup(), memcpy(), MIN, blk::nr, overlap(), blk::owner, prefault(), RUN_MAX, sector_mask(), SECTOR_SIZE, touch(), blk::valid, and writes.
Referenced by ata_read(), and blkcache_read().
| ssize_t blkcache_write | ( | void * | owner, |
| uint64_t | sector, | ||
| size_t | count, | ||
| void * | buf, | ||
| blkcache_io | write ) |
Writes sectors of a disk through the cache: they stay dirty in it until it is flushed.
If the cache has no room even after flushing, they go straight to the disk.
| owner | the disk (the driver's, for its sectors) |
| sector | the first sector, absolute on the disk |
| count | how many sectors |
| buf | the sectors' data |
| write | how the driver writes sectors |
Definition at line 484 of file blkcache.c.
References blk_data(), BLK_SECTORS, blkcache_flush(), blkcache_write(), block_new(), dirty, DIRTY_MAX, flush_old(), kfree(), kmalloc(), lookup(), make_dirty(), memcpy(), blk::nr, overlap(), blk::owner, prefault(), sector_mask(), SECTOR_SIZE, touch(), blk::valid, blk::write, and writes.
Referenced by ata_write(), and blkcache_write().
Takes a block for block nr of owner, with nothing valid in it: a free slot, or the clean block used least recently.
Returns NULL if every block is dirty, or there is no memory for the cache.
Definition at line 166 of file blkcache.c.
References arena, BLK_SIZE, blks, block_new(), bucket(), CACHE_BLOCKS, blk::dirty, evict(), blk::hnext, kmalloc(), lru_push(), blk::newer, blk::nr, NULL, oldest, blk::owner, used, and blk::valid.
Referenced by blkcache_read(), blkcache_write(), and block_new().
Returns the hash chain that block nr of owner is on.
Definition at line 90 of file blkcache.c.
References bucket(), buckets, CACHE_BUCKETS, blk::nr, and blk::owner.
Referenced by block_new(), bucket(), evict(), and lookup().
|
static |
Takes a clean block out of the cache.
Definition at line 133 of file blkcache.c.
References bucket(), evict(), blk::hnext, lru_unlink(), blk::nr, NULL, blk::owner, and used.
Referenced by block_new(), and evict().
|
static |
Writes the dirty sectors of b to the disk (with the wholly dirty blocks right after it, in one command), and marks them clean.
Returns 0 or a negative errno; sectors whose write failed stay dirty.
Definition at line 241 of file blkcache.c.
References BLK_ALL, blk_data(), BLK_SECTORS, BLK_SIZE, blk::dirty, flush_block(), full_dirty(), kfree(), kmalloc(), lookup(), make_clean(), make_dirty(), memcpy(), blk::nr, blk::owner, RUN_MAX, sector_mask(), SECTOR_SIZE, and blk::write.
Referenced by blkcache_flush(), and flush_block().
|
static |
Writes the dirty blocks to the disk if the oldest one is old enough (DIRTY_AGE).
Definition at line 344 of file blkcache.c.
References arch_rtime_ns(), blkcache_flush(), dirty, DIRTY_AGE, dirty_since, and flush_old().
Referenced by blkcache_read(), blkcache_write(), and flush_old().
|
inlinestatic |
Returns whether a block exists and all its sectors are dirty.
Definition at line 233 of file blkcache.c.
References BLK_ALL, blk::dirty, and full_dirty().
Referenced by blkcache_flush(), flush_block(), and full_dirty().
Returns block nr of owner, or NULL if it isn't cached.
Definition at line 96 of file blkcache.c.
References bucket(), blk::hnext, lookup(), blk::nr, NULL, and blk::owner.
Referenced by blkcache_flush(), blkcache_read(), blkcache_write(), flush_block(), and lookup().
|
static |
Puts a block at the head of the list: the most recently used.
Definition at line 114 of file blkcache.c.
References lru_push(), blk::newer, newest, NULL, blk::older, and oldest.
Referenced by block_new(), lru_push(), and touch().
|
static |
Takes a block off the list of blocks by use.
Definition at line 106 of file blkcache.c.
References lru_unlink(), blk::newer, newest, NULL, blk::older, and oldest.
Referenced by evict(), lru_unlink(), and touch().
Marks sectors of a block clean.
Definition at line 157 of file blkcache.c.
References blk::dirty, dirty, and make_clean().
Referenced by flush_block(), and make_clean().
|
static |
Marks sectors of a block dirty, to be written with write.
Definition at line 147 of file blkcache.c.
References arch_rtime_ns(), blk::dirty, dirty, dirty_since, make_dirty(), and blk::write.
Referenced by blkcache_write(), flush_block(), and make_dirty().
|
static |
Finds the sectors of block nr that are in the request [sector, sector + count): n of them, from sector first of the block, at sector off of the request.
Definition at line 221 of file blkcache.c.
References BLK_SECTORS, MAX, MIN, blk::nr, and overlap().
Referenced by blkcache_read(), blkcache_write(), and overlap().
|
static |
Maps every page of a buffer, by touching them: a process's buffer isn't mapped until it is used.
It is done before the cache is looked at, because mapping a page may read the disk and change the cache.
Definition at line 203 of file blkcache.c.
References PAGE_ALIGN, PAGE_SIZE, prefault(), and blk::write.
Referenced by blkcache_read(), blkcache_write(), and prefault().
Returns the mask of n sectors from sector first of a block.
Definition at line 84 of file blkcache.c.
References sector_mask().
Referenced by blkcache_read(), blkcache_write(), flush_block(), and sector_mask().
|
static |
Marks a block as just used.
Definition at line 124 of file blkcache.c.
References lru_push(), lru_unlink(), newest, and touch().
Referenced by blkcache_read(), blkcache_write(), and touch().
|
static |
Definition at line 64 of file blkcache.c.
Referenced by blk_data(), and block_new().
|
static |
Definition at line 63 of file blkcache.c.
Referenced by blk_data(), blkcache_flush(), and block_new().
|
static |
Definition at line 66 of file blkcache.c.
Referenced by bucket(), and hashmap_grow().
|
static |
Definition at line 68 of file blkcache.c.
Referenced by blkcache_flush(), blkcache_write(), flush_old(), make_clean(), and make_dirty().
|
static |
Definition at line 71 of file blkcache.c.
Referenced by flush_old(), and make_dirty().
|
static |
Definition at line 67 of file blkcache.c.
Referenced by lru_push(), lru_unlink(), and touch().
|
static |
Definition at line 67 of file blkcache.c.
Referenced by block_new(), lru_push(), and lru_unlink().
|
static |
Definition at line 68 of file blkcache.c.
Referenced by arp_update(), block_new(), and evict().
|
static |
Definition at line 75 of file blkcache.c.
Referenced by blkcache_read(), and blkcache_write().