The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/servers/fs/cache2.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 "buf.h"
   20 
   21 #if ENABLE_CACHE2
   22 
   23 #define MAX_BUF2        (256 * sizeof(char *))
   24 
   25 PRIVATE struct buf2 {   /* 2nd level cache per block administration */
   26   block_t b2_blocknr;           /* block number */
   27   dev_t b2_dev;                 /* device number */
   28   u16_t b2_count;               /* count of in-cache block groups */
   29 } buf2[MAX_BUF2];
   30 
   31 PRIVATE unsigned nr_buf2;               /* actual cache size */
   32 PRIVATE unsigned buf2_idx;              /* round-robin reuse index */
   33 
   34 #define hash2(block)    ((unsigned) ((block) & (MAX_BUF2 - 1)))
   35 
   36 /*===========================================================================*
   37  *                              init_cache2                                  *
   38  *===========================================================================*/
   39 PUBLIC void init_cache2(size)
   40 unsigned long size;
   41 {
   42 /* Initialize the second level disk buffer cache of 'size' blocks. */
   43 
   44   nr_buf2 = size > MAX_BUF2 ? MAX_BUF2 : (unsigned) size;
   45 }
   46 
   47 /*===========================================================================*
   48  *                              get_block2                                   *
   49  *===========================================================================*/
   50 PUBLIC int get_block2(bp, only_search)
   51 struct buf *bp;                 /* buffer to get from the 2nd level cache */
   52 int only_search;                /* if NO_READ, do nothing, else act normal */
   53 {
   54 /* Fill a buffer from the 2nd level cache.  Return true iff block acquired. */
   55   unsigned b;
   56   struct buf2 *bp2;
   57 
   58   /* If the block wanted is in the RAM disk then our game is over. */
   59   if (bp->b_dev == DEV_RAM) nr_buf2 = 0;
   60 
   61   /* Cache enabled?  NO_READ?  Any blocks with the same hash key? */
   62   if (nr_buf2 == 0 || only_search == NO_READ
   63                         || buf2[hash2(bp->b_blocknr)].b2_count == 0) return(0);
   64 
   65   /* Search backwards (there may be older versions). */
   66   b = buf2_idx;
   67   for (;;) {
   68         if (b == 0) b = nr_buf2;
   69         bp2 = &buf2[--b];
   70         if (bp2->b2_blocknr == bp->b_blocknr && bp2->b2_dev == bp->b_dev) break;
   71         if (b == buf2_idx) return(0);
   72   }
   73 
   74   /* Block is in the cache, get it. */
   75   if (dev_io(DEV_READ, DEV_RAM, FS_PROC_NR, bp->b_data,
   76                         (off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
   77         return(1);
   78   }
   79   return(0);
   80 }
   81 
   82 /*===========================================================================*
   83  *                              put_block2                                   *
   84  *===========================================================================*/
   85 PUBLIC void put_block2(bp)
   86 struct buf *bp;                 /* buffer to store in the 2nd level cache */
   87 {
   88 /* Store a buffer into the 2nd level cache. */
   89   unsigned b;
   90   struct buf2 *bp2;
   91 
   92   if (nr_buf2 == 0) return;     /* no 2nd level cache */
   93 
   94   b = buf2_idx++;
   95   if (buf2_idx == nr_buf2) buf2_idx = 0;
   96 
   97   bp2 = &buf2[b];
   98 
   99   if (dev_io(DEV_WRITE, DEV_RAM, FS_PROC_NR, bp->b_data,
  100                         (off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
  101         if (bp2->b2_dev != NO_DEV) buf2[hash2(bp2->b2_blocknr)].b2_count--;
  102         bp2->b2_dev = bp->b_dev;
  103         bp2->b2_blocknr = bp->b_blocknr;
  104         buf2[hash2(bp2->b2_blocknr)].b2_count++;
  105   }
  106 }
  107 
  108 /*===========================================================================*
  109  *                              invalidate2                                  *
  110  *===========================================================================*/
  111 PUBLIC void invalidate2(device)
  112 dev_t device;
  113 {
  114 /* Invalidate all blocks from a given device in the 2nd level cache. */
  115   unsigned b;
  116   struct buf2 *bp2;
  117 
  118   for (b = 0; b < nr_buf2; b++) {
  119         bp2 = &buf2[b];
  120         if (bp2->b2_dev == device) {
  121                 bp2->b2_dev = NO_DEV;
  122                 buf2[hash2(bp2->b2_blocknr)].b2_count--;
  123         }
  124   }
  125 }
  126 #endif /* ENABLE_CACHE2 */

Cache object: 3fec03f9e1ff476550fcf38229d5832a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.