dev: implement reading from block devices

reading from block devices is done using the block cache (bcache).
This cache stores sectors from a block device in pages of memory
marked as 'cached', which will allow them to be reclaimed when
memory pressure is high (TODO).

while block device drivers implement callbacks allowing reading/writing
at block-granularity, the device subsystem uses the block cache to
implement reading/writing at byte-granularity in a driver-agnostic way.

block drivers can disable the block cache for their devices, but this
will require that any clients communicate with the devices at
block-granularity.

also added an offset parameter to device and object read/write functions/callbacks.
This commit is contained in:
2023-07-09 21:58:40 +01:00
parent 53440653f2
commit 3233169f25
14 changed files with 435 additions and 52 deletions

46
include/socks/block.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef SOCKS_BLOCK_H_
#define SOCKS_BLOCK_H_
#include <socks/types.h>
#include <socks/btree.h>
#include <socks/locks.h>
#include <socks/status.h>
#include <stdbool.h>
enum block_device_flags {
BLOCK_DEVICE_NO_BCACHE = 0x01u,
};
struct bcache {
unsigned int b_sector_size;
unsigned int b_sectors_per_page;
struct btree b_pagetree;
spin_lock_t b_lock;
};
struct bcache_sector {
struct vm_page *sect_page;
unsigned int sect_index;
void *sect_buf;
bool sect_present;
};
extern struct bcache *bcache_create(unsigned int block_size);
extern void bcache_destroy(struct bcache *cache);
extern kern_status_t bcache_init(struct bcache *cache, unsigned int block_size);
extern void bcache_deinit(struct bcache *cache);
static inline void bcache_lock(struct bcache *cache)
{
spin_lock(&cache->b_lock);
}
static inline void bcache_unlock(struct bcache *cache)
{
spin_unlock(&cache->b_lock);
}
extern kern_status_t bcache_get(struct bcache *cache, sectors_t at, bool create, struct bcache_sector *out);
extern void bcache_mark_present(struct bcache_sector *sect);
#endif