xref: /minix3/minix/fs/mfs/stats.c (revision 1311233cfbe0c8d7c7a17bdf5274fbcdd76d7702)
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  *===========================================================================*/
count_free_bits(sp,map)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 }
90