xref: /minix/minix/fs/mfs/cache.c (revision 433d6423)
1 /* The file system maintains a buffer cache to reduce the number of disk
2  * accesses needed.  Whenever a read or write to the disk is done, a check is
3  * first made to see if the block is in the cache.  This file manages the
4  * cache.
5  *
6  * The entry points into this file are:
7  *   get_block:	  request to fetch a block for reading or writing from cache
8  *   put_block:	  return a block previously requested with get_block
9  *   alloc_zone:  allocate a new zone (to increase the length of a file)
10  *   free_zone:	  release a zone (when a file is removed)
11  *   invalidate:  remove all the cache blocks on some device
12  *
13  * Private functions:
14  *   read_block:    read or write a block from the disk itself
15  */
16 
17 #include "fs.h"
18 #include <minix/u64.h>
19 #include <minix/bdev.h>
20 #include <sys/param.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #include <minix/libminixfs.h>
24 #include <math.h>
25 #include "buf.h"
26 #include "super.h"
27 #include "inode.h"
28 
29 /*===========================================================================*
30  *				alloc_zone				     *
31  *===========================================================================*/
32 zone_t alloc_zone(
33   dev_t dev,			/* device where zone wanted */
34   zone_t z			/* try to allocate new zone near this one */
35 )
36 {
37 /* Allocate a new zone on the indicated device and return its number. */
38 
39   bit_t b, bit;
40   struct super_block *sp;
41   static int print_oos_msg = 1;
42 
43   /* Note that the routine alloc_bit() returns 1 for the lowest possible
44    * zone, which corresponds to sp->s_firstdatazone.  To convert a value
45    * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
46    * stored in the inode, use the formula:
47    *     z = b + sp->s_firstdatazone - 1
48    * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
49    */
50   sp = get_super(dev);
51 
52   /* If z is 0, skip initial part of the map known to be fully in use. */
53   if (z == sp->s_firstdatazone) {
54 	bit = sp->s_zsearch;
55   } else {
56 	bit = (bit_t) (z - (sp->s_firstdatazone - 1));
57   }
58   b = alloc_bit(sp, ZMAP, bit);
59   if (b == NO_BIT) {
60 	err_code = ENOSPC;
61 	if (print_oos_msg)
62 		printf("No space on device %d/%d\n", major(sp->s_dev),
63 			minor(sp->s_dev));
64 	print_oos_msg = 0;	/* Don't repeat message */
65 	return(NO_ZONE);
66   }
67   print_oos_msg = 1;
68   if (z == sp->s_firstdatazone) sp->s_zsearch = b;	/* for next time */
69   return( (zone_t) (sp->s_firstdatazone - 1) + (zone_t) b);
70 }
71 
72 /*===========================================================================*
73  *				free_zone				     *
74  *===========================================================================*/
75 void free_zone(
76   dev_t dev,				/* device where zone located */
77   zone_t numb				/* zone to be returned */
78 )
79 {
80 /* Return a zone. */
81 
82   register struct super_block *sp;
83   bit_t bit;
84 
85   /* Locate the appropriate super_block and return bit. */
86   sp = get_super(dev);
87   if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
88   bit = (bit_t) (numb - (zone_t) (sp->s_firstdatazone - 1));
89   free_bit(sp, ZMAP, bit);
90   if (bit < sp->s_zsearch) sp->s_zsearch = bit;
91 }
92 
93 
94