xref: /minix3/minix/fs/mfs/cache.c (revision 4472b590c74fed661146a925d8dff2ed1b04256e)
1433d6423SLionel Sambuc /* The file system maintains a buffer cache to reduce the number of disk
2433d6423SLionel Sambuc  * accesses needed.  Whenever a read or write to the disk is done, a check is
36c46a77dSDavid van Moolenbroek  * first made to see if the block is in the cache.  This file contains some
46c46a77dSDavid van Moolenbroek  * related routines, but the cache is now in libminixfs.
5433d6423SLionel Sambuc  */
6433d6423SLionel Sambuc 
7433d6423SLionel Sambuc #include "fs.h"
8433d6423SLionel Sambuc #include <minix/u64.h>
9433d6423SLionel Sambuc #include <minix/bdev.h>
10433d6423SLionel Sambuc #include <sys/param.h>
11433d6423SLionel Sambuc #include <stdlib.h>
12433d6423SLionel Sambuc #include <assert.h>
13433d6423SLionel Sambuc #include <minix/libminixfs.h>
14433d6423SLionel Sambuc #include <math.h>
15433d6423SLionel Sambuc #include "buf.h"
16433d6423SLionel Sambuc #include "super.h"
17433d6423SLionel Sambuc #include "inode.h"
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc /*===========================================================================*
206c46a77dSDavid van Moolenbroek  *				get_block				     *
216c46a77dSDavid van Moolenbroek  *===========================================================================*/
get_block(dev_t dev,block_t block,int how)226c46a77dSDavid van Moolenbroek struct buf *get_block(dev_t dev, block_t block, int how)
236c46a77dSDavid van Moolenbroek {
246c46a77dSDavid van Moolenbroek /* Wrapper routine for lmfs_get_block(). This MFS implementation does not deal
256c46a77dSDavid van Moolenbroek  * well with block read errors pretty much anywhere. To prevent corruption due
266c46a77dSDavid van Moolenbroek  * to unchecked error conditions, we panic upon an I/O failure here.
276c46a77dSDavid van Moolenbroek  */
286c46a77dSDavid van Moolenbroek   struct buf *bp;
296c46a77dSDavid van Moolenbroek   int r;
306c46a77dSDavid van Moolenbroek 
316c46a77dSDavid van Moolenbroek   if ((r = lmfs_get_block(&bp, dev, block, how)) != OK && r != ENOENT)
326c46a77dSDavid van Moolenbroek 	panic("MFS: error getting block (%llu,%u): %d", dev, block, r);
336c46a77dSDavid van Moolenbroek 
346c46a77dSDavid van Moolenbroek   assert(r == OK || how == PEEK);
356c46a77dSDavid van Moolenbroek 
366c46a77dSDavid van Moolenbroek   return (r == OK) ? bp : NULL;
376c46a77dSDavid van Moolenbroek }
386c46a77dSDavid van Moolenbroek 
396c46a77dSDavid van Moolenbroek /*===========================================================================*
40433d6423SLionel Sambuc  *				alloc_zone				     *
41433d6423SLionel Sambuc  *===========================================================================*/
alloc_zone(dev_t dev,zone_t z)42433d6423SLionel Sambuc zone_t alloc_zone(
43433d6423SLionel Sambuc   dev_t dev,			/* device where zone wanted */
44433d6423SLionel Sambuc   zone_t z			/* try to allocate new zone near this one */
45433d6423SLionel Sambuc )
46433d6423SLionel Sambuc {
47433d6423SLionel Sambuc /* Allocate a new zone on the indicated device and return its number. */
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc   bit_t b, bit;
50433d6423SLionel Sambuc   struct super_block *sp;
51433d6423SLionel Sambuc   static int print_oos_msg = 1;
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc   /* Note that the routine alloc_bit() returns 1 for the lowest possible
54433d6423SLionel Sambuc    * zone, which corresponds to sp->s_firstdatazone.  To convert a value
55433d6423SLionel Sambuc    * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
56433d6423SLionel Sambuc    * stored in the inode, use the formula:
57433d6423SLionel Sambuc    *     z = b + sp->s_firstdatazone - 1
58433d6423SLionel Sambuc    * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
59433d6423SLionel Sambuc    */
60*4472b590SDavid van Moolenbroek   sp = &superblock;
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc   /* If z is 0, skip initial part of the map known to be fully in use. */
63433d6423SLionel Sambuc   if (z == sp->s_firstdatazone) {
64433d6423SLionel Sambuc 	bit = sp->s_zsearch;
65433d6423SLionel Sambuc   } else {
66433d6423SLionel Sambuc 	bit = (bit_t) (z - (sp->s_firstdatazone - 1));
67433d6423SLionel Sambuc   }
68433d6423SLionel Sambuc   b = alloc_bit(sp, ZMAP, bit);
69433d6423SLionel Sambuc   if (b == NO_BIT) {
70433d6423SLionel Sambuc 	err_code = ENOSPC;
71433d6423SLionel Sambuc 	if (print_oos_msg)
72433d6423SLionel Sambuc 		printf("No space on device %d/%d\n", major(sp->s_dev),
73433d6423SLionel Sambuc 			minor(sp->s_dev));
74433d6423SLionel Sambuc 	print_oos_msg = 0;	/* Don't repeat message */
75433d6423SLionel Sambuc 	return(NO_ZONE);
76433d6423SLionel Sambuc   }
77433d6423SLionel Sambuc   print_oos_msg = 1;
78433d6423SLionel Sambuc   if (z == sp->s_firstdatazone) sp->s_zsearch = b;	/* for next time */
79433d6423SLionel Sambuc   return( (zone_t) (sp->s_firstdatazone - 1) + (zone_t) b);
80433d6423SLionel Sambuc }
81433d6423SLionel Sambuc 
82433d6423SLionel Sambuc /*===========================================================================*
83433d6423SLionel Sambuc  *				free_zone				     *
84433d6423SLionel Sambuc  *===========================================================================*/
free_zone(dev_t dev,zone_t numb)85433d6423SLionel Sambuc void free_zone(
86433d6423SLionel Sambuc   dev_t dev,				/* device where zone located */
87433d6423SLionel Sambuc   zone_t numb				/* zone to be returned */
88433d6423SLionel Sambuc )
89433d6423SLionel Sambuc {
90433d6423SLionel Sambuc /* Return a zone. */
91433d6423SLionel Sambuc 
92433d6423SLionel Sambuc   register struct super_block *sp;
93433d6423SLionel Sambuc   bit_t bit;
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc   /* Locate the appropriate super_block and return bit. */
96*4472b590SDavid van Moolenbroek   sp = &superblock;
97433d6423SLionel Sambuc   if (numb < sp->s_firstdatazone || numb >= sp->s_zones) return;
98433d6423SLionel Sambuc   bit = (bit_t) (numb - (zone_t) (sp->s_firstdatazone - 1));
99433d6423SLionel Sambuc   free_bit(sp, ZMAP, bit);
100433d6423SLionel Sambuc   if (bit < sp->s_zsearch) sp->s_zsearch = bit;
101e94f856bSDavid van Moolenbroek 
102e94f856bSDavid van Moolenbroek   /* Also tell libminixfs, so that 1) if it has a block for this bit, it can
103e94f856bSDavid van Moolenbroek    * mark it as clean, thus reducing useless writes, and 2) it can tell VM that
104e94f856bSDavid van Moolenbroek    * any previous inode association is to be broken for this block, so that the
105e94f856bSDavid van Moolenbroek    * block will not be mapped in erroneously later on.
106e94f856bSDavid van Moolenbroek    */
107e94f856bSDavid van Moolenbroek   assert(sp->s_log_zone_size == 0); /* otherwise we need a loop here.. */
108e94f856bSDavid van Moolenbroek   lmfs_free_block(dev, (block_t)numb);
109433d6423SLionel Sambuc }
110