CS350 COS
COS
Loading...
Searching...
No Matches
bufcache.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/kassert.h>
#include <sys/kdebug.h>
#include <sys/kmem.h>
#include <sys/spinlock.h>
#include <sys/disk.h>
#include <sys/bufcache.h>
#include <errno.h>
Include dependency graph for bufcache.c:

Go to the source code of this file.

Macros

#define CACHESIZE   (16*1024*1024)
 
#define HASHTABLEENTRIES   128
 
#define BLOCKSIZE   (16*1024)
 

Functions

static TAILQ_HEAD (CacheHashTable, DEFINE_SLAB(BufCacheEntry)
 
static int BufCacheLookup (Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
 
static int BufCacheAlloc (Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
 
int BufCache_Alloc (Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
 
void BufCache_Release (BufCacheEntry *entry)
 
int BufCache_Read (Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
 
int BufCache_Write (BufCacheEntry *entry)
 
static void Debug_BufCache (int argc, const char *argv[])
 
 REGISTER_DBGCMD (diskcache, "Display disk cache statistics", Debug_BufCache)
 

Variables

Spinlock cacheLock
 
XMemdiskBuf
 

Macro Definition Documentation

◆ BLOCKSIZE

#define BLOCKSIZE   (16*1024)

◆ CACHESIZE

#define CACHESIZE   (16*1024*1024)

◆ HASHTABLEENTRIES

#define HASHTABLEENTRIES   128

Function Documentation

◆ BufCache_Alloc()

int BufCache_Alloc ( Disk disk,
uint64_t  diskOffset,
BufCacheEntry **  entry 
)

BufCache_Alloc –

Allocate a buffer cache entry to allow writing new data to disk.

Parameters
[in]diskDisk object
[in]diskOffsetBlock offset within the disk
[out]entryIf successful, this contains the buffer cache entry.
Return values
0if successful
Returns
Otherwise returns an error code.

Definition at line 178 of file bufcache.c.

179{
180 int status;
181
183
184 status = BufCacheLookup(disk, diskOffset, entry);
185 if (*entry == NULL) {
186 status = BufCacheAlloc(disk, diskOffset, entry);
187 }
188
189 cacheAlloc++;
190
192
193 return status;
194}
Spinlock cacheLock
Definition: bufcache.c:18
static int BufCacheLookup(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
Definition: bufcache.c:97
static int BufCacheAlloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
Definition: bufcache.c:133
uint64_t diskOffset
Definition: newfs_o2fs.c:28
void Spinlock_Unlock(Spinlock *lock) __UNLOCK_EX(*lock)
Definition: spinlock.c:109
void Spinlock_Lock(Spinlock *lock) __LOCK_EX(*lock)
Definition: spinlock.c:75
#define NULL
Definition: stddef.h:6
Here is the call graph for this function:

◆ BufCache_Read()

int BufCache_Read ( Disk disk,
uint64_t  diskOffset,
BufCacheEntry **  entry 
)

BufCache_Read –

Read block from disk into the buffer cache.

Parameters
[in]diskDisk object
[in]diskOffsetBlock offset within the disk
[out]entryIf successful, this contains the buffer cache entry.
Return values
0if successful
Returns
Otherwise returns an error code.

Definition at line 229 of file bufcache.c.

230{
231 int status;
232 void *buf;
233 SGArray sga;
234
236 status = BufCacheLookup(disk, diskOffset, entry);
237 if (*entry != NULL) {
238 cacheHit++;
240 return status;
241 }
242 cacheMiss++;
243
244 status = BufCacheAlloc(disk, diskOffset, entry);
245 if (status != 0) {
247 return status;
248 }
249
250 buf = (*entry)->buffer;
251 SGArray_Init(&sga);
253
254 /*
255 * XXX: Need to avoid holding cacheLock while reading from the disk, but
256 * need ensure other cores doesn't issue a read to the same block.
257 */
258 status = Disk_Read(disk, buf, &sga, NULL, NULL);
260
261 return status;
262}
#define BLOCKSIZE
int Disk_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
Definition: disk.c:44
static char buf[4096]
Definition: ethdump.c:10
void SGArray_Init(SGArray *sga)
Definition: sga.c:12
int SGArray_Append(SGArray *sga, uint64_t off, uint64_t len)
Definition: sga.c:18
Definition: sga.h:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BufCache_Release()

void BufCache_Release ( BufCacheEntry entry)

BufCache_Release –

Release a buffer cache entry. If no other references are held the buffer cache entry is placed on the LRU list.

Parameters
[in]entryBuffer cache entry.

Definition at line 205 of file bufcache.c.

206{
208
209 entry->refCount--;
210 if (entry->refCount == 0) {
211 TAILQ_INSERT_TAIL(&lruList, entry, lruEntry);
212 }
213
215}
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:641
uint64_t refCount
Definition: bufcache.h:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BufCache_Write()

int BufCache_Write ( BufCacheEntry entry)

BufCache_Write –

Write a buffer cache entry to disk.

Return values
0if successful
Returns
Otherwise an error code is returned.

Definition at line 273 of file bufcache.c.

274{
275 void *buf = entry->buffer;
276 SGArray sga;
277
278 SGArray_Init(&sga);
279 SGArray_Append(&sga, entry->diskOffset, BLOCKSIZE);
280
281 return Disk_Write(entry->disk, buf, &sga, NULL, NULL);
282}
int Disk_Write(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
Definition: disk.c:50
void * buffer
Definition: bufcache.h:11
Disk * disk
Definition: bufcache.h:8
uint64_t diskOffset
Definition: bufcache.h:9
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BufCacheAlloc()

static int BufCacheAlloc ( Disk disk,
uint64_t  diskOffset,
BufCacheEntry **  entry 
)
static

BufCacheAlloc –

Allocates a buffer cache entry that can be used by BufCache_Alloc or BufCache_Read to allocate the underlying buffer..

Parameters
[in]diskDisk object
[in]diskOffsetBlock offset within the disk
[out]entryIf successful, this contains the buffer cache entry.
Return values
0if successful.
Returns
ENOMEM if there's no buffer cache entries free.

Definition at line 133 of file bufcache.c.

134{
135 struct CacheHashTable *table;
136 BufCacheEntry *e;
137
138 // Allocate from LRU list
139 e = TAILQ_FIRST(&lruList);
140 if (e == NULL) {
141 kprintf("BufCache: No space left!\n");
142 return ENOMEM;
143 }
144 TAILQ_REMOVE(&lruList, e, lruEntry);
145
146 // Remove from hash table
147 if (e->disk != NULL) {
148 table = &hashTable[e->diskOffset % HASHTABLEENTRIES];
149 TAILQ_REMOVE(table, e, htEntry);
150 }
151
152 // Initialize
153 e->disk = disk;
155 e->refCount = 1;
156
157 // Reinsert into hash table
158 table = &hashTable[diskOffset % HASHTABLEENTRIES];
159 TAILQ_INSERT_HEAD(table, e, htEntry);
160 *entry = e;
161
162 return 0;
163}
#define HASHTABLEENTRIES
#define ENOMEM
Definition: errno.h:14
int kprintf(const char *fmt,...)
Definition: printf.c:210
#define TAILQ_FIRST(head)
Definition: queue.h:555
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:659
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:628
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BufCacheLookup()

static int BufCacheLookup ( Disk disk,
uint64_t  diskOffset,
BufCacheEntry **  entry 
)
static

BufCacheLookup –

Looks up a buffer cache entry that can be used by BufCache_Alloc or BufCache_Read to allocate the underlying buffer.

Parameters
[in]diskDisk object
[in]diskOffsetBlock offset within the disk
[out]entryIf successful, this contains the buffer cache entry.
Return values
0if successful
Returns
ENOENT if not present.

Definition at line 97 of file bufcache.c.

98{
99 struct CacheHashTable *table;
100 BufCacheEntry *e;
101
102 // Check hash table
103 table = &hashTable[diskOffset % HASHTABLEENTRIES];
104 TAILQ_FOREACH(e, table, htEntry) {
105 if (e->disk == disk && e->diskOffset == diskOffset) {
106 e->refCount++;
107 if (e->refCount == 1) {
108 TAILQ_REMOVE(&lruList, e, lruEntry);
109 }
110 *entry = e;
111 return 0;
112 }
113 }
114
115 *entry = NULL;
116 return ENOENT;
117}
#define ENOENT
Definition: errno.h:15
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:557
Here is the caller graph for this function:

◆ Debug_BufCache()

static void Debug_BufCache ( int  argc,
const char *  argv[] 
)
static

Definition at line 285 of file bufcache.c.

286{
287 kprintf("Hits: %lld\n", cacheHit);
288 kprintf("Misses: %lld\n", cacheMiss);
289 kprintf("Allocations: %lld\n", cacheAlloc);
290}
Here is the call graph for this function:

◆ REGISTER_DBGCMD()

REGISTER_DBGCMD ( diskcache  ,
"Display disk cache statistics"  ,
Debug_BufCache   
)

◆ TAILQ_HEAD()

static TAILQ_HEAD ( CacheHashTable  ,
DEFINE_SLAB BufCacheEntry 
)
static

BufCache_Init –

Initialize the system buffer cache.

Definition at line 21 of file bufcache.c.

41{
42 int i;
43
45
46 diskBuf = XMem_New();
47 if (!diskBuf)
48 Panic("BufCache: Cannot create XMem region\n");
49
51 Panic("BufCache: Cannot back XMem region\n");
52
53 TAILQ_INIT(&lruList);
54
55 hashTable = PAlloc_AllocPage();
56 if (!hashTable)
57 Panic("BufCache: Cannot allocate hash table\n");
58 for (i = 0; i < HASHTABLEENTRIES; i++) {
59 TAILQ_INIT(&hashTable[i]);
60 }
61
62 Slab_Init(&cacheEntrySlab, "BufCacheEntry Slab", sizeof(BufCacheEntry), 16);
63
64 // Initialize cache
66 for (i = 0; i < CACHESIZE/BLOCKSIZE; i++) {
67 BufCacheEntry *e = BufCacheEntry_Alloc();
68 if (!e) {
69 Panic("BufCache: Cannot allocate cache entry\n");
70 }
71
72 memset(e, 0, sizeof(*e));
73 e->disk = NULL;
74 e->buffer = (void *)(bufBase + BLOCKSIZE * i);
75 TAILQ_INSERT_TAIL(&lruList, e, lruEntry);
76 }
77
78 cacheHit = 0;
79 cacheMiss = 0;
80 cacheAlloc = 0;
81}
XMem * diskBuf
Definition: bufcache.c:19
#define CACHESIZE
void * PAlloc_AllocPage()
Definition: palloc.c:188
void Slab_Init(Slab *slab, const char *name, uintptr_t objsz, uintptr_t align)
#define TAILQ_INIT(head)
Definition: queue.h:597
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
uint64_t uintptr_t
Definition: types.h:16
void Panic(const char *str)
Definition: vgacons.c:164
XMem * XMem_New()
Definition: xmem.c:47
bool XMem_Allocate(XMem *xmem, uintptr_t length)
Definition: xmem.c:92
uintptr_t XMem_GetBase(XMem *xmem)
Definition: xmem.c:80

Variable Documentation

◆ cacheLock

Spinlock cacheLock

Definition at line 18 of file bufcache.c.

◆ diskBuf

XMem* diskBuf

Definition at line 19 of file bufcache.c.