// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef _FSCACHE #define _FSCACHE #define CLEAN 0 #define DIRTY_NEW 1 // from a new write_TFS #define DIRTY_OLD 2 // from an overwrite // Values for the flags field in the Cache structure #define CACHE_DIRTY (1 << 0) #define SET_DIRTY_NEW(C, ent) { \ if (C) { \ (ent)->state = DIRTY_NEW; \ (C)->flags |= CACHE_DIRTY; \ } \ } #define SET_DIRTY_OLD(C, ent) { \ (ent)->state = DIRTY_OLD; \ (C)->flags |= CACHE_DIRTY; \ } typedef struct cache_entry FcEntry; struct cache_entry { FcEntry* next_lru; // next and prev for the LRU list is FcEntry* prev_lru; // a double linked list FcEntry* next_hash; // next and prev for the hash list is FcEntry* prev_hash; // a double linked list FcEntry** hash_head; // pointer to head of hash table list ui8* data; // pointer to cached data ui8* dirty_map; // dirty bitmap of pages in sector void* file_ptr; // pointer to file control information ui32 sect_num; // sector number in actual medium ui16 pin_cnt; // pin counter: 0 = unpinned, > 0 pinned ui16 state; // clean, dirty_new, dirty_old flag }; typedef int (*MedWFunc)(FcEntry* entry, int update, void* vol_ptr); typedef int (*MedRFunc)(void* head, ui32 sect_num, void* vol_ptr); typedef struct { FcEntry* pool; // array containing all cache entries FcEntry** hash_tbl; // hash table to point to pool FcEntry* lru_head; // head of the LRU list FcEntry* lru_tail; // tail of the LRU list ui32 pool_size; // number of cache entries ui32 sector_number; // current sector being worked on MedWFunc wr_sect; // write function to write sector back MedWFunc wr_page; // write function to write page back MedRFunc rd_sect; // read function to read sector ui32 block_sects; // num sects in memory block ui32 flags; // cache flags ui32 meta_ents; // number of non-file data sector entries ui32 meta_threshold; // min # of non-file data sector entries ui32 sector_pages; // number of pages in sector ui32 tot_access; // number of get requests ui32 hit_access; // number of hits on get requests ui32 ram_used; // RAM used by cache in bytes void* vol_ptr; // FS volume cache belongs to } Cache; int FcInit(Cache* C, ui32 pool_size, MedWFunc wrf, MedRFunc rdf, ui32 sect_sz, ui32 tmp_ents, ui32 block_sects, void* volp); int FcInitMeta(Cache* C, ui32 pool_size, ui32 meta_threshold, MedWFunc wr_sect, MedWFunc wr_page, MedRFunc rd_sect, ui32 sect_sz, ui32 pg_sz, ui32 tmp_ents, void* volp); void FcReinit(Cache* C, ui32 entry_size); void FcDestroy(Cache* C); void FcRmvEntry(Cache* C, ui32 entry_number); FcEntry* FcGetEntry(Cache* C, ui32 ent_number, int skip_rd, void* filep); void FcFreeEntry(Cache* C, FcEntry** entry); int FcFlush(Cache* C); void FcUpdateEntry(Cache* C, FcEntry* entry, ui32 entry_number); FcEntry* FcInCache(const Cache* C, ui32 entry_number); void FcSetDirtyNewPgs(Cache* C, FcEntry* ent, ui32 start, ui32 n); int FcHitsPercent(const Cache* C); int FcWriteSect(const Cache* C, FcEntry* ent, int update); int FcHash(uint sector_number, uint size); void FcRmvFmLRU(Cache* C, FcEntry* entry); ui32 FcRAM(const Cache* C); void FcDiag(Cache* C); #endif // _FSCACHE