18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/fs/affs/bitmap.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  (c) 1996 Hans-Joachim Widmaier
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  bitmap.c contains the code that handles all bitmap related stuff -
88c2ecf20Sopenharmony_ci *  block allocation, deallocation, calculation of free space.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include "affs.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciu32
158c2ecf20Sopenharmony_ciaffs_count_free_blocks(struct super_block *sb)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	struct affs_bm_info *bm;
188c2ecf20Sopenharmony_ci	u32 free;
198c2ecf20Sopenharmony_ci	int i;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	pr_debug("%s()\n", __func__);
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	if (sb_rdonly(sb))
248c2ecf20Sopenharmony_ci		return 0;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	mutex_lock(&AFFS_SB(sb)->s_bmlock);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	bm = AFFS_SB(sb)->s_bitmap;
298c2ecf20Sopenharmony_ci	free = 0;
308c2ecf20Sopenharmony_ci	for (i = AFFS_SB(sb)->s_bmap_count; i > 0; bm++, i--)
318c2ecf20Sopenharmony_ci		free += bm->bm_free;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	mutex_unlock(&AFFS_SB(sb)->s_bmlock);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	return free;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_civoid
398c2ecf20Sopenharmony_ciaffs_free_block(struct super_block *sb, u32 block)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct affs_sb_info *sbi = AFFS_SB(sb);
428c2ecf20Sopenharmony_ci	struct affs_bm_info *bm;
438c2ecf20Sopenharmony_ci	struct buffer_head *bh;
448c2ecf20Sopenharmony_ci	u32 blk, bmap, bit, mask, tmp;
458c2ecf20Sopenharmony_ci	__be32 *data;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	pr_debug("%s(%u)\n", __func__, block);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if (block > sbi->s_partition_size)
508c2ecf20Sopenharmony_ci		goto err_range;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	blk     = block - sbi->s_reserved;
538c2ecf20Sopenharmony_ci	bmap    = blk / sbi->s_bmap_bits;
548c2ecf20Sopenharmony_ci	bit     = blk % sbi->s_bmap_bits;
558c2ecf20Sopenharmony_ci	bm      = &sbi->s_bitmap[bmap];
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	mutex_lock(&sbi->s_bmlock);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	bh = sbi->s_bmap_bh;
608c2ecf20Sopenharmony_ci	if (sbi->s_last_bmap != bmap) {
618c2ecf20Sopenharmony_ci		affs_brelse(bh);
628c2ecf20Sopenharmony_ci		bh = affs_bread(sb, bm->bm_key);
638c2ecf20Sopenharmony_ci		if (!bh)
648c2ecf20Sopenharmony_ci			goto err_bh_read;
658c2ecf20Sopenharmony_ci		sbi->s_bmap_bh = bh;
668c2ecf20Sopenharmony_ci		sbi->s_last_bmap = bmap;
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	mask = 1 << (bit & 31);
708c2ecf20Sopenharmony_ci	data = (__be32 *)bh->b_data + bit / 32 + 1;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* mark block free */
738c2ecf20Sopenharmony_ci	tmp = be32_to_cpu(*data);
748c2ecf20Sopenharmony_ci	if (tmp & mask)
758c2ecf20Sopenharmony_ci		goto err_free;
768c2ecf20Sopenharmony_ci	*data = cpu_to_be32(tmp | mask);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* fix checksum */
798c2ecf20Sopenharmony_ci	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
808c2ecf20Sopenharmony_ci	*(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	mark_buffer_dirty(bh);
838c2ecf20Sopenharmony_ci	affs_mark_sb_dirty(sb);
848c2ecf20Sopenharmony_ci	bm->bm_free++;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_bmlock);
878c2ecf20Sopenharmony_ci	return;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cierr_free:
908c2ecf20Sopenharmony_ci	affs_warning(sb,"affs_free_block","Trying to free block %u which is already free", block);
918c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_bmlock);
928c2ecf20Sopenharmony_ci	return;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cierr_bh_read:
958c2ecf20Sopenharmony_ci	affs_error(sb,"affs_free_block","Cannot read bitmap block %u", bm->bm_key);
968c2ecf20Sopenharmony_ci	sbi->s_bmap_bh = NULL;
978c2ecf20Sopenharmony_ci	sbi->s_last_bmap = ~0;
988c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_bmlock);
998c2ecf20Sopenharmony_ci	return;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cierr_range:
1028c2ecf20Sopenharmony_ci	affs_error(sb, "affs_free_block","Block %u outside partition", block);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/*
1068c2ecf20Sopenharmony_ci * Allocate a block in the given allocation zone.
1078c2ecf20Sopenharmony_ci * Since we have to byte-swap the bitmap on little-endian
1088c2ecf20Sopenharmony_ci * machines, this is rather expensive. Therefore we will
1098c2ecf20Sopenharmony_ci * preallocate up to 16 blocks from the same word, if
1108c2ecf20Sopenharmony_ci * possible. We are not doing preallocations in the
1118c2ecf20Sopenharmony_ci * header zone, though.
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciu32
1158c2ecf20Sopenharmony_ciaffs_alloc_block(struct inode *inode, u32 goal)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct super_block *sb;
1188c2ecf20Sopenharmony_ci	struct affs_sb_info *sbi;
1198c2ecf20Sopenharmony_ci	struct affs_bm_info *bm;
1208c2ecf20Sopenharmony_ci	struct buffer_head *bh;
1218c2ecf20Sopenharmony_ci	__be32 *data, *enddata;
1228c2ecf20Sopenharmony_ci	u32 blk, bmap, bit, mask, mask2, tmp;
1238c2ecf20Sopenharmony_ci	int i;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	sb = inode->i_sb;
1268c2ecf20Sopenharmony_ci	sbi = AFFS_SB(sb);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	pr_debug("balloc(inode=%lu,goal=%u): ", inode->i_ino, goal);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (AFFS_I(inode)->i_pa_cnt) {
1318c2ecf20Sopenharmony_ci		pr_debug("%d\n", AFFS_I(inode)->i_lastalloc+1);
1328c2ecf20Sopenharmony_ci		AFFS_I(inode)->i_pa_cnt--;
1338c2ecf20Sopenharmony_ci		return ++AFFS_I(inode)->i_lastalloc;
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	if (!goal || goal > sbi->s_partition_size) {
1378c2ecf20Sopenharmony_ci		if (goal)
1388c2ecf20Sopenharmony_ci			affs_warning(sb, "affs_balloc", "invalid goal %d", goal);
1398c2ecf20Sopenharmony_ci		//if (!AFFS_I(inode)->i_last_block)
1408c2ecf20Sopenharmony_ci		//	affs_warning(sb, "affs_balloc", "no last alloc block");
1418c2ecf20Sopenharmony_ci		goal = sbi->s_reserved;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	blk = goal - sbi->s_reserved;
1458c2ecf20Sopenharmony_ci	bmap = blk / sbi->s_bmap_bits;
1468c2ecf20Sopenharmony_ci	bm = &sbi->s_bitmap[bmap];
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	mutex_lock(&sbi->s_bmlock);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	if (bm->bm_free)
1518c2ecf20Sopenharmony_ci		goto find_bmap_bit;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cifind_bmap:
1548c2ecf20Sopenharmony_ci	/* search for the next bmap buffer with free bits */
1558c2ecf20Sopenharmony_ci	i = sbi->s_bmap_count;
1568c2ecf20Sopenharmony_ci	do {
1578c2ecf20Sopenharmony_ci		if (--i < 0)
1588c2ecf20Sopenharmony_ci			goto err_full;
1598c2ecf20Sopenharmony_ci		bmap++;
1608c2ecf20Sopenharmony_ci		bm++;
1618c2ecf20Sopenharmony_ci		if (bmap < sbi->s_bmap_count)
1628c2ecf20Sopenharmony_ci			continue;
1638c2ecf20Sopenharmony_ci		/* restart search at zero */
1648c2ecf20Sopenharmony_ci		bmap = 0;
1658c2ecf20Sopenharmony_ci		bm = sbi->s_bitmap;
1668c2ecf20Sopenharmony_ci	} while (!bm->bm_free);
1678c2ecf20Sopenharmony_ci	blk = bmap * sbi->s_bmap_bits;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cifind_bmap_bit:
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	bh = sbi->s_bmap_bh;
1728c2ecf20Sopenharmony_ci	if (sbi->s_last_bmap != bmap) {
1738c2ecf20Sopenharmony_ci		affs_brelse(bh);
1748c2ecf20Sopenharmony_ci		bh = affs_bread(sb, bm->bm_key);
1758c2ecf20Sopenharmony_ci		if (!bh)
1768c2ecf20Sopenharmony_ci			goto err_bh_read;
1778c2ecf20Sopenharmony_ci		sbi->s_bmap_bh = bh;
1788c2ecf20Sopenharmony_ci		sbi->s_last_bmap = bmap;
1798c2ecf20Sopenharmony_ci	}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	/* find an unused block in this bitmap block */
1828c2ecf20Sopenharmony_ci	bit = blk % sbi->s_bmap_bits;
1838c2ecf20Sopenharmony_ci	data = (__be32 *)bh->b_data + bit / 32 + 1;
1848c2ecf20Sopenharmony_ci	enddata = (__be32 *)((u8 *)bh->b_data + sb->s_blocksize);
1858c2ecf20Sopenharmony_ci	mask = ~0UL << (bit & 31);
1868c2ecf20Sopenharmony_ci	blk &= ~31UL;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	tmp = be32_to_cpu(*data);
1898c2ecf20Sopenharmony_ci	if (tmp & mask)
1908c2ecf20Sopenharmony_ci		goto find_bit;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* scan the rest of the buffer */
1938c2ecf20Sopenharmony_ci	do {
1948c2ecf20Sopenharmony_ci		blk += 32;
1958c2ecf20Sopenharmony_ci		if (++data >= enddata)
1968c2ecf20Sopenharmony_ci			/* didn't find something, can only happen
1978c2ecf20Sopenharmony_ci			 * if scan didn't start at 0, try next bmap
1988c2ecf20Sopenharmony_ci			 */
1998c2ecf20Sopenharmony_ci			goto find_bmap;
2008c2ecf20Sopenharmony_ci	} while (!*data);
2018c2ecf20Sopenharmony_ci	tmp = be32_to_cpu(*data);
2028c2ecf20Sopenharmony_ci	mask = ~0;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cifind_bit:
2058c2ecf20Sopenharmony_ci	/* finally look for a free bit in the word */
2068c2ecf20Sopenharmony_ci	bit = ffs(tmp & mask) - 1;
2078c2ecf20Sopenharmony_ci	blk += bit + sbi->s_reserved;
2088c2ecf20Sopenharmony_ci	mask2 = mask = 1 << (bit & 31);
2098c2ecf20Sopenharmony_ci	AFFS_I(inode)->i_lastalloc = blk;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* prealloc as much as possible within this word */
2128c2ecf20Sopenharmony_ci	while ((mask2 <<= 1)) {
2138c2ecf20Sopenharmony_ci		if (!(tmp & mask2))
2148c2ecf20Sopenharmony_ci			break;
2158c2ecf20Sopenharmony_ci		AFFS_I(inode)->i_pa_cnt++;
2168c2ecf20Sopenharmony_ci		mask |= mask2;
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci	bm->bm_free -= AFFS_I(inode)->i_pa_cnt + 1;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	*data = cpu_to_be32(tmp & ~mask);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	/* fix checksum */
2238c2ecf20Sopenharmony_ci	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
2248c2ecf20Sopenharmony_ci	*(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	mark_buffer_dirty(bh);
2278c2ecf20Sopenharmony_ci	affs_mark_sb_dirty(sb);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_bmlock);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	pr_debug("%d\n", blk);
2328c2ecf20Sopenharmony_ci	return blk;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cierr_bh_read:
2358c2ecf20Sopenharmony_ci	affs_error(sb,"affs_read_block","Cannot read bitmap block %u", bm->bm_key);
2368c2ecf20Sopenharmony_ci	sbi->s_bmap_bh = NULL;
2378c2ecf20Sopenharmony_ci	sbi->s_last_bmap = ~0;
2388c2ecf20Sopenharmony_cierr_full:
2398c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_bmlock);
2408c2ecf20Sopenharmony_ci	pr_debug("failed\n");
2418c2ecf20Sopenharmony_ci	return 0;
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ciint affs_init_bitmap(struct super_block *sb, int *flags)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	struct affs_bm_info *bm;
2478c2ecf20Sopenharmony_ci	struct buffer_head *bmap_bh = NULL, *bh = NULL;
2488c2ecf20Sopenharmony_ci	__be32 *bmap_blk;
2498c2ecf20Sopenharmony_ci	u32 size, blk, end, offset, mask;
2508c2ecf20Sopenharmony_ci	int i, res = 0;
2518c2ecf20Sopenharmony_ci	struct affs_sb_info *sbi = AFFS_SB(sb);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	if (*flags & SB_RDONLY)
2548c2ecf20Sopenharmony_ci		return 0;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
2578c2ecf20Sopenharmony_ci		pr_notice("Bitmap invalid - mounting %s read only\n", sb->s_id);
2588c2ecf20Sopenharmony_ci		*flags |= SB_RDONLY;
2598c2ecf20Sopenharmony_ci		return 0;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	sbi->s_last_bmap = ~0;
2638c2ecf20Sopenharmony_ci	sbi->s_bmap_bh = NULL;
2648c2ecf20Sopenharmony_ci	sbi->s_bmap_bits = sb->s_blocksize * 8 - 32;
2658c2ecf20Sopenharmony_ci	sbi->s_bmap_count = (sbi->s_partition_size - sbi->s_reserved +
2668c2ecf20Sopenharmony_ci				 sbi->s_bmap_bits - 1) / sbi->s_bmap_bits;
2678c2ecf20Sopenharmony_ci	size = sbi->s_bmap_count * sizeof(*bm);
2688c2ecf20Sopenharmony_ci	bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL);
2698c2ecf20Sopenharmony_ci	if (!sbi->s_bitmap) {
2708c2ecf20Sopenharmony_ci		pr_err("Bitmap allocation failed\n");
2718c2ecf20Sopenharmony_ci		return -ENOMEM;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	bmap_blk = (__be32 *)sbi->s_root_bh->b_data;
2758c2ecf20Sopenharmony_ci	blk = sb->s_blocksize / 4 - 49;
2768c2ecf20Sopenharmony_ci	end = blk + 25;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	for (i = sbi->s_bmap_count; i > 0; bm++, i--) {
2798c2ecf20Sopenharmony_ci		affs_brelse(bh);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		bm->bm_key = be32_to_cpu(bmap_blk[blk]);
2828c2ecf20Sopenharmony_ci		bh = affs_bread(sb, bm->bm_key);
2838c2ecf20Sopenharmony_ci		if (!bh) {
2848c2ecf20Sopenharmony_ci			pr_err("Cannot read bitmap\n");
2858c2ecf20Sopenharmony_ci			res = -EIO;
2868c2ecf20Sopenharmony_ci			goto out;
2878c2ecf20Sopenharmony_ci		}
2888c2ecf20Sopenharmony_ci		if (affs_checksum_block(sb, bh)) {
2898c2ecf20Sopenharmony_ci			pr_warn("Bitmap %u invalid - mounting %s read only.\n",
2908c2ecf20Sopenharmony_ci				bm->bm_key, sb->s_id);
2918c2ecf20Sopenharmony_ci			*flags |= SB_RDONLY;
2928c2ecf20Sopenharmony_ci			goto out;
2938c2ecf20Sopenharmony_ci		}
2948c2ecf20Sopenharmony_ci		pr_debug("read bitmap block %d: %d\n", blk, bm->bm_key);
2958c2ecf20Sopenharmony_ci		bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci		/* Don't try read the extension if this is the last block,
2988c2ecf20Sopenharmony_ci		 * but we also need the right bm pointer below
2998c2ecf20Sopenharmony_ci		 */
3008c2ecf20Sopenharmony_ci		if (++blk < end || i == 1)
3018c2ecf20Sopenharmony_ci			continue;
3028c2ecf20Sopenharmony_ci		if (bmap_bh)
3038c2ecf20Sopenharmony_ci			affs_brelse(bmap_bh);
3048c2ecf20Sopenharmony_ci		bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
3058c2ecf20Sopenharmony_ci		if (!bmap_bh) {
3068c2ecf20Sopenharmony_ci			pr_err("Cannot read bitmap extension\n");
3078c2ecf20Sopenharmony_ci			res = -EIO;
3088c2ecf20Sopenharmony_ci			goto out;
3098c2ecf20Sopenharmony_ci		}
3108c2ecf20Sopenharmony_ci		bmap_blk = (__be32 *)bmap_bh->b_data;
3118c2ecf20Sopenharmony_ci		blk = 0;
3128c2ecf20Sopenharmony_ci		end = sb->s_blocksize / 4 - 1;
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	offset = (sbi->s_partition_size - sbi->s_reserved) % sbi->s_bmap_bits;
3168c2ecf20Sopenharmony_ci	mask = ~(0xFFFFFFFFU << (offset & 31));
3178c2ecf20Sopenharmony_ci	pr_debug("last word: %d %d %d\n", offset, offset / 32 + 1, mask);
3188c2ecf20Sopenharmony_ci	offset = offset / 32 + 1;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	if (mask) {
3218c2ecf20Sopenharmony_ci		u32 old, new;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		/* Mark unused bits in the last word as allocated */
3248c2ecf20Sopenharmony_ci		old = be32_to_cpu(((__be32 *)bh->b_data)[offset]);
3258c2ecf20Sopenharmony_ci		new = old & mask;
3268c2ecf20Sopenharmony_ci		//if (old != new) {
3278c2ecf20Sopenharmony_ci			((__be32 *)bh->b_data)[offset] = cpu_to_be32(new);
3288c2ecf20Sopenharmony_ci			/* fix checksum */
3298c2ecf20Sopenharmony_ci			//new -= old;
3308c2ecf20Sopenharmony_ci			//old = be32_to_cpu(*(__be32 *)bh->b_data);
3318c2ecf20Sopenharmony_ci			//*(__be32 *)bh->b_data = cpu_to_be32(old - new);
3328c2ecf20Sopenharmony_ci			//mark_buffer_dirty(bh);
3338c2ecf20Sopenharmony_ci		//}
3348c2ecf20Sopenharmony_ci		/* correct offset for the bitmap count below */
3358c2ecf20Sopenharmony_ci		//offset++;
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci	while (++offset < sb->s_blocksize / 4)
3388c2ecf20Sopenharmony_ci		((__be32 *)bh->b_data)[offset] = 0;
3398c2ecf20Sopenharmony_ci	((__be32 *)bh->b_data)[0] = 0;
3408c2ecf20Sopenharmony_ci	((__be32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
3418c2ecf20Sopenharmony_ci	mark_buffer_dirty(bh);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/* recalculate bitmap count for last block */
3448c2ecf20Sopenharmony_ci	bm--;
3458c2ecf20Sopenharmony_ci	bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ciout:
3488c2ecf20Sopenharmony_ci	affs_brelse(bh);
3498c2ecf20Sopenharmony_ci	affs_brelse(bmap_bh);
3508c2ecf20Sopenharmony_ci	return res;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_civoid affs_free_bitmap(struct super_block *sb)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	struct affs_sb_info *sbi = AFFS_SB(sb);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if (!sbi->s_bitmap)
3588c2ecf20Sopenharmony_ci		return;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	affs_brelse(sbi->s_bmap_bh);
3618c2ecf20Sopenharmony_ci	sbi->s_bmap_bh = NULL;
3628c2ecf20Sopenharmony_ci	sbi->s_last_bmap = ~0;
3638c2ecf20Sopenharmony_ci	kfree(sbi->s_bitmap);
3648c2ecf20Sopenharmony_ci	sbi->s_bitmap = NULL;
3658c2ecf20Sopenharmony_ci}
366