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