xref: /linux/fs/omfs/bitmap.c (revision 01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba)
136cc410aSBob Copeland #include <linux/kernel.h>
236cc410aSBob Copeland #include <linux/fs.h>
336cc410aSBob Copeland #include <linux/buffer_head.h>
436cc410aSBob Copeland #include <asm/div64.h>
536cc410aSBob Copeland #include "omfs.h"
636cc410aSBob Copeland 
736cc410aSBob Copeland unsigned long omfs_count_free(struct super_block *sb)
836cc410aSBob Copeland {
936cc410aSBob Copeland 	unsigned int i;
1036cc410aSBob Copeland 	unsigned long sum = 0;
1136cc410aSBob Copeland 	struct omfs_sb_info *sbi = OMFS_SB(sb);
1236cc410aSBob Copeland 	int nbits = sb->s_blocksize * 8;
1336cc410aSBob Copeland 
1436cc410aSBob Copeland 	for (i = 0; i < sbi->s_imap_size; i++)
1536cc410aSBob Copeland 		sum += nbits - bitmap_weight(sbi->s_imap[i], nbits);
1636cc410aSBob Copeland 
1736cc410aSBob Copeland 	return sum;
1836cc410aSBob Copeland }
1936cc410aSBob Copeland 
2036cc410aSBob Copeland /*
2136cc410aSBob Copeland  *  Counts the run of zero bits starting at bit up to max.
2236cc410aSBob Copeland  *  It handles the case where a run might spill over a buffer.
2336cc410aSBob Copeland  *  Called with bitmap lock.
2436cc410aSBob Copeland  */
2536cc410aSBob Copeland static int count_run(unsigned long **addr, int nbits,
2636cc410aSBob Copeland 		int addrlen, int bit, int max)
2736cc410aSBob Copeland {
2836cc410aSBob Copeland 	int count = 0;
2936cc410aSBob Copeland 	int x;
3036cc410aSBob Copeland 
3136cc410aSBob Copeland 	for (; addrlen > 0; addrlen--, addr++) {
3236cc410aSBob Copeland 		x = find_next_bit(*addr, nbits, bit);
3336cc410aSBob Copeland 		count += x - bit;
3436cc410aSBob Copeland 
3536cc410aSBob Copeland 		if (x < nbits || count > max)
3636cc410aSBob Copeland 			return min(count, max);
3736cc410aSBob Copeland 
3836cc410aSBob Copeland 		bit = 0;
3936cc410aSBob Copeland 	}
4036cc410aSBob Copeland 	return min(count, max);
4136cc410aSBob Copeland }
4236cc410aSBob Copeland 
4336cc410aSBob Copeland /*
4436cc410aSBob Copeland  * Sets or clears the run of count bits starting with bit.
4536cc410aSBob Copeland  * Called with bitmap lock.
4636cc410aSBob Copeland  */
4736cc410aSBob Copeland static int set_run(struct super_block *sb, int map,
4836cc410aSBob Copeland 		int nbits, int bit, int count, int set)
4936cc410aSBob Copeland {
5036cc410aSBob Copeland 	int i;
5136cc410aSBob Copeland 	int err;
5236cc410aSBob Copeland 	struct buffer_head *bh;
5336cc410aSBob Copeland 	struct omfs_sb_info *sbi = OMFS_SB(sb);
5436cc410aSBob Copeland 
5536cc410aSBob Copeland  	err = -ENOMEM;
5636cc410aSBob Copeland 	bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
5736cc410aSBob Copeland 	if (!bh)
5836cc410aSBob Copeland 		goto out;
5936cc410aSBob Copeland 
6036cc410aSBob Copeland 	for (i = 0; i < count; i++, bit++) {
6136cc410aSBob Copeland 		if (bit >= nbits) {
6236cc410aSBob Copeland 			bit = 0;
6336cc410aSBob Copeland 			map++;
6436cc410aSBob Copeland 
6536cc410aSBob Copeland 			mark_buffer_dirty(bh);
6636cc410aSBob Copeland 			brelse(bh);
6736cc410aSBob Copeland 			bh = sb_bread(sb,
6836cc410aSBob Copeland 				clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
6936cc410aSBob Copeland 			if (!bh)
7036cc410aSBob Copeland 				goto out;
7136cc410aSBob Copeland 		}
7236cc410aSBob Copeland 		if (set) {
7336cc410aSBob Copeland 			set_bit(bit, sbi->s_imap[map]);
74d406f66dSHarvey Harrison 			set_bit(bit, (unsigned long *)bh->b_data);
7536cc410aSBob Copeland 		} else {
7636cc410aSBob Copeland 			clear_bit(bit, sbi->s_imap[map]);
77d406f66dSHarvey Harrison 			clear_bit(bit, (unsigned long *)bh->b_data);
7836cc410aSBob Copeland 		}
7936cc410aSBob Copeland 	}
8036cc410aSBob Copeland 	mark_buffer_dirty(bh);
8136cc410aSBob Copeland 	brelse(bh);
8236cc410aSBob Copeland 	err = 0;
8336cc410aSBob Copeland out:
8436cc410aSBob Copeland 	return err;
8536cc410aSBob Copeland }
8636cc410aSBob Copeland 
8736cc410aSBob Copeland /*
88af901ca1SAndré Goddard Rosa  * Tries to allocate exactly one block.  Returns true if successful.
8936cc410aSBob Copeland  */
9036cc410aSBob Copeland int omfs_allocate_block(struct super_block *sb, u64 block)
9136cc410aSBob Copeland {
9236cc410aSBob Copeland 	struct buffer_head *bh;
9336cc410aSBob Copeland 	struct omfs_sb_info *sbi = OMFS_SB(sb);
9436cc410aSBob Copeland 	int bits_per_entry = 8 * sb->s_blocksize;
959419fc1cSBob Copeland 	unsigned int map, bit;
9636cc410aSBob Copeland 	int ret = 0;
9736cc410aSBob Copeland 	u64 tmp;
9836cc410aSBob Copeland 
9936cc410aSBob Copeland 	tmp = block;
10036cc410aSBob Copeland 	bit = do_div(tmp, bits_per_entry);
10136cc410aSBob Copeland 	map = tmp;
10236cc410aSBob Copeland 
10336cc410aSBob Copeland 	mutex_lock(&sbi->s_bitmap_lock);
10436cc410aSBob Copeland 	if (map >= sbi->s_imap_size || test_and_set_bit(bit, sbi->s_imap[map]))
10536cc410aSBob Copeland 		goto out;
10636cc410aSBob Copeland 
10736cc410aSBob Copeland 	if (sbi->s_bitmap_ino > 0) {
10836cc410aSBob Copeland 		bh = sb_bread(sb, clus_to_blk(sbi, sbi->s_bitmap_ino) + map);
10936cc410aSBob Copeland 		if (!bh)
11036cc410aSBob Copeland 			goto out;
11136cc410aSBob Copeland 
112d406f66dSHarvey Harrison 		set_bit(bit, (unsigned long *)bh->b_data);
11336cc410aSBob Copeland 		mark_buffer_dirty(bh);
11436cc410aSBob Copeland 		brelse(bh);
11536cc410aSBob Copeland 	}
11636cc410aSBob Copeland 	ret = 1;
11736cc410aSBob Copeland out:
11836cc410aSBob Copeland 	mutex_unlock(&sbi->s_bitmap_lock);
11936cc410aSBob Copeland 	return ret;
12036cc410aSBob Copeland }
12136cc410aSBob Copeland 
12236cc410aSBob Copeland 
12336cc410aSBob Copeland /*
12436cc410aSBob Copeland  *  Tries to allocate a set of blocks.	The request size depends on the
12536cc410aSBob Copeland  *  type: for inodes, we must allocate sbi->s_mirrors blocks, and for file
12636cc410aSBob Copeland  *  blocks, we try to allocate sbi->s_clustersize, but can always get away
12736cc410aSBob Copeland  *  with just one block.
12836cc410aSBob Copeland  */
12936cc410aSBob Copeland int omfs_allocate_range(struct super_block *sb,
13036cc410aSBob Copeland 			int min_request,
13136cc410aSBob Copeland 			int max_request,
13236cc410aSBob Copeland 			u64 *return_block,
13336cc410aSBob Copeland 			int *return_size)
13436cc410aSBob Copeland {
13536cc410aSBob Copeland 	struct omfs_sb_info *sbi = OMFS_SB(sb);
13636cc410aSBob Copeland 	int bits_per_entry = 8 * sb->s_blocksize;
13736cc410aSBob Copeland 	int ret = 0;
13836cc410aSBob Copeland 	int i, run, bit;
13936cc410aSBob Copeland 
14036cc410aSBob Copeland 	mutex_lock(&sbi->s_bitmap_lock);
14136cc410aSBob Copeland 	for (i = 0; i < sbi->s_imap_size; i++) {
14236cc410aSBob Copeland 		bit = 0;
14336cc410aSBob Copeland 		while (bit < bits_per_entry) {
14436cc410aSBob Copeland 			bit = find_next_zero_bit(sbi->s_imap[i], bits_per_entry,
14536cc410aSBob Copeland 				bit);
14636cc410aSBob Copeland 
14736cc410aSBob Copeland 			if (bit == bits_per_entry)
14836cc410aSBob Copeland 				break;
14936cc410aSBob Copeland 
15036cc410aSBob Copeland 			run = count_run(&sbi->s_imap[i], bits_per_entry,
15136cc410aSBob Copeland 				sbi->s_imap_size-i, bit, max_request);
15236cc410aSBob Copeland 
15336cc410aSBob Copeland 			if (run >= min_request)
15436cc410aSBob Copeland 				goto found;
15536cc410aSBob Copeland 			bit += run;
15636cc410aSBob Copeland 		}
15736cc410aSBob Copeland 	}
15836cc410aSBob Copeland 	ret = -ENOSPC;
15936cc410aSBob Copeland 	goto out;
16036cc410aSBob Copeland 
16136cc410aSBob Copeland found:
1625a6b2b36SBob Copeland 	*return_block = (u64) i * bits_per_entry + bit;
16336cc410aSBob Copeland 	*return_size = run;
16436cc410aSBob Copeland 	ret = set_run(sb, i, bits_per_entry, bit, run, 1);
16536cc410aSBob Copeland 
16636cc410aSBob Copeland out:
16736cc410aSBob Copeland 	mutex_unlock(&sbi->s_bitmap_lock);
16836cc410aSBob Copeland 	return ret;
16936cc410aSBob Copeland }
17036cc410aSBob Copeland 
17136cc410aSBob Copeland /*
17236cc410aSBob Copeland  * Clears count bits starting at a given block.
17336cc410aSBob Copeland  */
17436cc410aSBob Copeland int omfs_clear_range(struct super_block *sb, u64 block, int count)
17536cc410aSBob Copeland {
17636cc410aSBob Copeland 	struct omfs_sb_info *sbi = OMFS_SB(sb);
17736cc410aSBob Copeland 	int bits_per_entry = 8 * sb->s_blocksize;
17836cc410aSBob Copeland 	u64 tmp;
1799419fc1cSBob Copeland 	unsigned int map, bit;
1809419fc1cSBob Copeland 	int ret;
18136cc410aSBob Copeland 
18236cc410aSBob Copeland 	tmp = block;
18336cc410aSBob Copeland 	bit = do_div(tmp, bits_per_entry);
18436cc410aSBob Copeland 	map = tmp;
18536cc410aSBob Copeland 
18636cc410aSBob Copeland 	if (map >= sbi->s_imap_size)
18736cc410aSBob Copeland 		return 0;
18836cc410aSBob Copeland 
18936cc410aSBob Copeland 	mutex_lock(&sbi->s_bitmap_lock);
19036cc410aSBob Copeland 	ret = set_run(sb, map, bits_per_entry, bit, count, 0);
19136cc410aSBob Copeland 	mutex_unlock(&sbi->s_bitmap_lock);
19236cc410aSBob Copeland 	return ret;
19336cc410aSBob Copeland }
194