1 #include "fs.h" 2 #include <string.h> 3 #include <minix/com.h> 4 #include <assert.h> 5 #include <minix/u64.h> 6 #include "buf.h" 7 #include "inode.h" 8 #include "super.h" 9 #include "const.h" 10 11 /*===========================================================================* 12 * count_free_bits * 13 *===========================================================================*/ 14 bit_t count_free_bits(sp, map) 15 struct super_block *sp; /* the filesystem to allocate from */ 16 int map; /* IMAP (inode map) or ZMAP (zone map) */ 17 { 18 /* Allocate a bit from a bit map and return its bit number. */ 19 block_t start_block; /* first bit block */ 20 block_t block; 21 bit_t map_bits; /* how many bits are there in the bit map? */ 22 short bit_blocks; /* how many blocks are there in the bit map? */ 23 bit_t origin; /* number of bit to start searching at */ 24 unsigned word, bcount; 25 struct buf *bp; 26 bitchunk_t *wptr, *wlim, k; 27 bit_t i, b; 28 bit_t free_bits; 29 30 assert(sp != NULL); 31 32 if (map == IMAP) { 33 start_block = START_BLOCK; 34 map_bits = (bit_t) (sp->s_ninodes + 1); 35 bit_blocks = sp->s_imap_blocks; 36 origin = sp->s_isearch; 37 } else { 38 start_block = START_BLOCK + sp->s_imap_blocks; 39 map_bits = (bit_t) (sp->s_zones - (sp->s_firstdatazone - 1)); 40 bit_blocks = sp->s_zmap_blocks; 41 origin = sp->s_zsearch; 42 } 43 44 /* Figure out where to start the bit search (depends on 'origin'). */ 45 if (origin >= map_bits) origin = 0; /* for robustness */ 46 free_bits = 0; 47 48 /* Locate the starting place. */ 49 block = (block_t) (origin / FS_BITS_PER_BLOCK(sp->s_block_size)); 50 word = (origin % FS_BITS_PER_BLOCK(sp->s_block_size)) / FS_BITCHUNK_BITS; 51 52 /* Iterate over all blocks plus one, because we start in the middle. */ 53 bcount = bit_blocks; 54 do { 55 bp = get_block(sp->s_dev, start_block + block, NORMAL); 56 assert(bp); 57 wlim = &b_bitmap(bp)[FS_BITMAP_CHUNKS(sp->s_block_size)]; 58 59 /* Iterate over the words in block. */ 60 for (wptr = &b_bitmap(bp)[word]; wptr < wlim; wptr++) { 61 62 /* Does this word contain a free bit? */ 63 if (*wptr == (bitchunk_t) ~0) continue; 64 65 k = (bitchunk_t) conv4(sp->s_native, (int) *wptr); 66 67 for (i = 0; i < 8*sizeof(k); ++i) { 68 /* Bit number from the start of the bit map. */ 69 b = ((bit_t) block * FS_BITS_PER_BLOCK(sp->s_block_size)) 70 + (wptr - &b_bitmap(bp)[0]) * FS_BITCHUNK_BITS 71 + i; 72 73 /* Don't count bits beyond the end of the map. */ 74 if (b >= map_bits) { 75 break; 76 } 77 if ((k & (1 << i)) == 0) { 78 free_bits++; 79 } 80 } 81 82 if (b >= map_bits) break; 83 } 84 put_block(bp, MAP_BLOCK); 85 ++block; 86 word = 0; 87 } while (--bcount > 0); 88 return free_bits; /* no bit could be allocated */ 89 } 90 91 92 /*===========================================================================* 93 * blockstats * 94 *===========================================================================*/ 95 void fs_blockstats(u64_t *blocks, u64_t *free, u64_t *used) 96 { 97 struct super_block *sp; 98 99 sp = get_super(fs_dev); 100 101 assert(sp); 102 assert(!sp->s_log_zone_size); 103 104 *blocks = sp->s_zones; 105 *used = get_used_blocks(sp); 106 *free = *blocks - *used; 107 108 return; 109 } 110