2 * core/cache.c: A simple LRU-based cache implementation.
14 * Initialize the cache data structres. the _block_size_shift_ specify
15 * the block size, which is 512 byte for FAT fs of the current
16 * implementation since the block(cluster) size in FAT is a bit big.
19 void cache_init(struct device
*dev
, int block_size_shift
)
21 struct cache
*prev
, *cur
;
22 char *data
= dev
->cache_data
;
23 struct cache
*head
, *cache
;
26 dev
->cache_block_size
= 1 << block_size_shift
;
28 if (dev
->cache_size
< dev
->cache_block_size
+ 2*sizeof(struct cache
)) {
29 dev
->cache_head
= NULL
;
30 return; /* Cache unusably small */
33 /* We need one struct cache for the headnode plus one for each block */
35 (dev
->cache_size
- sizeof(struct cache
))/
36 (dev
->cache_block_size
+ sizeof(struct cache
));
38 dev
->cache_head
= head
= (struct cache
*)
39 (data
+ (dev
->cache_entries
<< block_size_shift
));
40 cache
= dev
->cache_head
+ 1; /* First cache descriptor */
42 head
->prev
= &cache
[dev
->cache_entries
-1];
43 head
->next
->prev
= dev
->cache_head
;
49 for (i
= 0; i
< dev
->cache_entries
; i
++) {
55 data
+= dev
->cache_block_size
;
61 * Lock a block permanently in the cache
63 void cache_lock_block(struct cache
*cs
)
65 cs
->prev
->next
= cs
->next
;
66 cs
->next
->prev
= cs
->prev
;
68 cs
->next
= cs
->prev
= NULL
;
72 * Check for a particular BLOCK in the block cache,
73 * and if it is already there, just do nothing and return;
74 * otherwise pick a victim block and update the LRU link.
76 struct cache
*_get_cache_block(struct device
*dev
, block_t block
)
78 struct cache
*head
= dev
->cache_head
;
82 cs
= dev
->cache_head
+ 1;
84 for (i
= 0; i
< dev
->cache_entries
; i
++) {
85 if (cs
->block
== block
)
90 /* Not found, pick a victim */
94 /* Move to the end of the LRU chain, unless the block is already locked */
96 cs
->prev
->next
= cs
->next
;
97 cs
->next
->prev
= cs
->prev
;
99 cs
->prev
= head
->prev
;
100 head
->prev
->next
= cs
;
109 * Check for a particular BLOCK in the block cache,
110 * and if it is already there, just do nothing and return;
111 * otherwise load it from disk and update the LRU link.
112 * Return the data pointer.
114 const void *get_cache(struct device
*dev
, block_t block
)
118 cs
= _get_cache_block(dev
, block
);
119 if (cs
->block
!= block
) {
121 getoneblk(dev
->disk
, cs
->data
, block
, dev
->cache_block_size
);