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