|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | *  linux/fs/affs/bitmap.c | 
|  | * | 
|  | *  (c) 1996 Hans-Joachim Widmaier | 
|  | * | 
|  | *  bitmap.c contains the code that handles all bitmap related stuff - | 
|  | *  block allocation, deallocation, calculation of free space. | 
|  | */ | 
|  |  | 
|  | #include <linux/slab.h> | 
|  | #include "affs.h" | 
|  |  | 
|  | u32 | 
|  | affs_count_free_blocks(struct super_block *sb) | 
|  | { | 
|  | struct affs_bm_info *bm; | 
|  | u32 free; | 
|  | int i; | 
|  |  | 
|  | pr_debug("%s()\n", __func__); | 
|  |  | 
|  | if (sb_rdonly(sb)) | 
|  | return 0; | 
|  |  | 
|  | mutex_lock(&AFFS_SB(sb)->s_bmlock); | 
|  |  | 
|  | bm = AFFS_SB(sb)->s_bitmap; | 
|  | free = 0; | 
|  | for (i = AFFS_SB(sb)->s_bmap_count; i > 0; bm++, i--) | 
|  | free += bm->bm_free; | 
|  |  | 
|  | mutex_unlock(&AFFS_SB(sb)->s_bmlock); | 
|  |  | 
|  | return free; | 
|  | } | 
|  |  | 
|  | void | 
|  | affs_free_block(struct super_block *sb, u32 block) | 
|  | { | 
|  | struct affs_sb_info *sbi = AFFS_SB(sb); | 
|  | struct affs_bm_info *bm; | 
|  | struct buffer_head *bh; | 
|  | u32 blk, bmap, bit, mask, tmp; | 
|  | __be32 *data; | 
|  |  | 
|  | pr_debug("%s(%u)\n", __func__, block); | 
|  |  | 
|  | if (block > sbi->s_partition_size) | 
|  | goto err_range; | 
|  |  | 
|  | blk     = block - sbi->s_reserved; | 
|  | bmap    = blk / sbi->s_bmap_bits; | 
|  | bit     = blk % sbi->s_bmap_bits; | 
|  | bm      = &sbi->s_bitmap[bmap]; | 
|  |  | 
|  | mutex_lock(&sbi->s_bmlock); | 
|  |  | 
|  | bh = sbi->s_bmap_bh; | 
|  | if (sbi->s_last_bmap != bmap) { | 
|  | affs_brelse(bh); | 
|  | bh = affs_bread(sb, bm->bm_key); | 
|  | if (!bh) | 
|  | goto err_bh_read; | 
|  | sbi->s_bmap_bh = bh; | 
|  | sbi->s_last_bmap = bmap; | 
|  | } | 
|  |  | 
|  | mask = 1 << (bit & 31); | 
|  | data = (__be32 *)bh->b_data + bit / 32 + 1; | 
|  |  | 
|  | /* mark block free */ | 
|  | tmp = be32_to_cpu(*data); | 
|  | if (tmp & mask) | 
|  | goto err_free; | 
|  | *data = cpu_to_be32(tmp | mask); | 
|  |  | 
|  | /* fix checksum */ | 
|  | tmp = be32_to_cpu(*(__be32 *)bh->b_data); | 
|  | *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask); | 
|  |  | 
|  | mark_buffer_dirty(bh); | 
|  | affs_mark_sb_dirty(sb); | 
|  | bm->bm_free++; | 
|  |  | 
|  | mutex_unlock(&sbi->s_bmlock); | 
|  | return; | 
|  |  | 
|  | err_free: | 
|  | affs_warning(sb,"affs_free_block","Trying to free block %u which is already free", block); | 
|  | mutex_unlock(&sbi->s_bmlock); | 
|  | return; | 
|  |  | 
|  | err_bh_read: | 
|  | affs_error(sb,"affs_free_block","Cannot read bitmap block %u", bm->bm_key); | 
|  | sbi->s_bmap_bh = NULL; | 
|  | sbi->s_last_bmap = ~0; | 
|  | mutex_unlock(&sbi->s_bmlock); | 
|  | return; | 
|  |  | 
|  | err_range: | 
|  | affs_error(sb, "affs_free_block","Block %u outside partition", block); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Allocate a block in the given allocation zone. | 
|  | * Since we have to byte-swap the bitmap on little-endian | 
|  | * machines, this is rather expensive. Therefore we will | 
|  | * preallocate up to 16 blocks from the same word, if | 
|  | * possible. We are not doing preallocations in the | 
|  | * header zone, though. | 
|  | */ | 
|  |  | 
|  | u32 | 
|  | affs_alloc_block(struct inode *inode, u32 goal) | 
|  | { | 
|  | struct super_block *sb; | 
|  | struct affs_sb_info *sbi; | 
|  | struct affs_bm_info *bm; | 
|  | struct buffer_head *bh; | 
|  | __be32 *data, *enddata; | 
|  | u32 blk, bmap, bit, mask, mask2, tmp; | 
|  | int i; | 
|  |  | 
|  | sb = inode->i_sb; | 
|  | sbi = AFFS_SB(sb); | 
|  |  | 
|  | pr_debug("balloc(inode=%lu,goal=%u): ", inode->i_ino, goal); | 
|  |  | 
|  | if (AFFS_I(inode)->i_pa_cnt) { | 
|  | pr_debug("%d\n", AFFS_I(inode)->i_lastalloc+1); | 
|  | AFFS_I(inode)->i_pa_cnt--; | 
|  | return ++AFFS_I(inode)->i_lastalloc; | 
|  | } | 
|  |  | 
|  | if (!goal || goal > sbi->s_partition_size) { | 
|  | if (goal) | 
|  | affs_warning(sb, "affs_balloc", "invalid goal %d", goal); | 
|  | //if (!AFFS_I(inode)->i_last_block) | 
|  | //	affs_warning(sb, "affs_balloc", "no last alloc block"); | 
|  | goal = sbi->s_reserved; | 
|  | } | 
|  |  | 
|  | blk = goal - sbi->s_reserved; | 
|  | bmap = blk / sbi->s_bmap_bits; | 
|  | bm = &sbi->s_bitmap[bmap]; | 
|  |  | 
|  | mutex_lock(&sbi->s_bmlock); | 
|  |  | 
|  | if (bm->bm_free) | 
|  | goto find_bmap_bit; | 
|  |  | 
|  | find_bmap: | 
|  | /* search for the next bmap buffer with free bits */ | 
|  | i = sbi->s_bmap_count; | 
|  | do { | 
|  | if (--i < 0) | 
|  | goto err_full; | 
|  | bmap++; | 
|  | bm++; | 
|  | if (bmap < sbi->s_bmap_count) | 
|  | continue; | 
|  | /* restart search at zero */ | 
|  | bmap = 0; | 
|  | bm = sbi->s_bitmap; | 
|  | } while (!bm->bm_free); | 
|  | blk = bmap * sbi->s_bmap_bits; | 
|  |  | 
|  | find_bmap_bit: | 
|  |  | 
|  | bh = sbi->s_bmap_bh; | 
|  | if (sbi->s_last_bmap != bmap) { | 
|  | affs_brelse(bh); | 
|  | bh = affs_bread(sb, bm->bm_key); | 
|  | if (!bh) | 
|  | goto err_bh_read; | 
|  | sbi->s_bmap_bh = bh; | 
|  | sbi->s_last_bmap = bmap; | 
|  | } | 
|  |  | 
|  | /* find an unused block in this bitmap block */ | 
|  | bit = blk % sbi->s_bmap_bits; | 
|  | data = (__be32 *)bh->b_data + bit / 32 + 1; | 
|  | enddata = (__be32 *)((u8 *)bh->b_data + sb->s_blocksize); | 
|  | mask = ~0UL << (bit & 31); | 
|  | blk &= ~31UL; | 
|  |  | 
|  | tmp = be32_to_cpu(*data); | 
|  | if (tmp & mask) | 
|  | goto find_bit; | 
|  |  | 
|  | /* scan the rest of the buffer */ | 
|  | do { | 
|  | blk += 32; | 
|  | if (++data >= enddata) | 
|  | /* didn't find something, can only happen | 
|  | * if scan didn't start at 0, try next bmap | 
|  | */ | 
|  | goto find_bmap; | 
|  | } while (!*data); | 
|  | tmp = be32_to_cpu(*data); | 
|  | mask = ~0; | 
|  |  | 
|  | find_bit: | 
|  | /* finally look for a free bit in the word */ | 
|  | bit = ffs(tmp & mask) - 1; | 
|  | blk += bit + sbi->s_reserved; | 
|  | mask2 = mask = 1 << (bit & 31); | 
|  | AFFS_I(inode)->i_lastalloc = blk; | 
|  |  | 
|  | /* prealloc as much as possible within this word */ | 
|  | while ((mask2 <<= 1)) { | 
|  | if (!(tmp & mask2)) | 
|  | break; | 
|  | AFFS_I(inode)->i_pa_cnt++; | 
|  | mask |= mask2; | 
|  | } | 
|  | bm->bm_free -= AFFS_I(inode)->i_pa_cnt + 1; | 
|  |  | 
|  | *data = cpu_to_be32(tmp & ~mask); | 
|  |  | 
|  | /* fix checksum */ | 
|  | tmp = be32_to_cpu(*(__be32 *)bh->b_data); | 
|  | *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask); | 
|  |  | 
|  | mark_buffer_dirty(bh); | 
|  | affs_mark_sb_dirty(sb); | 
|  |  | 
|  | mutex_unlock(&sbi->s_bmlock); | 
|  |  | 
|  | pr_debug("%d\n", blk); | 
|  | return blk; | 
|  |  | 
|  | err_bh_read: | 
|  | affs_error(sb,"affs_read_block","Cannot read bitmap block %u", bm->bm_key); | 
|  | sbi->s_bmap_bh = NULL; | 
|  | sbi->s_last_bmap = ~0; | 
|  | err_full: | 
|  | mutex_unlock(&sbi->s_bmlock); | 
|  | pr_debug("failed\n"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int affs_init_bitmap(struct super_block *sb, int *flags) | 
|  | { | 
|  | struct affs_bm_info *bm; | 
|  | struct buffer_head *bmap_bh = NULL, *bh = NULL; | 
|  | __be32 *bmap_blk; | 
|  | u32 size, blk, end, offset, mask; | 
|  | int i, res = 0; | 
|  | struct affs_sb_info *sbi = AFFS_SB(sb); | 
|  |  | 
|  | if (*flags & SB_RDONLY) | 
|  | return 0; | 
|  |  | 
|  | if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) { | 
|  | pr_notice("Bitmap invalid - mounting %s read only\n", sb->s_id); | 
|  | *flags |= SB_RDONLY; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sbi->s_last_bmap = ~0; | 
|  | sbi->s_bmap_bh = NULL; | 
|  | sbi->s_bmap_bits = sb->s_blocksize * 8 - 32; | 
|  | sbi->s_bmap_count = (sbi->s_partition_size - sbi->s_reserved + | 
|  | sbi->s_bmap_bits - 1) / sbi->s_bmap_bits; | 
|  | size = sbi->s_bmap_count * sizeof(*bm); | 
|  | bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL); | 
|  | if (!sbi->s_bitmap) { | 
|  | pr_err("Bitmap allocation failed\n"); | 
|  | return -ENOMEM; | 
|  | } | 
|  |  | 
|  | bmap_blk = (__be32 *)sbi->s_root_bh->b_data; | 
|  | blk = sb->s_blocksize / 4 - 49; | 
|  | end = blk + 25; | 
|  |  | 
|  | for (i = sbi->s_bmap_count; i > 0; bm++, i--) { | 
|  | affs_brelse(bh); | 
|  |  | 
|  | bm->bm_key = be32_to_cpu(bmap_blk[blk]); | 
|  | bh = affs_bread(sb, bm->bm_key); | 
|  | if (!bh) { | 
|  | pr_err("Cannot read bitmap\n"); | 
|  | res = -EIO; | 
|  | goto out; | 
|  | } | 
|  | if (affs_checksum_block(sb, bh)) { | 
|  | pr_warn("Bitmap %u invalid - mounting %s read only.\n", | 
|  | bm->bm_key, sb->s_id); | 
|  | *flags |= SB_RDONLY; | 
|  | goto out; | 
|  | } | 
|  | pr_debug("read bitmap block %d: %d\n", blk, bm->bm_key); | 
|  | bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4); | 
|  |  | 
|  | /* Don't try read the extension if this is the last block, | 
|  | * but we also need the right bm pointer below | 
|  | */ | 
|  | if (++blk < end || i == 1) | 
|  | continue; | 
|  | if (bmap_bh) | 
|  | affs_brelse(bmap_bh); | 
|  | bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk])); | 
|  | if (!bmap_bh) { | 
|  | pr_err("Cannot read bitmap extension\n"); | 
|  | res = -EIO; | 
|  | goto out; | 
|  | } | 
|  | bmap_blk = (__be32 *)bmap_bh->b_data; | 
|  | blk = 0; | 
|  | end = sb->s_blocksize / 4 - 1; | 
|  | } | 
|  |  | 
|  | offset = (sbi->s_partition_size - sbi->s_reserved) % sbi->s_bmap_bits; | 
|  | mask = ~(0xFFFFFFFFU << (offset & 31)); | 
|  | pr_debug("last word: %d %d %d\n", offset, offset / 32 + 1, mask); | 
|  | offset = offset / 32 + 1; | 
|  |  | 
|  | if (mask) { | 
|  | u32 old, new; | 
|  |  | 
|  | /* Mark unused bits in the last word as allocated */ | 
|  | old = be32_to_cpu(((__be32 *)bh->b_data)[offset]); | 
|  | new = old & mask; | 
|  | //if (old != new) { | 
|  | ((__be32 *)bh->b_data)[offset] = cpu_to_be32(new); | 
|  | /* fix checksum */ | 
|  | //new -= old; | 
|  | //old = be32_to_cpu(*(__be32 *)bh->b_data); | 
|  | //*(__be32 *)bh->b_data = cpu_to_be32(old - new); | 
|  | //mark_buffer_dirty(bh); | 
|  | //} | 
|  | /* correct offset for the bitmap count below */ | 
|  | //offset++; | 
|  | } | 
|  | while (++offset < sb->s_blocksize / 4) | 
|  | ((__be32 *)bh->b_data)[offset] = 0; | 
|  | ((__be32 *)bh->b_data)[0] = 0; | 
|  | ((__be32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh)); | 
|  | mark_buffer_dirty(bh); | 
|  |  | 
|  | /* recalculate bitmap count for last block */ | 
|  | bm--; | 
|  | bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4); | 
|  |  | 
|  | out: | 
|  | affs_brelse(bh); | 
|  | affs_brelse(bmap_bh); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | void affs_free_bitmap(struct super_block *sb) | 
|  | { | 
|  | struct affs_sb_info *sbi = AFFS_SB(sb); | 
|  |  | 
|  | if (!sbi->s_bitmap) | 
|  | return; | 
|  |  | 
|  | affs_brelse(sbi->s_bmap_bh); | 
|  | sbi->s_bmap_bh = NULL; | 
|  | sbi->s_last_bmap = ~0; | 
|  | kfree(sbi->s_bitmap); | 
|  | sbi->s_bitmap = NULL; | 
|  | } |