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