struct bcache_entry {
uint8_t *buffer;
uint64_t size;
uint64_t lba;
uint64_t access_time;
struct mutex lock;
bool dirty;
bool no_evict;
struct bio_request *request;
refcount_t refcount;
};
struct bcache_wrapper {
uint64_t key;
struct bcache_entry *value;
bool occupied;
struct bcache_wrapper *next;
};
struct bcache {
struct bcache_wrapper **entries;
_Atomic uint64_t ticks;
uint64_t capacity;
uint64_t count;
uint64_t spb;
struct spinlock lock;
};
uint64_t bcache_hash(uint64_t x, uint64_t capacity);
void bcache_init(struct bcache *cache, uint64_t capacity);
void * bcache_get(struct block_device *disk, uint64_t lba, uint64_t block_size, uint64_t spb, bool no_evict, struct bcache_entry **out_entry);
bool bcache_writethrough(struct block_device *disk, struct bcache_entry *ent, uint64_t spb);
void bcache_write_queue(struct block_device *disk, struct bcache_entry *ent, uint64_t spb, enum bio_request_priority prio);
void bcache_stat(struct block_device *disk, uint64_t *total_dirty_out, uint64_t *total_present_out);
bool bcache_insert(struct block_device *disk, uint64_t lba, struct bcache_entry *ent, uint64_t spb);
bool bcache_evict(struct block_device *disk, uint64_t spb);
enum errno bcache_prefetch_async(struct block_device *disk, uint64_t lba, uint64_t block_size, uint64_t spb);
void * bcache_create_ent(struct block_device *disk, uint64_t lba, uint64_t block_size, uint64_t sectors_per_block, bool no_evict, struct bcache_entry **out_entry);
void bcache_increment_ticks(struct bcache *cache);
uint64_t bcache_get_ticks(struct bcache *cache);
void bcache_ent_lock(struct bcache_entry *ent);
void bcache_ent_unlock(struct bcache_entry *ent);
void bcache_ent_pin(struct bcache_entry *ent);
void bcache_ent_unpin(struct bcache_entry *ent);
void bcache_ent_acquire(struct bcache_entry *ent);
void bcache_ent_release(struct bcache_entry *ent);
#define DEFAULT_BLOCK_CACHE_SIZE 2048
#define DEFAULT_MAX_DIRTY_ENTS 64