~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/fs/cache2.c


  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.