1 /* Second level block cache to supplement the file system cache. The block
2 * cache of a 16-bit Minix system is very small, too small to prevent trashing.
3 * A generic 32-bit system also doesn't have a very large cache to allow it
4 * to run on systems with little memory. On a system with lots of memory one
5 * can use the RAM disk as a read-only second level cache. Any blocks pushed
6 * out of the primary cache are cached on the RAM disk. This code manages the
7 * second level cache. The cache is a simple FIFO where old blocks are put
8 * into and drop out at the other end. Must be searched backwards.
9 *
10 * The entry points into this file are:
11 * init_cache2: initialize the second level cache
12 * get_block2: get a block from the 2nd level cache
13 * put_block2: store a block in the 2nd level cache
14 * invalidate2: remove all the cache blocks on some device
15 */
16
17 #include "fs.h"
18 #include <minix/com.h>
19 #include <minix/boot.h>
20 #include "buf.h"
21
22 #if ENABLE_CACHE2
23
24 #define MAX_BUF2 (256 * sizeof(char *))
25
26 PRIVATE struct buf2 { /* 2nd level cache per block administration */
27 block_t b2_blocknr; /* block number */
28 dev_t b2_dev; /* device number */
29 u16_t b2_count; /* count of in-cache block groups */
30 } buf2[MAX_BUF2];
31
32 PRIVATE unsigned nr_buf2; /* actual cache size */
33 PRIVATE unsigned buf2_idx; /* round-robin reuse index */
34
35 #define hash2(block) ((unsigned) ((block) & (MAX_BUF2 - 1)))
36
37
38 /*===========================================================================*
39 * init_cache2 *
40 *===========================================================================*/
41 PUBLIC void init_cache2(size)
42 unsigned long size;
43 {
44 /* Initialize the second level disk buffer cache of 'size' blocks. */
45
46 nr_buf2 = size > MAX_BUF2 ? MAX_BUF2 : (unsigned) size;
47 }
48
49
50 /*===========================================================================*
51 * get_block2 *
52 *===========================================================================*/
53 PUBLIC int get_block2(bp, only_search)
54 struct buf *bp; /* buffer to get from the 2nd level cache */
55 int only_search; /* if NO_READ, do nothing, else act normal */
56 {
57 /* Fill a buffer from the 2nd level cache. Return true iff block acquired. */
58 unsigned b;
59 struct buf2 *bp2;
60
61 /* If the block wanted is in the RAM disk then our game is over. */
62 if (bp->b_dev == DEV_RAM) nr_buf2 = 0;
63
64 /* Cache enabled? NO_READ? Any blocks with the same hash key? */
65 if (nr_buf2 == 0 || only_search == NO_READ
66 || buf2[hash2(bp->b_blocknr)].b2_count == 0) return(0);
67
68 /* Search backwards (there may be older versions). */
69 b = buf2_idx;
70 for (;;) {
71 if (b == 0) b = nr_buf2;
72 bp2 = &buf2[--b];
73 if (bp2->b2_blocknr == bp->b_blocknr && bp2->b2_dev == bp->b_dev) break;
74 if (b == buf2_idx) return(0);
75 }
76
77 /* Block is in the cache, get it. */
78 if (dev_io(DEV_READ, 0, DEV_RAM, (off_t) b * BLOCK_SIZE, BLOCK_SIZE,
79 FS_PROC_NR, bp->b_data) == BLOCK_SIZE) {
80 return(1);
81 }
82 return(0);
83 }
84
85
86 /*===========================================================================*
87 * put_block2 *
88 *===========================================================================*/
89 PUBLIC void put_block2(bp)
90 struct buf *bp; /* buffer to store in the 2nd level cache */
91 {
92 /* Store a buffer into the 2nd level cache. */
93 unsigned b;
94 struct buf2 *bp2;
95
96 if (nr_buf2 == 0) return; /* no 2nd level cache */
97
98 b = buf2_idx++;
99 if (buf2_idx == nr_buf2) buf2_idx = 0;
100
101 bp2 = &buf2[b];
102
103 if (dev_io(DEV_WRITE, 0, DEV_RAM, (off_t) b * BLOCK_SIZE, BLOCK_SIZE,
104 FS_PROC_NR, bp->b_data) == BLOCK_SIZE) {
105 if (bp2->b2_dev != NO_DEV) buf2[hash2(bp2->b2_blocknr)].b2_count--;
106 bp2->b2_dev = bp->b_dev;
107 bp2->b2_blocknr = bp->b_blocknr;
108 buf2[hash2(bp2->b2_blocknr)].b2_count++;
109 }
110 }
111
112
113 /*===========================================================================*
114 * invalidate2 *
115 *===========================================================================*/
116 PUBLIC void invalidate2(device)
117 dev_t device;
118 {
119 /* Invalidate all blocks from a given device in the 2nd level cache. */
120 unsigned b;
121 struct buf2 *bp2;
122
123 for (b = 0; b < nr_buf2; b++) {
124 bp2 = &buf2[b];
125 if (bp2->b2_dev == device) {
126 bp2->b2_dev = NO_DEV;
127 buf2[hash2(bp2->b2_blocknr)].b2_count--;
128 }
129 }
130 }
131 #endif /* ENABLE_CACHE2 */
132
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.