1433d6423SLionel Sambuc #include "fs.h" 2433d6423SLionel Sambuc #include <string.h> 3433d6423SLionel Sambuc #include <minix/com.h> 4433d6423SLionel Sambuc #include <assert.h> 5433d6423SLionel Sambuc #include <minix/u64.h> 6433d6423SLionel Sambuc #include "buf.h" 7433d6423SLionel Sambuc #include "inode.h" 8433d6423SLionel Sambuc #include "super.h" 9433d6423SLionel Sambuc #include "const.h" 10433d6423SLionel Sambuc 11433d6423SLionel Sambuc /*===========================================================================* 12433d6423SLionel Sambuc * count_free_bits * 13433d6423SLionel Sambuc *===========================================================================*/ 14433d6423SLionel Sambuc bit_t count_free_bits(sp, map) 15433d6423SLionel Sambuc struct super_block *sp; /* the filesystem to allocate from */ 16433d6423SLionel Sambuc int map; /* IMAP (inode map) or ZMAP (zone map) */ 17433d6423SLionel Sambuc { 18433d6423SLionel Sambuc /* Allocate a bit from a bit map and return its bit number. */ 19433d6423SLionel Sambuc block_t start_block; /* first bit block */ 20433d6423SLionel Sambuc block_t block; 21433d6423SLionel Sambuc bit_t map_bits; /* how many bits are there in the bit map? */ 22433d6423SLionel Sambuc short bit_blocks; /* how many blocks are there in the bit map? */ 23433d6423SLionel Sambuc bit_t origin; /* number of bit to start searching at */ 24433d6423SLionel Sambuc unsigned word, bcount; 25433d6423SLionel Sambuc struct buf *bp; 26433d6423SLionel Sambuc bitchunk_t *wptr, *wlim, k; 27433d6423SLionel Sambuc bit_t i, b; 28433d6423SLionel Sambuc bit_t free_bits; 29433d6423SLionel Sambuc 30433d6423SLionel Sambuc assert(sp != NULL); 31433d6423SLionel Sambuc 32433d6423SLionel Sambuc if (map == IMAP) { 33433d6423SLionel Sambuc start_block = START_BLOCK; 34433d6423SLionel Sambuc map_bits = (bit_t) (sp->s_ninodes + 1); 35433d6423SLionel Sambuc bit_blocks = sp->s_imap_blocks; 36433d6423SLionel Sambuc origin = sp->s_isearch; 37433d6423SLionel Sambuc } else { 38433d6423SLionel Sambuc start_block = START_BLOCK + sp->s_imap_blocks; 39433d6423SLionel Sambuc map_bits = (bit_t) (sp->s_zones - (sp->s_firstdatazone - 1)); 40433d6423SLionel Sambuc bit_blocks = sp->s_zmap_blocks; 41433d6423SLionel Sambuc origin = sp->s_zsearch; 42433d6423SLionel Sambuc } 43433d6423SLionel Sambuc 44433d6423SLionel Sambuc /* Figure out where to start the bit search (depends on 'origin'). */ 45433d6423SLionel Sambuc if (origin >= map_bits) origin = 0; /* for robustness */ 46433d6423SLionel Sambuc free_bits = 0; 47433d6423SLionel Sambuc 48433d6423SLionel Sambuc /* Locate the starting place. */ 49433d6423SLionel Sambuc block = (block_t) (origin / FS_BITS_PER_BLOCK(sp->s_block_size)); 50433d6423SLionel Sambuc word = (origin % FS_BITS_PER_BLOCK(sp->s_block_size)) / FS_BITCHUNK_BITS; 51433d6423SLionel Sambuc 52433d6423SLionel Sambuc /* Iterate over all blocks plus one, because we start in the middle. */ 53433d6423SLionel Sambuc bcount = bit_blocks; 54433d6423SLionel Sambuc do { 55433d6423SLionel Sambuc bp = get_block(sp->s_dev, start_block + block, NORMAL); 56433d6423SLionel Sambuc assert(bp); 57433d6423SLionel Sambuc wlim = &b_bitmap(bp)[FS_BITMAP_CHUNKS(sp->s_block_size)]; 58433d6423SLionel Sambuc 59433d6423SLionel Sambuc /* Iterate over the words in block. */ 60433d6423SLionel Sambuc for (wptr = &b_bitmap(bp)[word]; wptr < wlim; wptr++) { 61433d6423SLionel Sambuc 62433d6423SLionel Sambuc /* Does this word contain a free bit? */ 63433d6423SLionel Sambuc if (*wptr == (bitchunk_t) ~0) continue; 64433d6423SLionel Sambuc 65433d6423SLionel Sambuc k = (bitchunk_t) conv4(sp->s_native, (int) *wptr); 66433d6423SLionel Sambuc 67433d6423SLionel Sambuc for (i = 0; i < 8*sizeof(k); ++i) { 68433d6423SLionel Sambuc /* Bit number from the start of the bit map. */ 69433d6423SLionel Sambuc b = ((bit_t) block * FS_BITS_PER_BLOCK(sp->s_block_size)) 70433d6423SLionel Sambuc + (wptr - &b_bitmap(bp)[0]) * FS_BITCHUNK_BITS 71433d6423SLionel Sambuc + i; 72433d6423SLionel Sambuc 73433d6423SLionel Sambuc /* Don't count bits beyond the end of the map. */ 74433d6423SLionel Sambuc if (b >= map_bits) { 75433d6423SLionel Sambuc break; 76433d6423SLionel Sambuc } 77433d6423SLionel Sambuc if ((k & (1 << i)) == 0) { 78433d6423SLionel Sambuc free_bits++; 79433d6423SLionel Sambuc } 80433d6423SLionel Sambuc } 81433d6423SLionel Sambuc 82433d6423SLionel Sambuc if (b >= map_bits) break; 83433d6423SLionel Sambuc } 84*0314acfbSDavid van Moolenbroek put_block(bp); 85433d6423SLionel Sambuc ++block; 86433d6423SLionel Sambuc word = 0; 87433d6423SLionel Sambuc } while (--bcount > 0); 88*0314acfbSDavid van Moolenbroek return free_bits; 89433d6423SLionel Sambuc } 90433d6423SLionel Sambuc 91433d6423SLionel Sambuc 92433d6423SLionel Sambuc /*===========================================================================* 93433d6423SLionel Sambuc * blockstats * 94433d6423SLionel Sambuc *===========================================================================*/ 95*0314acfbSDavid van Moolenbroek void fs_blockstats(u64_t *blocks, u64_t *free) 96433d6423SLionel Sambuc { 97433d6423SLionel Sambuc struct super_block *sp; 98433d6423SLionel Sambuc 99433d6423SLionel Sambuc sp = get_super(fs_dev); 100433d6423SLionel Sambuc 101433d6423SLionel Sambuc assert(sp); 102433d6423SLionel Sambuc assert(!sp->s_log_zone_size); 103433d6423SLionel Sambuc 104433d6423SLionel Sambuc *blocks = sp->s_zones; 105*0314acfbSDavid van Moolenbroek *free = *blocks - get_used_blocks(sp); 106433d6423SLionel Sambuc 107433d6423SLionel Sambuc return; 108433d6423SLionel Sambuc } 109