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