18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  linux/fs/ufs/balloc.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1998
68c2ecf20Sopenharmony_ci * Daniel Pirkl <daniel.pirkl@email.cz>
78c2ecf20Sopenharmony_ci * Charles University, Faculty of Mathematics and Physics
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/fs.h>
138c2ecf20Sopenharmony_ci#include <linux/stat.h>
148c2ecf20Sopenharmony_ci#include <linux/time.h>
158c2ecf20Sopenharmony_ci#include <linux/string.h>
168c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
178c2ecf20Sopenharmony_ci#include <linux/capability.h>
188c2ecf20Sopenharmony_ci#include <linux/bitops.h>
198c2ecf20Sopenharmony_ci#include <linux/bio.h>
208c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "ufs_fs.h"
238c2ecf20Sopenharmony_ci#include "ufs.h"
248c2ecf20Sopenharmony_ci#include "swab.h"
258c2ecf20Sopenharmony_ci#include "util.h"
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define INVBLOCK ((u64)-1L)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned);
308c2ecf20Sopenharmony_cistatic u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
318c2ecf20Sopenharmony_cistatic u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
328c2ecf20Sopenharmony_cistatic u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
338c2ecf20Sopenharmony_cistatic unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
348c2ecf20Sopenharmony_cistatic void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * Free 'count' fragments from fragment number 'fragment'
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_civoid ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct super_block * sb;
428c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
438c2ecf20Sopenharmony_ci	struct ufs_cg_private_info * ucpi;
448c2ecf20Sopenharmony_ci	struct ufs_cylinder_group * ucg;
458c2ecf20Sopenharmony_ci	unsigned cgno, bit, end_bit, bbase, blkmap, i;
468c2ecf20Sopenharmony_ci	u64 blkno;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	sb = inode->i_sb;
498c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	UFSD("ENTER, fragment %llu, count %u\n",
528c2ecf20Sopenharmony_ci	     (unsigned long long)fragment, count);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
558c2ecf20Sopenharmony_ci		ufs_error (sb, "ufs_free_fragments", "internal error");
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	mutex_lock(&UFS_SB(sb)->s_lock);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	cgno = ufs_dtog(uspi, fragment);
608c2ecf20Sopenharmony_ci	bit = ufs_dtogd(uspi, fragment);
618c2ecf20Sopenharmony_ci	if (cgno >= uspi->s_ncg) {
628c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
638c2ecf20Sopenharmony_ci		goto failed;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	ucpi = ufs_load_cylinder (sb, cgno);
678c2ecf20Sopenharmony_ci	if (!ucpi)
688c2ecf20Sopenharmony_ci		goto failed;
698c2ecf20Sopenharmony_ci	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
708c2ecf20Sopenharmony_ci	if (!ufs_cg_chkmagic(sb, ucg)) {
718c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
728c2ecf20Sopenharmony_ci		goto failed;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	end_bit = bit + count;
768c2ecf20Sopenharmony_ci	bbase = ufs_blknum (bit);
778c2ecf20Sopenharmony_ci	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
788c2ecf20Sopenharmony_ci	ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
798c2ecf20Sopenharmony_ci	for (i = bit; i < end_bit; i++) {
808c2ecf20Sopenharmony_ci		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
818c2ecf20Sopenharmony_ci			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
828c2ecf20Sopenharmony_ci		else
838c2ecf20Sopenharmony_ci			ufs_error (sb, "ufs_free_fragments",
848c2ecf20Sopenharmony_ci				   "bit already cleared for fragment %u", i);
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	inode_sub_bytes(inode, count << uspi->s_fshift);
888c2ecf20Sopenharmony_ci	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
898c2ecf20Sopenharmony_ci	uspi->cs_total.cs_nffree += count;
908c2ecf20Sopenharmony_ci	fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
918c2ecf20Sopenharmony_ci	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
928c2ecf20Sopenharmony_ci	ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	/*
958c2ecf20Sopenharmony_ci	 * Trying to reassemble free fragments into block
968c2ecf20Sopenharmony_ci	 */
978c2ecf20Sopenharmony_ci	blkno = ufs_fragstoblks (bbase);
988c2ecf20Sopenharmony_ci	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
998c2ecf20Sopenharmony_ci		fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
1008c2ecf20Sopenharmony_ci		uspi->cs_total.cs_nffree -= uspi->s_fpb;
1018c2ecf20Sopenharmony_ci		fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
1028c2ecf20Sopenharmony_ci		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
1038c2ecf20Sopenharmony_ci			ufs_clusteracct (sb, ucpi, blkno, 1);
1048c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
1058c2ecf20Sopenharmony_ci		uspi->cs_total.cs_nbfree++;
1068c2ecf20Sopenharmony_ci		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
1078c2ecf20Sopenharmony_ci		if (uspi->fs_magic != UFS2_MAGIC) {
1088c2ecf20Sopenharmony_ci			unsigned cylno = ufs_cbtocylno (bbase);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
1118c2ecf20Sopenharmony_ci						  ufs_cbtorpos(bbase)), 1);
1128c2ecf20Sopenharmony_ci			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
1138c2ecf20Sopenharmony_ci		}
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (USPI_UBH(uspi));
1178c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
1188c2ecf20Sopenharmony_ci	if (sb->s_flags & SB_SYNCHRONOUS)
1198c2ecf20Sopenharmony_ci		ubh_sync_block(UCPI_UBH(ucpi));
1208c2ecf20Sopenharmony_ci	ufs_mark_sb_dirty(sb);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	mutex_unlock(&UFS_SB(sb)->s_lock);
1238c2ecf20Sopenharmony_ci	UFSD("EXIT\n");
1248c2ecf20Sopenharmony_ci	return;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cifailed:
1278c2ecf20Sopenharmony_ci	mutex_unlock(&UFS_SB(sb)->s_lock);
1288c2ecf20Sopenharmony_ci	UFSD("EXIT (FAILED)\n");
1298c2ecf20Sopenharmony_ci	return;
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci/*
1338c2ecf20Sopenharmony_ci * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
1348c2ecf20Sopenharmony_ci */
1358c2ecf20Sopenharmony_civoid ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct super_block * sb;
1388c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
1398c2ecf20Sopenharmony_ci	struct ufs_cg_private_info * ucpi;
1408c2ecf20Sopenharmony_ci	struct ufs_cylinder_group * ucg;
1418c2ecf20Sopenharmony_ci	unsigned overflow, cgno, bit, end_bit, i;
1428c2ecf20Sopenharmony_ci	u64 blkno;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	sb = inode->i_sb;
1458c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	UFSD("ENTER, fragment %llu, count %u\n",
1488c2ecf20Sopenharmony_ci	     (unsigned long long)fragment, count);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
1518c2ecf20Sopenharmony_ci		ufs_error (sb, "ufs_free_blocks", "internal error, "
1528c2ecf20Sopenharmony_ci			   "fragment %llu, count %u\n",
1538c2ecf20Sopenharmony_ci			   (unsigned long long)fragment, count);
1548c2ecf20Sopenharmony_ci		goto failed;
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	mutex_lock(&UFS_SB(sb)->s_lock);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cido_more:
1608c2ecf20Sopenharmony_ci	overflow = 0;
1618c2ecf20Sopenharmony_ci	cgno = ufs_dtog(uspi, fragment);
1628c2ecf20Sopenharmony_ci	bit = ufs_dtogd(uspi, fragment);
1638c2ecf20Sopenharmony_ci	if (cgno >= uspi->s_ncg) {
1648c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
1658c2ecf20Sopenharmony_ci		goto failed_unlock;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci	end_bit = bit + count;
1688c2ecf20Sopenharmony_ci	if (end_bit > uspi->s_fpg) {
1698c2ecf20Sopenharmony_ci		overflow = bit + count - uspi->s_fpg;
1708c2ecf20Sopenharmony_ci		count -= overflow;
1718c2ecf20Sopenharmony_ci		end_bit -= overflow;
1728c2ecf20Sopenharmony_ci	}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	ucpi = ufs_load_cylinder (sb, cgno);
1758c2ecf20Sopenharmony_ci	if (!ucpi)
1768c2ecf20Sopenharmony_ci		goto failed_unlock;
1778c2ecf20Sopenharmony_ci	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
1788c2ecf20Sopenharmony_ci	if (!ufs_cg_chkmagic(sb, ucg)) {
1798c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
1808c2ecf20Sopenharmony_ci		goto failed_unlock;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	for (i = bit; i < end_bit; i += uspi->s_fpb) {
1848c2ecf20Sopenharmony_ci		blkno = ufs_fragstoblks(i);
1858c2ecf20Sopenharmony_ci		if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
1868c2ecf20Sopenharmony_ci			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
1878c2ecf20Sopenharmony_ci		}
1888c2ecf20Sopenharmony_ci		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
1898c2ecf20Sopenharmony_ci		inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
1908c2ecf20Sopenharmony_ci		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
1918c2ecf20Sopenharmony_ci			ufs_clusteracct (sb, ucpi, blkno, 1);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
1948c2ecf20Sopenharmony_ci		uspi->cs_total.cs_nbfree++;
1958c2ecf20Sopenharmony_ci		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci		if (uspi->fs_magic != UFS2_MAGIC) {
1988c2ecf20Sopenharmony_ci			unsigned cylno = ufs_cbtocylno(i);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
2018c2ecf20Sopenharmony_ci						  ufs_cbtorpos(i)), 1);
2028c2ecf20Sopenharmony_ci			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
2038c2ecf20Sopenharmony_ci		}
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (USPI_UBH(uspi));
2078c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
2088c2ecf20Sopenharmony_ci	if (sb->s_flags & SB_SYNCHRONOUS)
2098c2ecf20Sopenharmony_ci		ubh_sync_block(UCPI_UBH(ucpi));
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	if (overflow) {
2128c2ecf20Sopenharmony_ci		fragment += count;
2138c2ecf20Sopenharmony_ci		count = overflow;
2148c2ecf20Sopenharmony_ci		goto do_more;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	ufs_mark_sb_dirty(sb);
2188c2ecf20Sopenharmony_ci	mutex_unlock(&UFS_SB(sb)->s_lock);
2198c2ecf20Sopenharmony_ci	UFSD("EXIT\n");
2208c2ecf20Sopenharmony_ci	return;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cifailed_unlock:
2238c2ecf20Sopenharmony_ci	mutex_unlock(&UFS_SB(sb)->s_lock);
2248c2ecf20Sopenharmony_cifailed:
2258c2ecf20Sopenharmony_ci	UFSD("EXIT (FAILED)\n");
2268c2ecf20Sopenharmony_ci	return;
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/*
2308c2ecf20Sopenharmony_ci * Modify inode page cache in such way:
2318c2ecf20Sopenharmony_ci * have - blocks with b_blocknr equal to oldb...oldb+count-1
2328c2ecf20Sopenharmony_ci * get - blocks with b_blocknr equal to newb...newb+count-1
2338c2ecf20Sopenharmony_ci * also we suppose that oldb...oldb+count-1 blocks
2348c2ecf20Sopenharmony_ci * situated at the end of file.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * We can come here from ufs_writepage or ufs_prepare_write,
2378c2ecf20Sopenharmony_ci * locked_page is argument of these functions, so we already lock it.
2388c2ecf20Sopenharmony_ci */
2398c2ecf20Sopenharmony_cistatic void ufs_change_blocknr(struct inode *inode, sector_t beg,
2408c2ecf20Sopenharmony_ci			       unsigned int count, sector_t oldb,
2418c2ecf20Sopenharmony_ci			       sector_t newb, struct page *locked_page)
2428c2ecf20Sopenharmony_ci{
2438c2ecf20Sopenharmony_ci	const unsigned blks_per_page =
2448c2ecf20Sopenharmony_ci		1 << (PAGE_SHIFT - inode->i_blkbits);
2458c2ecf20Sopenharmony_ci	const unsigned mask = blks_per_page - 1;
2468c2ecf20Sopenharmony_ci	struct address_space * const mapping = inode->i_mapping;
2478c2ecf20Sopenharmony_ci	pgoff_t index, cur_index, last_index;
2488c2ecf20Sopenharmony_ci	unsigned pos, j, lblock;
2498c2ecf20Sopenharmony_ci	sector_t end, i;
2508c2ecf20Sopenharmony_ci	struct page *page;
2518c2ecf20Sopenharmony_ci	struct buffer_head *head, *bh;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n",
2548c2ecf20Sopenharmony_ci	      inode->i_ino, count,
2558c2ecf20Sopenharmony_ci	     (unsigned long long)oldb, (unsigned long long)newb);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	BUG_ON(!locked_page);
2588c2ecf20Sopenharmony_ci	BUG_ON(!PageLocked(locked_page));
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	cur_index = locked_page->index;
2618c2ecf20Sopenharmony_ci	end = count + beg;
2628c2ecf20Sopenharmony_ci	last_index = end >> (PAGE_SHIFT - inode->i_blkbits);
2638c2ecf20Sopenharmony_ci	for (i = beg; i < end; i = (i | mask) + 1) {
2648c2ecf20Sopenharmony_ci		index = i >> (PAGE_SHIFT - inode->i_blkbits);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci		if (likely(cur_index != index)) {
2678c2ecf20Sopenharmony_ci			page = ufs_get_locked_page(mapping, index);
2688c2ecf20Sopenharmony_ci			if (!page)/* it was truncated */
2698c2ecf20Sopenharmony_ci				continue;
2708c2ecf20Sopenharmony_ci			if (IS_ERR(page)) {/* or EIO */
2718c2ecf20Sopenharmony_ci				ufs_error(inode->i_sb, __func__,
2728c2ecf20Sopenharmony_ci					  "read of page %llu failed\n",
2738c2ecf20Sopenharmony_ci					  (unsigned long long)index);
2748c2ecf20Sopenharmony_ci				continue;
2758c2ecf20Sopenharmony_ci			}
2768c2ecf20Sopenharmony_ci		} else
2778c2ecf20Sopenharmony_ci			page = locked_page;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci		head = page_buffers(page);
2808c2ecf20Sopenharmony_ci		bh = head;
2818c2ecf20Sopenharmony_ci		pos = i & mask;
2828c2ecf20Sopenharmony_ci		for (j = 0; j < pos; ++j)
2838c2ecf20Sopenharmony_ci			bh = bh->b_this_page;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci		if (unlikely(index == last_index))
2878c2ecf20Sopenharmony_ci			lblock = end & mask;
2888c2ecf20Sopenharmony_ci		else
2898c2ecf20Sopenharmony_ci			lblock = blks_per_page;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		do {
2928c2ecf20Sopenharmony_ci			if (j >= lblock)
2938c2ecf20Sopenharmony_ci				break;
2948c2ecf20Sopenharmony_ci			pos = (i - beg) + j;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci			if (!buffer_mapped(bh))
2978c2ecf20Sopenharmony_ci					map_bh(bh, inode->i_sb, oldb + pos);
2988c2ecf20Sopenharmony_ci			if (!buffer_uptodate(bh)) {
2998c2ecf20Sopenharmony_ci				ll_rw_block(REQ_OP_READ, 0, 1, &bh);
3008c2ecf20Sopenharmony_ci				wait_on_buffer(bh);
3018c2ecf20Sopenharmony_ci				if (!buffer_uptodate(bh)) {
3028c2ecf20Sopenharmony_ci					ufs_error(inode->i_sb, __func__,
3038c2ecf20Sopenharmony_ci						  "read of block failed\n");
3048c2ecf20Sopenharmony_ci					break;
3058c2ecf20Sopenharmony_ci				}
3068c2ecf20Sopenharmony_ci			}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci			UFSD(" change from %llu to %llu, pos %u\n",
3098c2ecf20Sopenharmony_ci			     (unsigned long long)(pos + oldb),
3108c2ecf20Sopenharmony_ci			     (unsigned long long)(pos + newb), pos);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci			bh->b_blocknr = newb + pos;
3138c2ecf20Sopenharmony_ci			clean_bdev_bh_alias(bh);
3148c2ecf20Sopenharmony_ci			mark_buffer_dirty(bh);
3158c2ecf20Sopenharmony_ci			++j;
3168c2ecf20Sopenharmony_ci			bh = bh->b_this_page;
3178c2ecf20Sopenharmony_ci		} while (bh != head);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci		if (likely(cur_index != index))
3208c2ecf20Sopenharmony_ci			ufs_put_locked_page(page);
3218c2ecf20Sopenharmony_ci 	}
3228c2ecf20Sopenharmony_ci	UFSD("EXIT\n");
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
3268c2ecf20Sopenharmony_ci			    int sync)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	struct buffer_head *bh;
3298c2ecf20Sopenharmony_ci	sector_t end = beg + n;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	for (; beg < end; ++beg) {
3328c2ecf20Sopenharmony_ci		bh = sb_getblk(inode->i_sb, beg);
3338c2ecf20Sopenharmony_ci		lock_buffer(bh);
3348c2ecf20Sopenharmony_ci		memset(bh->b_data, 0, inode->i_sb->s_blocksize);
3358c2ecf20Sopenharmony_ci		set_buffer_uptodate(bh);
3368c2ecf20Sopenharmony_ci		mark_buffer_dirty(bh);
3378c2ecf20Sopenharmony_ci		unlock_buffer(bh);
3388c2ecf20Sopenharmony_ci		if (IS_SYNC(inode) || sync)
3398c2ecf20Sopenharmony_ci			sync_dirty_buffer(bh);
3408c2ecf20Sopenharmony_ci		brelse(bh);
3418c2ecf20Sopenharmony_ci	}
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ciu64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
3458c2ecf20Sopenharmony_ci			   u64 goal, unsigned count, int *err,
3468c2ecf20Sopenharmony_ci			   struct page *locked_page)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	struct super_block * sb;
3498c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
3508c2ecf20Sopenharmony_ci	struct ufs_super_block_first * usb1;
3518c2ecf20Sopenharmony_ci	unsigned cgno, oldcount, newcount;
3528c2ecf20Sopenharmony_ci	u64 tmp, request, result;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
3558c2ecf20Sopenharmony_ci	     inode->i_ino, (unsigned long long)fragment,
3568c2ecf20Sopenharmony_ci	     (unsigned long long)goal, count);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	sb = inode->i_sb;
3598c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
3608c2ecf20Sopenharmony_ci	usb1 = ubh_get_usb_first(uspi);
3618c2ecf20Sopenharmony_ci	*err = -ENOSPC;
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	mutex_lock(&UFS_SB(sb)->s_lock);
3648c2ecf20Sopenharmony_ci	tmp = ufs_data_ptr_to_cpu(sb, p);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
3678c2ecf20Sopenharmony_ci		ufs_warning(sb, "ufs_new_fragments", "internal warning"
3688c2ecf20Sopenharmony_ci			    " fragment %llu, count %u",
3698c2ecf20Sopenharmony_ci			    (unsigned long long)fragment, count);
3708c2ecf20Sopenharmony_ci		count = uspi->s_fpb - ufs_fragnum(fragment);
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci	oldcount = ufs_fragnum (fragment);
3738c2ecf20Sopenharmony_ci	newcount = oldcount + count;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	/*
3768c2ecf20Sopenharmony_ci	 * Somebody else has just allocated our fragments
3778c2ecf20Sopenharmony_ci	 */
3788c2ecf20Sopenharmony_ci	if (oldcount) {
3798c2ecf20Sopenharmony_ci		if (!tmp) {
3808c2ecf20Sopenharmony_ci			ufs_error(sb, "ufs_new_fragments", "internal error, "
3818c2ecf20Sopenharmony_ci				  "fragment %llu, tmp %llu\n",
3828c2ecf20Sopenharmony_ci				  (unsigned long long)fragment,
3838c2ecf20Sopenharmony_ci				  (unsigned long long)tmp);
3848c2ecf20Sopenharmony_ci			mutex_unlock(&UFS_SB(sb)->s_lock);
3858c2ecf20Sopenharmony_ci			return INVBLOCK;
3868c2ecf20Sopenharmony_ci		}
3878c2ecf20Sopenharmony_ci		if (fragment < UFS_I(inode)->i_lastfrag) {
3888c2ecf20Sopenharmony_ci			UFSD("EXIT (ALREADY ALLOCATED)\n");
3898c2ecf20Sopenharmony_ci			mutex_unlock(&UFS_SB(sb)->s_lock);
3908c2ecf20Sopenharmony_ci			return 0;
3918c2ecf20Sopenharmony_ci		}
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci	else {
3948c2ecf20Sopenharmony_ci		if (tmp) {
3958c2ecf20Sopenharmony_ci			UFSD("EXIT (ALREADY ALLOCATED)\n");
3968c2ecf20Sopenharmony_ci			mutex_unlock(&UFS_SB(sb)->s_lock);
3978c2ecf20Sopenharmony_ci			return 0;
3988c2ecf20Sopenharmony_ci		}
3998c2ecf20Sopenharmony_ci	}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	/*
4028c2ecf20Sopenharmony_ci	 * There is not enough space for user on the device
4038c2ecf20Sopenharmony_ci	 */
4048c2ecf20Sopenharmony_ci	if (unlikely(ufs_freefrags(uspi) <= uspi->s_root_blocks)) {
4058c2ecf20Sopenharmony_ci		if (!capable(CAP_SYS_RESOURCE)) {
4068c2ecf20Sopenharmony_ci			mutex_unlock(&UFS_SB(sb)->s_lock);
4078c2ecf20Sopenharmony_ci			UFSD("EXIT (FAILED)\n");
4088c2ecf20Sopenharmony_ci			return 0;
4098c2ecf20Sopenharmony_ci		}
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (goal >= uspi->s_size)
4138c2ecf20Sopenharmony_ci		goal = 0;
4148c2ecf20Sopenharmony_ci	if (goal == 0)
4158c2ecf20Sopenharmony_ci		cgno = ufs_inotocg (inode->i_ino);
4168c2ecf20Sopenharmony_ci	else
4178c2ecf20Sopenharmony_ci		cgno = ufs_dtog(uspi, goal);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	/*
4208c2ecf20Sopenharmony_ci	 * allocate new fragment
4218c2ecf20Sopenharmony_ci	 */
4228c2ecf20Sopenharmony_ci	if (oldcount == 0) {
4238c2ecf20Sopenharmony_ci		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
4248c2ecf20Sopenharmony_ci		if (result) {
4258c2ecf20Sopenharmony_ci			ufs_clear_frags(inode, result + oldcount,
4268c2ecf20Sopenharmony_ci					newcount - oldcount, locked_page != NULL);
4278c2ecf20Sopenharmony_ci			*err = 0;
4288c2ecf20Sopenharmony_ci			write_seqlock(&UFS_I(inode)->meta_lock);
4298c2ecf20Sopenharmony_ci			ufs_cpu_to_data_ptr(sb, p, result);
4308c2ecf20Sopenharmony_ci			UFS_I(inode)->i_lastfrag =
4318c2ecf20Sopenharmony_ci				max(UFS_I(inode)->i_lastfrag, fragment + count);
4328c2ecf20Sopenharmony_ci			write_sequnlock(&UFS_I(inode)->meta_lock);
4338c2ecf20Sopenharmony_ci		}
4348c2ecf20Sopenharmony_ci		mutex_unlock(&UFS_SB(sb)->s_lock);
4358c2ecf20Sopenharmony_ci		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4368c2ecf20Sopenharmony_ci		return result;
4378c2ecf20Sopenharmony_ci	}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/*
4408c2ecf20Sopenharmony_ci	 * resize block
4418c2ecf20Sopenharmony_ci	 */
4428c2ecf20Sopenharmony_ci	result = ufs_add_fragments(inode, tmp, oldcount, newcount);
4438c2ecf20Sopenharmony_ci	if (result) {
4448c2ecf20Sopenharmony_ci		*err = 0;
4458c2ecf20Sopenharmony_ci		read_seqlock_excl(&UFS_I(inode)->meta_lock);
4468c2ecf20Sopenharmony_ci		UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
4478c2ecf20Sopenharmony_ci						fragment + count);
4488c2ecf20Sopenharmony_ci		read_sequnlock_excl(&UFS_I(inode)->meta_lock);
4498c2ecf20Sopenharmony_ci		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
4508c2ecf20Sopenharmony_ci				locked_page != NULL);
4518c2ecf20Sopenharmony_ci		mutex_unlock(&UFS_SB(sb)->s_lock);
4528c2ecf20Sopenharmony_ci		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4538c2ecf20Sopenharmony_ci		return result;
4548c2ecf20Sopenharmony_ci	}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/*
4578c2ecf20Sopenharmony_ci	 * allocate new block and move data
4588c2ecf20Sopenharmony_ci	 */
4598c2ecf20Sopenharmony_ci	if (fs32_to_cpu(sb, usb1->fs_optim) == UFS_OPTSPACE) {
4608c2ecf20Sopenharmony_ci		request = newcount;
4618c2ecf20Sopenharmony_ci		if (uspi->cs_total.cs_nffree < uspi->s_space_to_time)
4628c2ecf20Sopenharmony_ci			usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
4638c2ecf20Sopenharmony_ci	} else {
4648c2ecf20Sopenharmony_ci		request = uspi->s_fpb;
4658c2ecf20Sopenharmony_ci		if (uspi->cs_total.cs_nffree > uspi->s_time_to_space)
4668c2ecf20Sopenharmony_ci			usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci	result = ufs_alloc_fragments (inode, cgno, goal, request, err);
4698c2ecf20Sopenharmony_ci	if (result) {
4708c2ecf20Sopenharmony_ci		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
4718c2ecf20Sopenharmony_ci				locked_page != NULL);
4728c2ecf20Sopenharmony_ci		mutex_unlock(&UFS_SB(sb)->s_lock);
4738c2ecf20Sopenharmony_ci		ufs_change_blocknr(inode, fragment - oldcount, oldcount,
4748c2ecf20Sopenharmony_ci				   uspi->s_sbbase + tmp,
4758c2ecf20Sopenharmony_ci				   uspi->s_sbbase + result, locked_page);
4768c2ecf20Sopenharmony_ci		*err = 0;
4778c2ecf20Sopenharmony_ci		write_seqlock(&UFS_I(inode)->meta_lock);
4788c2ecf20Sopenharmony_ci		ufs_cpu_to_data_ptr(sb, p, result);
4798c2ecf20Sopenharmony_ci		UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
4808c2ecf20Sopenharmony_ci						fragment + count);
4818c2ecf20Sopenharmony_ci		write_sequnlock(&UFS_I(inode)->meta_lock);
4828c2ecf20Sopenharmony_ci		if (newcount < request)
4838c2ecf20Sopenharmony_ci			ufs_free_fragments (inode, result + newcount, request - newcount);
4848c2ecf20Sopenharmony_ci		ufs_free_fragments (inode, tmp, oldcount);
4858c2ecf20Sopenharmony_ci		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4868c2ecf20Sopenharmony_ci		return result;
4878c2ecf20Sopenharmony_ci	}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	mutex_unlock(&UFS_SB(sb)->s_lock);
4908c2ecf20Sopenharmony_ci	UFSD("EXIT (FAILED)\n");
4918c2ecf20Sopenharmony_ci	return 0;
4928c2ecf20Sopenharmony_ci}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic bool try_add_frags(struct inode *inode, unsigned frags)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	unsigned size = frags * i_blocksize(inode);
4978c2ecf20Sopenharmony_ci	spin_lock(&inode->i_lock);
4988c2ecf20Sopenharmony_ci	__inode_add_bytes(inode, size);
4998c2ecf20Sopenharmony_ci	if (unlikely((u32)inode->i_blocks != inode->i_blocks)) {
5008c2ecf20Sopenharmony_ci		__inode_sub_bytes(inode, size);
5018c2ecf20Sopenharmony_ci		spin_unlock(&inode->i_lock);
5028c2ecf20Sopenharmony_ci		return false;
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci	spin_unlock(&inode->i_lock);
5058c2ecf20Sopenharmony_ci	return true;
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_cistatic u64 ufs_add_fragments(struct inode *inode, u64 fragment,
5098c2ecf20Sopenharmony_ci			     unsigned oldcount, unsigned newcount)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	struct super_block * sb;
5128c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
5138c2ecf20Sopenharmony_ci	struct ufs_cg_private_info * ucpi;
5148c2ecf20Sopenharmony_ci	struct ufs_cylinder_group * ucg;
5158c2ecf20Sopenharmony_ci	unsigned cgno, fragno, fragoff, count, fragsize, i;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
5188c2ecf20Sopenharmony_ci	     (unsigned long long)fragment, oldcount, newcount);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	sb = inode->i_sb;
5218c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
5228c2ecf20Sopenharmony_ci	count = newcount - oldcount;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	cgno = ufs_dtog(uspi, fragment);
5258c2ecf20Sopenharmony_ci	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
5268c2ecf20Sopenharmony_ci		return 0;
5278c2ecf20Sopenharmony_ci	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
5288c2ecf20Sopenharmony_ci		return 0;
5298c2ecf20Sopenharmony_ci	ucpi = ufs_load_cylinder (sb, cgno);
5308c2ecf20Sopenharmony_ci	if (!ucpi)
5318c2ecf20Sopenharmony_ci		return 0;
5328c2ecf20Sopenharmony_ci	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
5338c2ecf20Sopenharmony_ci	if (!ufs_cg_chkmagic(sb, ucg)) {
5348c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_add_fragments",
5358c2ecf20Sopenharmony_ci			"internal error, bad magic number on cg %u", cgno);
5368c2ecf20Sopenharmony_ci		return 0;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	fragno = ufs_dtogd(uspi, fragment);
5408c2ecf20Sopenharmony_ci	fragoff = ufs_fragnum (fragno);
5418c2ecf20Sopenharmony_ci	for (i = oldcount; i < newcount; i++)
5428c2ecf20Sopenharmony_ci		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
5438c2ecf20Sopenharmony_ci			return 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if (!try_add_frags(inode, count))
5468c2ecf20Sopenharmony_ci		return 0;
5478c2ecf20Sopenharmony_ci	/*
5488c2ecf20Sopenharmony_ci	 * Block can be extended
5498c2ecf20Sopenharmony_ci	 */
5508c2ecf20Sopenharmony_ci	ucg->cg_time = ufs_get_seconds(sb);
5518c2ecf20Sopenharmony_ci	for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
5528c2ecf20Sopenharmony_ci		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
5538c2ecf20Sopenharmony_ci			break;
5548c2ecf20Sopenharmony_ci	fragsize = i - oldcount;
5558c2ecf20Sopenharmony_ci	if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
5568c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_add_fragments",
5578c2ecf20Sopenharmony_ci			"internal error or corrupted bitmap on cg %u", cgno);
5588c2ecf20Sopenharmony_ci	fs32_sub(sb, &ucg->cg_frsum[fragsize], 1);
5598c2ecf20Sopenharmony_ci	if (fragsize != count)
5608c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
5618c2ecf20Sopenharmony_ci	for (i = oldcount; i < newcount; i++)
5628c2ecf20Sopenharmony_ci		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
5658c2ecf20Sopenharmony_ci	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
5668c2ecf20Sopenharmony_ci	uspi->cs_total.cs_nffree -= count;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (USPI_UBH(uspi));
5698c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
5708c2ecf20Sopenharmony_ci	if (sb->s_flags & SB_SYNCHRONOUS)
5718c2ecf20Sopenharmony_ci		ubh_sync_block(UCPI_UBH(ucpi));
5728c2ecf20Sopenharmony_ci	ufs_mark_sb_dirty(sb);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	return fragment;
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci#define UFS_TEST_FREE_SPACE_CG \
5808c2ecf20Sopenharmony_ci	ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \
5818c2ecf20Sopenharmony_ci	if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \
5828c2ecf20Sopenharmony_ci		goto cg_found; \
5838c2ecf20Sopenharmony_ci	for (k = count; k < uspi->s_fpb; k++) \
5848c2ecf20Sopenharmony_ci		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
5858c2ecf20Sopenharmony_ci			goto cg_found;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
5888c2ecf20Sopenharmony_ci			       u64 goal, unsigned count, int *err)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct super_block * sb;
5918c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
5928c2ecf20Sopenharmony_ci	struct ufs_cg_private_info * ucpi;
5938c2ecf20Sopenharmony_ci	struct ufs_cylinder_group * ucg;
5948c2ecf20Sopenharmony_ci	unsigned oldcg, i, j, k, allocsize;
5958c2ecf20Sopenharmony_ci	u64 result;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
5988c2ecf20Sopenharmony_ci	     inode->i_ino, cgno, (unsigned long long)goal, count);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	sb = inode->i_sb;
6018c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
6028c2ecf20Sopenharmony_ci	oldcg = cgno;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	/*
6058c2ecf20Sopenharmony_ci	 * 1. searching on preferred cylinder group
6068c2ecf20Sopenharmony_ci	 */
6078c2ecf20Sopenharmony_ci	UFS_TEST_FREE_SPACE_CG
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	/*
6108c2ecf20Sopenharmony_ci	 * 2. quadratic rehash
6118c2ecf20Sopenharmony_ci	 */
6128c2ecf20Sopenharmony_ci	for (j = 1; j < uspi->s_ncg; j *= 2) {
6138c2ecf20Sopenharmony_ci		cgno += j;
6148c2ecf20Sopenharmony_ci		if (cgno >= uspi->s_ncg)
6158c2ecf20Sopenharmony_ci			cgno -= uspi->s_ncg;
6168c2ecf20Sopenharmony_ci		UFS_TEST_FREE_SPACE_CG
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	/*
6208c2ecf20Sopenharmony_ci	 * 3. brute force search
6218c2ecf20Sopenharmony_ci	 * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step )
6228c2ecf20Sopenharmony_ci	 */
6238c2ecf20Sopenharmony_ci	cgno = (oldcg + 1) % uspi->s_ncg;
6248c2ecf20Sopenharmony_ci	for (j = 2; j < uspi->s_ncg; j++) {
6258c2ecf20Sopenharmony_ci		cgno++;
6268c2ecf20Sopenharmony_ci		if (cgno >= uspi->s_ncg)
6278c2ecf20Sopenharmony_ci			cgno = 0;
6288c2ecf20Sopenharmony_ci		UFS_TEST_FREE_SPACE_CG
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	UFSD("EXIT (FAILED)\n");
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cicg_found:
6358c2ecf20Sopenharmony_ci	ucpi = ufs_load_cylinder (sb, cgno);
6368c2ecf20Sopenharmony_ci	if (!ucpi)
6378c2ecf20Sopenharmony_ci		return 0;
6388c2ecf20Sopenharmony_ci	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
6398c2ecf20Sopenharmony_ci	if (!ufs_cg_chkmagic(sb, ucg))
6408c2ecf20Sopenharmony_ci		ufs_panic (sb, "ufs_alloc_fragments",
6418c2ecf20Sopenharmony_ci			"internal error, bad magic number on cg %u", cgno);
6428c2ecf20Sopenharmony_ci	ucg->cg_time = ufs_get_seconds(sb);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	if (count == uspi->s_fpb) {
6458c2ecf20Sopenharmony_ci		result = ufs_alloccg_block (inode, ucpi, goal, err);
6468c2ecf20Sopenharmony_ci		if (result == INVBLOCK)
6478c2ecf20Sopenharmony_ci			return 0;
6488c2ecf20Sopenharmony_ci		goto succed;
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	for (allocsize = count; allocsize < uspi->s_fpb; allocsize++)
6528c2ecf20Sopenharmony_ci		if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0)
6538c2ecf20Sopenharmony_ci			break;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	if (allocsize == uspi->s_fpb) {
6568c2ecf20Sopenharmony_ci		result = ufs_alloccg_block (inode, ucpi, goal, err);
6578c2ecf20Sopenharmony_ci		if (result == INVBLOCK)
6588c2ecf20Sopenharmony_ci			return 0;
6598c2ecf20Sopenharmony_ci		goal = ufs_dtogd(uspi, result);
6608c2ecf20Sopenharmony_ci		for (i = count; i < uspi->s_fpb; i++)
6618c2ecf20Sopenharmony_ci			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
6628c2ecf20Sopenharmony_ci		i = uspi->s_fpb - count;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci		inode_sub_bytes(inode, i << uspi->s_fshift);
6658c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
6668c2ecf20Sopenharmony_ci		uspi->cs_total.cs_nffree += i;
6678c2ecf20Sopenharmony_ci		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
6688c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_frsum[i], 1);
6698c2ecf20Sopenharmony_ci		goto succed;
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
6738c2ecf20Sopenharmony_ci	if (result == INVBLOCK)
6748c2ecf20Sopenharmony_ci		return 0;
6758c2ecf20Sopenharmony_ci	if (!try_add_frags(inode, count))
6768c2ecf20Sopenharmony_ci		return 0;
6778c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++)
6788c2ecf20Sopenharmony_ci		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
6818c2ecf20Sopenharmony_ci	uspi->cs_total.cs_nffree -= count;
6828c2ecf20Sopenharmony_ci	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
6838c2ecf20Sopenharmony_ci	fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	if (count != allocsize)
6868c2ecf20Sopenharmony_ci		fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cisucced:
6898c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (USPI_UBH(uspi));
6908c2ecf20Sopenharmony_ci	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
6918c2ecf20Sopenharmony_ci	if (sb->s_flags & SB_SYNCHRONOUS)
6928c2ecf20Sopenharmony_ci		ubh_sync_block(UCPI_UBH(ucpi));
6938c2ecf20Sopenharmony_ci	ufs_mark_sb_dirty(sb);
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	result += cgno * uspi->s_fpg;
6968c2ecf20Sopenharmony_ci	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
6978c2ecf20Sopenharmony_ci	return result;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cistatic u64 ufs_alloccg_block(struct inode *inode,
7018c2ecf20Sopenharmony_ci			     struct ufs_cg_private_info *ucpi,
7028c2ecf20Sopenharmony_ci			     u64 goal, int *err)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	struct super_block * sb;
7058c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
7068c2ecf20Sopenharmony_ci	struct ufs_cylinder_group * ucg;
7078c2ecf20Sopenharmony_ci	u64 result, blkno;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	sb = inode->i_sb;
7128c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
7138c2ecf20Sopenharmony_ci	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	if (goal == 0) {
7168c2ecf20Sopenharmony_ci		goal = ucpi->c_rotor;
7178c2ecf20Sopenharmony_ci		goto norot;
7188c2ecf20Sopenharmony_ci	}
7198c2ecf20Sopenharmony_ci	goal = ufs_blknum (goal);
7208c2ecf20Sopenharmony_ci	goal = ufs_dtogd(uspi, goal);
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	/*
7238c2ecf20Sopenharmony_ci	 * If the requested block is available, use it.
7248c2ecf20Sopenharmony_ci	 */
7258c2ecf20Sopenharmony_ci	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) {
7268c2ecf20Sopenharmony_ci		result = goal;
7278c2ecf20Sopenharmony_ci		goto gotit;
7288c2ecf20Sopenharmony_ci	}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_cinorot:
7318c2ecf20Sopenharmony_ci	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
7328c2ecf20Sopenharmony_ci	if (result == INVBLOCK)
7338c2ecf20Sopenharmony_ci		return INVBLOCK;
7348c2ecf20Sopenharmony_ci	ucpi->c_rotor = result;
7358c2ecf20Sopenharmony_cigotit:
7368c2ecf20Sopenharmony_ci	if (!try_add_frags(inode, uspi->s_fpb))
7378c2ecf20Sopenharmony_ci		return 0;
7388c2ecf20Sopenharmony_ci	blkno = ufs_fragstoblks(result);
7398c2ecf20Sopenharmony_ci	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
7408c2ecf20Sopenharmony_ci	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
7418c2ecf20Sopenharmony_ci		ufs_clusteracct (sb, ucpi, blkno, -1);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
7448c2ecf20Sopenharmony_ci	uspi->cs_total.cs_nbfree--;
7458c2ecf20Sopenharmony_ci	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (uspi->fs_magic != UFS2_MAGIC) {
7488c2ecf20Sopenharmony_ci		unsigned cylno = ufs_cbtocylno((unsigned)result);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
7518c2ecf20Sopenharmony_ci					  ufs_cbtorpos((unsigned)result)), 1);
7528c2ecf20Sopenharmony_ci		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
7538c2ecf20Sopenharmony_ci	}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	UFSD("EXIT, result %llu\n", (unsigned long long)result);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	return result;
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_cistatic unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
7618c2ecf20Sopenharmony_ci			  struct ufs_buffer_head *ubh,
7628c2ecf20Sopenharmony_ci			  unsigned begin, unsigned size,
7638c2ecf20Sopenharmony_ci			  unsigned char *table, unsigned char mask)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	unsigned rest, offset;
7668c2ecf20Sopenharmony_ci	unsigned char *cp;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	offset = begin & ~uspi->s_fmask;
7708c2ecf20Sopenharmony_ci	begin >>= uspi->s_fshift;
7718c2ecf20Sopenharmony_ci	for (;;) {
7728c2ecf20Sopenharmony_ci		if ((offset + size) < uspi->s_fsize)
7738c2ecf20Sopenharmony_ci			rest = size;
7748c2ecf20Sopenharmony_ci		else
7758c2ecf20Sopenharmony_ci			rest = uspi->s_fsize - offset;
7768c2ecf20Sopenharmony_ci		size -= rest;
7778c2ecf20Sopenharmony_ci		cp = ubh->bh[begin]->b_data + offset;
7788c2ecf20Sopenharmony_ci		while ((table[*cp++] & mask) == 0 && --rest)
7798c2ecf20Sopenharmony_ci			;
7808c2ecf20Sopenharmony_ci		if (rest || !size)
7818c2ecf20Sopenharmony_ci			break;
7828c2ecf20Sopenharmony_ci		begin++;
7838c2ecf20Sopenharmony_ci		offset = 0;
7848c2ecf20Sopenharmony_ci	}
7858c2ecf20Sopenharmony_ci	return (size + rest);
7868c2ecf20Sopenharmony_ci}
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci/*
7898c2ecf20Sopenharmony_ci * Find a block of the specified size in the specified cylinder group.
7908c2ecf20Sopenharmony_ci * @sp: pointer to super block
7918c2ecf20Sopenharmony_ci * @ucpi: pointer to cylinder group info
7928c2ecf20Sopenharmony_ci * @goal: near which block we want find new one
7938c2ecf20Sopenharmony_ci * @count: specified size
7948c2ecf20Sopenharmony_ci */
7958c2ecf20Sopenharmony_cistatic u64 ufs_bitmap_search(struct super_block *sb,
7968c2ecf20Sopenharmony_ci			     struct ufs_cg_private_info *ucpi,
7978c2ecf20Sopenharmony_ci			     u64 goal, unsigned count)
7988c2ecf20Sopenharmony_ci{
7998c2ecf20Sopenharmony_ci	/*
8008c2ecf20Sopenharmony_ci	 * Bit patterns for identifying fragments in the block map
8018c2ecf20Sopenharmony_ci	 * used as ((map & mask_arr) == want_arr)
8028c2ecf20Sopenharmony_ci	 */
8038c2ecf20Sopenharmony_ci	static const int mask_arr[9] = {
8048c2ecf20Sopenharmony_ci		0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
8058c2ecf20Sopenharmony_ci	};
8068c2ecf20Sopenharmony_ci	static const int want_arr[9] = {
8078c2ecf20Sopenharmony_ci		0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
8088c2ecf20Sopenharmony_ci	};
8098c2ecf20Sopenharmony_ci	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
8108c2ecf20Sopenharmony_ci	unsigned start, length, loc;
8118c2ecf20Sopenharmony_ci	unsigned pos, want, blockmap, mask, end;
8128c2ecf20Sopenharmony_ci	u64 result;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
8158c2ecf20Sopenharmony_ci	     (unsigned long long)goal, count);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	if (goal)
8188c2ecf20Sopenharmony_ci		start = ufs_dtogd(uspi, goal) >> 3;
8198c2ecf20Sopenharmony_ci	else
8208c2ecf20Sopenharmony_ci		start = ucpi->c_frotor >> 3;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	length = ((uspi->s_fpg + 7) >> 3) - start;
8238c2ecf20Sopenharmony_ci	loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length,
8248c2ecf20Sopenharmony_ci		(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
8258c2ecf20Sopenharmony_ci		1 << (count - 1 + (uspi->s_fpb & 7)));
8268c2ecf20Sopenharmony_ci	if (loc == 0) {
8278c2ecf20Sopenharmony_ci		length = start + 1;
8288c2ecf20Sopenharmony_ci		loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length,
8298c2ecf20Sopenharmony_ci				(uspi->s_fpb == 8) ? ufs_fragtable_8fpb :
8308c2ecf20Sopenharmony_ci				ufs_fragtable_other,
8318c2ecf20Sopenharmony_ci				1 << (count - 1 + (uspi->s_fpb & 7)));
8328c2ecf20Sopenharmony_ci		if (loc == 0) {
8338c2ecf20Sopenharmony_ci			ufs_error(sb, "ufs_bitmap_search",
8348c2ecf20Sopenharmony_ci				  "bitmap corrupted on cg %u, start %u,"
8358c2ecf20Sopenharmony_ci				  " length %u, count %u, freeoff %u\n",
8368c2ecf20Sopenharmony_ci				  ucpi->c_cgx, start, length, count,
8378c2ecf20Sopenharmony_ci				  ucpi->c_freeoff);
8388c2ecf20Sopenharmony_ci			return INVBLOCK;
8398c2ecf20Sopenharmony_ci		}
8408c2ecf20Sopenharmony_ci		start = 0;
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ci	result = (start + length - loc) << 3;
8438c2ecf20Sopenharmony_ci	ucpi->c_frotor = result;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	/*
8468c2ecf20Sopenharmony_ci	 * found the byte in the map
8478c2ecf20Sopenharmony_ci	 */
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	for (end = result + 8; result < end; result += uspi->s_fpb) {
8508c2ecf20Sopenharmony_ci		blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result);
8518c2ecf20Sopenharmony_ci		blockmap <<= 1;
8528c2ecf20Sopenharmony_ci		mask = mask_arr[count];
8538c2ecf20Sopenharmony_ci		want = want_arr[count];
8548c2ecf20Sopenharmony_ci		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
8558c2ecf20Sopenharmony_ci			if ((blockmap & mask) == want) {
8568c2ecf20Sopenharmony_ci				UFSD("EXIT, result %llu\n",
8578c2ecf20Sopenharmony_ci				     (unsigned long long)result);
8588c2ecf20Sopenharmony_ci				return result + pos;
8598c2ecf20Sopenharmony_ci 			}
8608c2ecf20Sopenharmony_ci			mask <<= 1;
8618c2ecf20Sopenharmony_ci			want <<= 1;
8628c2ecf20Sopenharmony_ci 		}
8638c2ecf20Sopenharmony_ci 	}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
8668c2ecf20Sopenharmony_ci		  ucpi->c_cgx);
8678c2ecf20Sopenharmony_ci	UFSD("EXIT (FAILED)\n");
8688c2ecf20Sopenharmony_ci	return INVBLOCK;
8698c2ecf20Sopenharmony_ci}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_cistatic void ufs_clusteracct(struct super_block * sb,
8728c2ecf20Sopenharmony_ci	struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
8738c2ecf20Sopenharmony_ci{
8748c2ecf20Sopenharmony_ci	struct ufs_sb_private_info * uspi;
8758c2ecf20Sopenharmony_ci	int i, start, end, forw, back;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	uspi = UFS_SB(sb)->s_uspi;
8788c2ecf20Sopenharmony_ci	if (uspi->s_contigsumsize <= 0)
8798c2ecf20Sopenharmony_ci		return;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	if (cnt > 0)
8828c2ecf20Sopenharmony_ci		ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
8838c2ecf20Sopenharmony_ci	else
8848c2ecf20Sopenharmony_ci		ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	/*
8878c2ecf20Sopenharmony_ci	 * Find the size of the cluster going forward.
8888c2ecf20Sopenharmony_ci	 */
8898c2ecf20Sopenharmony_ci	start = blkno + 1;
8908c2ecf20Sopenharmony_ci	end = start + uspi->s_contigsumsize;
8918c2ecf20Sopenharmony_ci	if ( end >= ucpi->c_nclusterblks)
8928c2ecf20Sopenharmony_ci		end = ucpi->c_nclusterblks;
8938c2ecf20Sopenharmony_ci	i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start);
8948c2ecf20Sopenharmony_ci	if (i > end)
8958c2ecf20Sopenharmony_ci		i = end;
8968c2ecf20Sopenharmony_ci	forw = i - start;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	/*
8998c2ecf20Sopenharmony_ci	 * Find the size of the cluster going backward.
9008c2ecf20Sopenharmony_ci	 */
9018c2ecf20Sopenharmony_ci	start = blkno - 1;
9028c2ecf20Sopenharmony_ci	end = start - uspi->s_contigsumsize;
9038c2ecf20Sopenharmony_ci	if (end < 0 )
9048c2ecf20Sopenharmony_ci		end = -1;
9058c2ecf20Sopenharmony_ci	i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end);
9068c2ecf20Sopenharmony_ci	if ( i < end)
9078c2ecf20Sopenharmony_ci		i = end;
9088c2ecf20Sopenharmony_ci	back = start - i;
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	/*
9118c2ecf20Sopenharmony_ci	 * Account for old cluster and the possibly new forward and
9128c2ecf20Sopenharmony_ci	 * back clusters.
9138c2ecf20Sopenharmony_ci	 */
9148c2ecf20Sopenharmony_ci	i = back + forw + 1;
9158c2ecf20Sopenharmony_ci	if (i > uspi->s_contigsumsize)
9168c2ecf20Sopenharmony_ci		i = uspi->s_contigsumsize;
9178c2ecf20Sopenharmony_ci	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt);
9188c2ecf20Sopenharmony_ci	if (back > 0)
9198c2ecf20Sopenharmony_ci		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt);
9208c2ecf20Sopenharmony_ci	if (forw > 0)
9218c2ecf20Sopenharmony_ci		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt);
9228c2ecf20Sopenharmony_ci}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic unsigned char ufs_fragtable_8fpb[] = {
9268c2ecf20Sopenharmony_ci	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
9278c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
9288c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9298c2ecf20Sopenharmony_ci	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
9308c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9318c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
9328c2ecf20Sopenharmony_ci	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
9338c2ecf20Sopenharmony_ci	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40,
9348c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9358c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
9368c2ecf20Sopenharmony_ci	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9378c2ecf20Sopenharmony_ci	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
9388c2ecf20Sopenharmony_ci	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
9398c2ecf20Sopenharmony_ci	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12,
9408c2ecf20Sopenharmony_ci	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C,
9418c2ecf20Sopenharmony_ci	0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
9428c2ecf20Sopenharmony_ci};
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_cistatic unsigned char ufs_fragtable_other[] = {
9458c2ecf20Sopenharmony_ci	0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A,
9468c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9478c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9488c2ecf20Sopenharmony_ci	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
9498c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9508c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9518c2ecf20Sopenharmony_ci	0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE,
9528c2ecf20Sopenharmony_ci	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
9538c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9548c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9558c2ecf20Sopenharmony_ci	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9568c2ecf20Sopenharmony_ci	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
9578c2ecf20Sopenharmony_ci	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
9588c2ecf20Sopenharmony_ci	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E,	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
9598c2ecf20Sopenharmony_ci	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
9608c2ecf20Sopenharmony_ci	0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A,
9618c2ecf20Sopenharmony_ci};
962