xref: /openbmc/linux/fs/ufs/balloc.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/fs/ufs/balloc.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 1998
61da177e4SLinus Torvalds  * Daniel Pirkl <daniel.pirkl@email.cz>
71da177e4SLinus Torvalds  * Charles University, Faculty of Mathematics and Physics
854fb996aSEvgeniy Dushistov  *
954fb996aSEvgeniy Dushistov  * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds #include <linux/fs.h>
131da177e4SLinus Torvalds #include <linux/stat.h>
141da177e4SLinus Torvalds #include <linux/time.h>
151da177e4SLinus Torvalds #include <linux/string.h>
161da177e4SLinus Torvalds #include <linux/buffer_head.h>
1716f7e0feSRandy Dunlap #include <linux/capability.h>
181da177e4SLinus Torvalds #include <linux/bitops.h>
192f8b5444SChristoph Hellwig #include <linux/bio.h>
201da177e4SLinus Torvalds #include <asm/byteorder.h>
211da177e4SLinus Torvalds 
22e5420598SMike Frysinger #include "ufs_fs.h"
23bcd6d4ecSChristoph Hellwig #include "ufs.h"
241da177e4SLinus Torvalds #include "swab.h"
251da177e4SLinus Torvalds #include "util.h"
261da177e4SLinus Torvalds 
2754fb996aSEvgeniy Dushistov #define INVBLOCK ((u64)-1L)
2854fb996aSEvgeniy Dushistov 
2945641c82SFabian Frederick static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned);
3054fb996aSEvgeniy Dushistov static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
3154fb996aSEvgeniy Dushistov static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
3254fb996aSEvgeniy Dushistov static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
331da177e4SLinus Torvalds static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
341da177e4SLinus Torvalds static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /*
371da177e4SLinus Torvalds  * Free 'count' fragments from fragment number 'fragment'
381da177e4SLinus Torvalds  */
ufs_free_fragments(struct inode * inode,u64 fragment,unsigned count)3954fb996aSEvgeniy Dushistov void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
406ef4d6bfSEvgeniy Dushistov {
411da177e4SLinus Torvalds 	struct super_block * sb;
421da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
431da177e4SLinus Torvalds 	struct ufs_cg_private_info * ucpi;
441da177e4SLinus Torvalds 	struct ufs_cylinder_group * ucg;
4554fb996aSEvgeniy Dushistov 	unsigned cgno, bit, end_bit, bbase, blkmap, i;
4654fb996aSEvgeniy Dushistov 	u64 blkno;
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	sb = inode->i_sb;
491da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
501da177e4SLinus Torvalds 
5154fb996aSEvgeniy Dushistov 	UFSD("ENTER, fragment %llu, count %u\n",
5254fb996aSEvgeniy Dushistov 	     (unsigned long long)fragment, count);
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds 	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
551da177e4SLinus Torvalds 		ufs_error (sb, "ufs_free_fragments", "internal error");
561da177e4SLinus Torvalds 
57cdd9eefdSFabian Frederick 	mutex_lock(&UFS_SB(sb)->s_lock);
581da177e4SLinus Torvalds 
5954fb996aSEvgeniy Dushistov 	cgno = ufs_dtog(uspi, fragment);
6054fb996aSEvgeniy Dushistov 	bit = ufs_dtogd(uspi, fragment);
611da177e4SLinus Torvalds 	if (cgno >= uspi->s_ncg) {
621da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
631da177e4SLinus Torvalds 		goto failed;
641da177e4SLinus Torvalds 	}
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds 	ucpi = ufs_load_cylinder (sb, cgno);
671da177e4SLinus Torvalds 	if (!ucpi)
681da177e4SLinus Torvalds 		goto failed;
699695ef16SEvgeniy Dushistov 	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
701da177e4SLinus Torvalds 	if (!ufs_cg_chkmagic(sb, ucg)) {
711da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
721da177e4SLinus Torvalds 		goto failed;
731da177e4SLinus Torvalds 	}
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	end_bit = bit + count;
761da177e4SLinus Torvalds 	bbase = ufs_blknum (bit);
779695ef16SEvgeniy Dushistov 	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
781da177e4SLinus Torvalds 	ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
791da177e4SLinus Torvalds 	for (i = bit; i < end_bit; i++) {
809695ef16SEvgeniy Dushistov 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
819695ef16SEvgeniy Dushistov 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
827b4ee73eSEvgeniy 		else
837b4ee73eSEvgeniy 			ufs_error (sb, "ufs_free_fragments",
841da177e4SLinus Torvalds 				   "bit already cleared for fragment %u", i);
851da177e4SLinus Torvalds 	}
861da177e4SLinus Torvalds 
87eb315d2aSAl Viro 	inode_sub_bytes(inode, count << uspi->s_fshift);
881da177e4SLinus Torvalds 	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
89ee3ffd6cSEvgeniy Dushistov 	uspi->cs_total.cs_nffree += count;
901da177e4SLinus Torvalds 	fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
919695ef16SEvgeniy Dushistov 	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
921da177e4SLinus Torvalds 	ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds 	/*
951da177e4SLinus Torvalds 	 * Trying to reassemble free fragments into block
961da177e4SLinus Torvalds 	 */
971da177e4SLinus Torvalds 	blkno = ufs_fragstoblks (bbase);
989695ef16SEvgeniy Dushistov 	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
991da177e4SLinus Torvalds 		fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
100ee3ffd6cSEvgeniy Dushistov 		uspi->cs_total.cs_nffree -= uspi->s_fpb;
1011da177e4SLinus Torvalds 		fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
1021da177e4SLinus Torvalds 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
1031da177e4SLinus Torvalds 			ufs_clusteracct (sb, ucpi, blkno, 1);
1041da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
105ee3ffd6cSEvgeniy Dushistov 		uspi->cs_total.cs_nbfree++;
1061da177e4SLinus Torvalds 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
10754fb996aSEvgeniy Dushistov 		if (uspi->fs_magic != UFS2_MAGIC) {
10854fb996aSEvgeniy Dushistov 			unsigned cylno = ufs_cbtocylno (bbase);
10954fb996aSEvgeniy Dushistov 
11054fb996aSEvgeniy Dushistov 			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
11154fb996aSEvgeniy Dushistov 						  ufs_cbtorpos(bbase)), 1);
1121da177e4SLinus Torvalds 			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
1131da177e4SLinus Torvalds 		}
11454fb996aSEvgeniy Dushistov 	}
1151da177e4SLinus Torvalds 
1169695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
1179695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
1181751e8a6SLinus Torvalds 	if (sb->s_flags & SB_SYNCHRONOUS)
1199cb569d6SChristoph Hellwig 		ubh_sync_block(UCPI_UBH(ucpi));
1209e9ad5f4SArtem Bityutskiy 	ufs_mark_sb_dirty(sb);
1211da177e4SLinus Torvalds 
122cdd9eefdSFabian Frederick 	mutex_unlock(&UFS_SB(sb)->s_lock);
123abf5d15fSEvgeniy Dushistov 	UFSD("EXIT\n");
1241da177e4SLinus Torvalds 	return;
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds failed:
127cdd9eefdSFabian Frederick 	mutex_unlock(&UFS_SB(sb)->s_lock);
128abf5d15fSEvgeniy Dushistov 	UFSD("EXIT (FAILED)\n");
1291da177e4SLinus Torvalds 	return;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds /*
1331da177e4SLinus Torvalds  * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
1341da177e4SLinus Torvalds  */
ufs_free_blocks(struct inode * inode,u64 fragment,unsigned count)13554fb996aSEvgeniy Dushistov void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
1366ef4d6bfSEvgeniy Dushistov {
1371da177e4SLinus Torvalds 	struct super_block * sb;
1381da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
1391da177e4SLinus Torvalds 	struct ufs_cg_private_info * ucpi;
1401da177e4SLinus Torvalds 	struct ufs_cylinder_group * ucg;
14154fb996aSEvgeniy Dushistov 	unsigned overflow, cgno, bit, end_bit, i;
14254fb996aSEvgeniy Dushistov 	u64 blkno;
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds 	sb = inode->i_sb;
1451da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
1461da177e4SLinus Torvalds 
14754fb996aSEvgeniy Dushistov 	UFSD("ENTER, fragment %llu, count %u\n",
14854fb996aSEvgeniy Dushistov 	     (unsigned long long)fragment, count);
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
1511da177e4SLinus Torvalds 		ufs_error (sb, "ufs_free_blocks", "internal error, "
15254fb996aSEvgeniy Dushistov 			   "fragment %llu, count %u\n",
15354fb996aSEvgeniy Dushistov 			   (unsigned long long)fragment, count);
1541da177e4SLinus Torvalds 		goto failed;
1551da177e4SLinus Torvalds 	}
1561da177e4SLinus Torvalds 
157cdd9eefdSFabian Frederick 	mutex_lock(&UFS_SB(sb)->s_lock);
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds do_more:
1601da177e4SLinus Torvalds 	overflow = 0;
16154fb996aSEvgeniy Dushistov 	cgno = ufs_dtog(uspi, fragment);
16254fb996aSEvgeniy Dushistov 	bit = ufs_dtogd(uspi, fragment);
1631da177e4SLinus Torvalds 	if (cgno >= uspi->s_ncg) {
1641da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
1652e006393SEvgeniy Dushistov 		goto failed_unlock;
1661da177e4SLinus Torvalds 	}
1671da177e4SLinus Torvalds 	end_bit = bit + count;
1681da177e4SLinus Torvalds 	if (end_bit > uspi->s_fpg) {
1691da177e4SLinus Torvalds 		overflow = bit + count - uspi->s_fpg;
1701da177e4SLinus Torvalds 		count -= overflow;
1711da177e4SLinus Torvalds 		end_bit -= overflow;
1721da177e4SLinus Torvalds 	}
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds 	ucpi = ufs_load_cylinder (sb, cgno);
1751da177e4SLinus Torvalds 	if (!ucpi)
1762e006393SEvgeniy Dushistov 		goto failed_unlock;
1779695ef16SEvgeniy Dushistov 	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
1781da177e4SLinus Torvalds 	if (!ufs_cg_chkmagic(sb, ucg)) {
1791da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
1802e006393SEvgeniy Dushistov 		goto failed_unlock;
1811da177e4SLinus Torvalds 	}
1821da177e4SLinus Torvalds 
1831da177e4SLinus Torvalds 	for (i = bit; i < end_bit; i += uspi->s_fpb) {
1841da177e4SLinus Torvalds 		blkno = ufs_fragstoblks(i);
1859695ef16SEvgeniy Dushistov 		if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
1861da177e4SLinus Torvalds 			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
1871da177e4SLinus Torvalds 		}
1889695ef16SEvgeniy Dushistov 		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
189eb315d2aSAl Viro 		inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
1901da177e4SLinus Torvalds 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
1911da177e4SLinus Torvalds 			ufs_clusteracct (sb, ucpi, blkno, 1);
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
194ee3ffd6cSEvgeniy Dushistov 		uspi->cs_total.cs_nbfree++;
1951da177e4SLinus Torvalds 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
19654fb996aSEvgeniy Dushistov 
19754fb996aSEvgeniy Dushistov 		if (uspi->fs_magic != UFS2_MAGIC) {
19854fb996aSEvgeniy Dushistov 			unsigned cylno = ufs_cbtocylno(i);
19954fb996aSEvgeniy Dushistov 
20054fb996aSEvgeniy Dushistov 			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
20154fb996aSEvgeniy Dushistov 						  ufs_cbtorpos(i)), 1);
2021da177e4SLinus Torvalds 			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
2031da177e4SLinus Torvalds 		}
20454fb996aSEvgeniy Dushistov 	}
2051da177e4SLinus Torvalds 
2069695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
2079695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
2081751e8a6SLinus Torvalds 	if (sb->s_flags & SB_SYNCHRONOUS)
2099cb569d6SChristoph Hellwig 		ubh_sync_block(UCPI_UBH(ucpi));
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	if (overflow) {
2121da177e4SLinus Torvalds 		fragment += count;
2131da177e4SLinus Torvalds 		count = overflow;
2141da177e4SLinus Torvalds 		goto do_more;
2151da177e4SLinus Torvalds 	}
2161da177e4SLinus Torvalds 
2179e9ad5f4SArtem Bityutskiy 	ufs_mark_sb_dirty(sb);
218cdd9eefdSFabian Frederick 	mutex_unlock(&UFS_SB(sb)->s_lock);
219abf5d15fSEvgeniy Dushistov 	UFSD("EXIT\n");
2201da177e4SLinus Torvalds 	return;
2211da177e4SLinus Torvalds 
2222e006393SEvgeniy Dushistov failed_unlock:
223cdd9eefdSFabian Frederick 	mutex_unlock(&UFS_SB(sb)->s_lock);
2242e006393SEvgeniy Dushistov failed:
225abf5d15fSEvgeniy Dushistov 	UFSD("EXIT (FAILED)\n");
2261da177e4SLinus Torvalds 	return;
2271da177e4SLinus Torvalds }
2281da177e4SLinus Torvalds 
2296ef4d6bfSEvgeniy Dushistov /*
2306ef4d6bfSEvgeniy Dushistov  * Modify inode page cache in such way:
2316ef4d6bfSEvgeniy Dushistov  * have - blocks with b_blocknr equal to oldb...oldb+count-1
2326ef4d6bfSEvgeniy Dushistov  * get - blocks with b_blocknr equal to newb...newb+count-1
2336ef4d6bfSEvgeniy Dushistov  * also we suppose that oldb...oldb+count-1 blocks
2346ef4d6bfSEvgeniy Dushistov  * situated at the end of file.
2356ef4d6bfSEvgeniy Dushistov  *
2366ef4d6bfSEvgeniy Dushistov  * We can come here from ufs_writepage or ufs_prepare_write,
2376ef4d6bfSEvgeniy Dushistov  * locked_page is argument of these functions, so we already lock it.
2386ef4d6bfSEvgeniy Dushistov  */
ufs_change_blocknr(struct inode * inode,sector_t beg,unsigned int count,sector_t oldb,sector_t newb,struct page * locked_page)2395431bf97SEvgeniy Dushistov static void ufs_change_blocknr(struct inode *inode, sector_t beg,
2405431bf97SEvgeniy Dushistov 			       unsigned int count, sector_t oldb,
2415431bf97SEvgeniy Dushistov 			       sector_t newb, struct page *locked_page)
2426ef4d6bfSEvgeniy Dushistov {
2435431bf97SEvgeniy Dushistov 	const unsigned blks_per_page =
24409cbfeafSKirill A. Shutemov 		1 << (PAGE_SHIFT - inode->i_blkbits);
2455431bf97SEvgeniy Dushistov 	const unsigned mask = blks_per_page - 1;
246efee2b81SEvgeniy Dushistov 	struct address_space * const mapping = inode->i_mapping;
2475431bf97SEvgeniy Dushistov 	pgoff_t index, cur_index, last_index;
2485431bf97SEvgeniy Dushistov 	unsigned pos, j, lblock;
2495431bf97SEvgeniy Dushistov 	sector_t end, i;
2506ef4d6bfSEvgeniy Dushistov 	struct page *page;
2516ef4d6bfSEvgeniy Dushistov 	struct buffer_head *head, *bh;
2526ef4d6bfSEvgeniy Dushistov 
2535431bf97SEvgeniy Dushistov 	UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n",
2545431bf97SEvgeniy Dushistov 	      inode->i_ino, count,
2555431bf97SEvgeniy Dushistov 	     (unsigned long long)oldb, (unsigned long long)newb);
2566ef4d6bfSEvgeniy Dushistov 
257a685e26fSEvgeniy Dushistov 	BUG_ON(!locked_page);
2586ef4d6bfSEvgeniy Dushistov 	BUG_ON(!PageLocked(locked_page));
2596ef4d6bfSEvgeniy Dushistov 
260a685e26fSEvgeniy Dushistov 	cur_index = locked_page->index;
2615431bf97SEvgeniy Dushistov 	end = count + beg;
26209cbfeafSKirill A. Shutemov 	last_index = end >> (PAGE_SHIFT - inode->i_blkbits);
2635431bf97SEvgeniy Dushistov 	for (i = beg; i < end; i = (i | mask) + 1) {
26409cbfeafSKirill A. Shutemov 		index = i >> (PAGE_SHIFT - inode->i_blkbits);
2656ef4d6bfSEvgeniy Dushistov 
2666ef4d6bfSEvgeniy Dushistov 		if (likely(cur_index != index)) {
2676ef4d6bfSEvgeniy Dushistov 			page = ufs_get_locked_page(mapping, index);
2685431bf97SEvgeniy Dushistov 			if (!page)/* it was truncated */
2696ef4d6bfSEvgeniy Dushistov 				continue;
2705431bf97SEvgeniy Dushistov 			if (IS_ERR(page)) {/* or EIO */
2719746077aSHarvey Harrison 				ufs_error(inode->i_sb, __func__,
2725431bf97SEvgeniy Dushistov 					  "read of page %llu failed\n",
2735431bf97SEvgeniy Dushistov 					  (unsigned long long)index);
2745431bf97SEvgeniy Dushistov 				continue;
2755431bf97SEvgeniy Dushistov 			}
2766ef4d6bfSEvgeniy Dushistov 		} else
2776ef4d6bfSEvgeniy Dushistov 			page = locked_page;
2786ef4d6bfSEvgeniy Dushistov 
2796ef4d6bfSEvgeniy Dushistov 		head = page_buffers(page);
2806ef4d6bfSEvgeniy Dushistov 		bh = head;
2815431bf97SEvgeniy Dushistov 		pos = i & mask;
282efee2b81SEvgeniy Dushistov 		for (j = 0; j < pos; ++j)
283efee2b81SEvgeniy Dushistov 			bh = bh->b_this_page;
2845431bf97SEvgeniy Dushistov 
2855431bf97SEvgeniy Dushistov 
2865431bf97SEvgeniy Dushistov 		if (unlikely(index == last_index))
2875431bf97SEvgeniy Dushistov 			lblock = end & mask;
2885431bf97SEvgeniy Dushistov 		else
2895431bf97SEvgeniy Dushistov 			lblock = blks_per_page;
2905431bf97SEvgeniy Dushistov 
2916ef4d6bfSEvgeniy Dushistov 		do {
2925431bf97SEvgeniy Dushistov 			if (j >= lblock)
2935431bf97SEvgeniy Dushistov 				break;
2945431bf97SEvgeniy Dushistov 			pos = (i - beg) + j;
2955431bf97SEvgeniy Dushistov 
2965431bf97SEvgeniy Dushistov 			if (!buffer_mapped(bh))
2975431bf97SEvgeniy Dushistov 					map_bh(bh, inode->i_sb, oldb + pos);
298*6799b698SZhang Yi 			if (bh_read(bh, 0) < 0) {
2999746077aSHarvey Harrison 				ufs_error(inode->i_sb, __func__,
3005431bf97SEvgeniy Dushistov 					  "read of block failed\n");
3015431bf97SEvgeniy Dushistov 				break;
3025431bf97SEvgeniy Dushistov 			}
3035431bf97SEvgeniy Dushistov 
3045431bf97SEvgeniy Dushistov 			UFSD(" change from %llu to %llu, pos %u\n",
3059df13039SAndrew Morton 			     (unsigned long long)(pos + oldb),
3069df13039SAndrew Morton 			     (unsigned long long)(pos + newb), pos);
3075431bf97SEvgeniy Dushistov 
308efee2b81SEvgeniy Dushistov 			bh->b_blocknr = newb + pos;
309e64855c6SJan Kara 			clean_bdev_bh_alias(bh);
3106ef4d6bfSEvgeniy Dushistov 			mark_buffer_dirty(bh);
311efee2b81SEvgeniy Dushistov 			++j;
3126ef4d6bfSEvgeniy Dushistov 			bh = bh->b_this_page;
3136ef4d6bfSEvgeniy Dushistov 		} while (bh != head);
3146ef4d6bfSEvgeniy Dushistov 
31510e5dce0SEvgeniy Dushistov 		if (likely(cur_index != index))
31610e5dce0SEvgeniy Dushistov 			ufs_put_locked_page(page);
3176ef4d6bfSEvgeniy Dushistov  	}
318abf5d15fSEvgeniy Dushistov 	UFSD("EXIT\n");
3196ef4d6bfSEvgeniy Dushistov }
3201da177e4SLinus Torvalds 
ufs_clear_frags(struct inode * inode,sector_t beg,unsigned int n,int sync)321d63b7090SEvgeniy Dushistov static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
322d63b7090SEvgeniy Dushistov 			    int sync)
323d63b7090SEvgeniy Dushistov {
324d63b7090SEvgeniy Dushistov 	struct buffer_head *bh;
325d63b7090SEvgeniy Dushistov 	sector_t end = beg + n;
326d63b7090SEvgeniy Dushistov 
327d63b7090SEvgeniy Dushistov 	for (; beg < end; ++beg) {
328d63b7090SEvgeniy Dushistov 		bh = sb_getblk(inode->i_sb, beg);
329d63b7090SEvgeniy Dushistov 		lock_buffer(bh);
330d63b7090SEvgeniy Dushistov 		memset(bh->b_data, 0, inode->i_sb->s_blocksize);
331d63b7090SEvgeniy Dushistov 		set_buffer_uptodate(bh);
332d63b7090SEvgeniy Dushistov 		mark_buffer_dirty(bh);
333d63b7090SEvgeniy Dushistov 		unlock_buffer(bh);
334d63b7090SEvgeniy Dushistov 		if (IS_SYNC(inode) || sync)
335d63b7090SEvgeniy Dushistov 			sync_dirty_buffer(bh);
336d63b7090SEvgeniy Dushistov 		brelse(bh);
337d63b7090SEvgeniy Dushistov 	}
338d63b7090SEvgeniy Dushistov }
339d63b7090SEvgeniy Dushistov 
ufs_new_fragments(struct inode * inode,void * p,u64 fragment,u64 goal,unsigned count,int * err,struct page * locked_page)34054fb996aSEvgeniy Dushistov u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
34154fb996aSEvgeniy Dushistov 			   u64 goal, unsigned count, int *err,
34254fb996aSEvgeniy Dushistov 			   struct page *locked_page)
3431da177e4SLinus Torvalds {
3441da177e4SLinus Torvalds 	struct super_block * sb;
3451da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
3461da177e4SLinus Torvalds 	struct ufs_super_block_first * usb1;
34754fb996aSEvgeniy Dushistov 	unsigned cgno, oldcount, newcount;
34854fb996aSEvgeniy Dushistov 	u64 tmp, request, result;
3491da177e4SLinus Torvalds 
35054fb996aSEvgeniy Dushistov 	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
35154fb996aSEvgeniy Dushistov 	     inode->i_ino, (unsigned long long)fragment,
35254fb996aSEvgeniy Dushistov 	     (unsigned long long)goal, count);
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	sb = inode->i_sb;
3551da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
3567b4ee73eSEvgeniy 	usb1 = ubh_get_usb_first(uspi);
3571da177e4SLinus Torvalds 	*err = -ENOSPC;
3581da177e4SLinus Torvalds 
359cdd9eefdSFabian Frederick 	mutex_lock(&UFS_SB(sb)->s_lock);
36054fb996aSEvgeniy Dushistov 	tmp = ufs_data_ptr_to_cpu(sb, p);
3611da177e4SLinus Torvalds 
3621da177e4SLinus Torvalds 	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
3631da177e4SLinus Torvalds 		ufs_warning(sb, "ufs_new_fragments", "internal warning"
36454fb996aSEvgeniy Dushistov 			    " fragment %llu, count %u",
36554fb996aSEvgeniy Dushistov 			    (unsigned long long)fragment, count);
3661da177e4SLinus Torvalds 		count = uspi->s_fpb - ufs_fragnum(fragment);
3671da177e4SLinus Torvalds 	}
3681da177e4SLinus Torvalds 	oldcount = ufs_fragnum (fragment);
3691da177e4SLinus Torvalds 	newcount = oldcount + count;
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 	/*
3721da177e4SLinus Torvalds 	 * Somebody else has just allocated our fragments
3731da177e4SLinus Torvalds 	 */
3741da177e4SLinus Torvalds 	if (oldcount) {
3751da177e4SLinus Torvalds 		if (!tmp) {
3761da177e4SLinus Torvalds 			ufs_error(sb, "ufs_new_fragments", "internal error, "
37754fb996aSEvgeniy Dushistov 				  "fragment %llu, tmp %llu\n",
37854fb996aSEvgeniy Dushistov 				  (unsigned long long)fragment,
37954fb996aSEvgeniy Dushistov 				  (unsigned long long)tmp);
380cdd9eefdSFabian Frederick 			mutex_unlock(&UFS_SB(sb)->s_lock);
38154fb996aSEvgeniy Dushistov 			return INVBLOCK;
3821da177e4SLinus Torvalds 		}
3831da177e4SLinus Torvalds 		if (fragment < UFS_I(inode)->i_lastfrag) {
384abf5d15fSEvgeniy Dushistov 			UFSD("EXIT (ALREADY ALLOCATED)\n");
385cdd9eefdSFabian Frederick 			mutex_unlock(&UFS_SB(sb)->s_lock);
3861da177e4SLinus Torvalds 			return 0;
3871da177e4SLinus Torvalds 		}
3881da177e4SLinus Torvalds 	}
3891da177e4SLinus Torvalds 	else {
3901da177e4SLinus Torvalds 		if (tmp) {
391abf5d15fSEvgeniy Dushistov 			UFSD("EXIT (ALREADY ALLOCATED)\n");
392cdd9eefdSFabian Frederick 			mutex_unlock(&UFS_SB(sb)->s_lock);
3931da177e4SLinus Torvalds 			return 0;
3941da177e4SLinus Torvalds 		}
3951da177e4SLinus Torvalds 	}
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 	/*
3981da177e4SLinus Torvalds 	 * There is not enough space for user on the device
3991da177e4SLinus Torvalds 	 */
400c596961dSAl Viro 	if (unlikely(ufs_freefrags(uspi) <= uspi->s_root_blocks)) {
401b451cec4SAl Viro 		if (!capable(CAP_SYS_RESOURCE)) {
402cdd9eefdSFabian Frederick 			mutex_unlock(&UFS_SB(sb)->s_lock);
403abf5d15fSEvgeniy Dushistov 			UFSD("EXIT (FAILED)\n");
4041da177e4SLinus Torvalds 			return 0;
4051da177e4SLinus Torvalds 		}
406b451cec4SAl Viro 	}
4071da177e4SLinus Torvalds 
4081da177e4SLinus Torvalds 	if (goal >= uspi->s_size)
4091da177e4SLinus Torvalds 		goal = 0;
4101da177e4SLinus Torvalds 	if (goal == 0)
4111da177e4SLinus Torvalds 		cgno = ufs_inotocg (inode->i_ino);
4121da177e4SLinus Torvalds 	else
41354fb996aSEvgeniy Dushistov 		cgno = ufs_dtog(uspi, goal);
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	/*
4161da177e4SLinus Torvalds 	 * allocate new fragment
4171da177e4SLinus Torvalds 	 */
4181da177e4SLinus Torvalds 	if (oldcount == 0) {
4191da177e4SLinus Torvalds 		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
4201da177e4SLinus Torvalds 		if (result) {
421bd2843feSAl Viro 			ufs_clear_frags(inode, result + oldcount,
422bd2843feSAl Viro 					newcount - oldcount, locked_page != NULL);
42309bf4f5bSAl Viro 			*err = 0;
424724bb09fSAl Viro 			write_seqlock(&UFS_I(inode)->meta_lock);
42554fb996aSEvgeniy Dushistov 			ufs_cpu_to_data_ptr(sb, p, result);
42654fb996aSEvgeniy Dushistov 			UFS_I(inode)->i_lastfrag =
4271d582723SDan Carpenter 				max(UFS_I(inode)->i_lastfrag, fragment + count);
42809bf4f5bSAl Viro 			write_sequnlock(&UFS_I(inode)->meta_lock);
4291da177e4SLinus Torvalds 		}
430cdd9eefdSFabian Frederick 		mutex_unlock(&UFS_SB(sb)->s_lock);
43154fb996aSEvgeniy Dushistov 		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4321da177e4SLinus Torvalds 		return result;
4331da177e4SLinus Torvalds 	}
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds 	/*
4361da177e4SLinus Torvalds 	 * resize block
4371da177e4SLinus Torvalds 	 */
43845641c82SFabian Frederick 	result = ufs_add_fragments(inode, tmp, oldcount, newcount);
4391da177e4SLinus Torvalds 	if (result) {
4401da177e4SLinus Torvalds 		*err = 0;
44109bf4f5bSAl Viro 		read_seqlock_excl(&UFS_I(inode)->meta_lock);
4421d582723SDan Carpenter 		UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
4431d582723SDan Carpenter 						fragment + count);
44409bf4f5bSAl Viro 		read_sequnlock_excl(&UFS_I(inode)->meta_lock);
445d63b7090SEvgeniy Dushistov 		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
446d63b7090SEvgeniy Dushistov 				locked_page != NULL);
447cdd9eefdSFabian Frederick 		mutex_unlock(&UFS_SB(sb)->s_lock);
44854fb996aSEvgeniy Dushistov 		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4491da177e4SLinus Torvalds 		return result;
4501da177e4SLinus Torvalds 	}
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds 	/*
4531da177e4SLinus Torvalds 	 * allocate new block and move data
4541da177e4SLinus Torvalds 	 */
45577e9ce32SAl Viro 	if (fs32_to_cpu(sb, usb1->fs_optim) == UFS_OPTSPACE) {
4561da177e4SLinus Torvalds 		request = newcount;
45777e9ce32SAl Viro 		if (uspi->cs_total.cs_nffree < uspi->s_space_to_time)
4581da177e4SLinus Torvalds 			usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
45977e9ce32SAl Viro 	} else {
4601da177e4SLinus Torvalds 		request = uspi->s_fpb;
46177e9ce32SAl Viro 		if (uspi->cs_total.cs_nffree > uspi->s_time_to_space)
46277e9ce32SAl Viro 			usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
4631da177e4SLinus Torvalds 	}
4641da177e4SLinus Torvalds 	result = ufs_alloc_fragments (inode, cgno, goal, request, err);
4651da177e4SLinus Torvalds 	if (result) {
466efee2b81SEvgeniy Dushistov 		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
467efee2b81SEvgeniy Dushistov 				locked_page != NULL);
468289dec5bSAl Viro 		mutex_unlock(&UFS_SB(sb)->s_lock);
4694b25a37eSEvgeniy Dushistov 		ufs_change_blocknr(inode, fragment - oldcount, oldcount,
4704b25a37eSEvgeniy Dushistov 				   uspi->s_sbbase + tmp,
4714b25a37eSEvgeniy Dushistov 				   uspi->s_sbbase + result, locked_page);
47209bf4f5bSAl Viro 		*err = 0;
473724bb09fSAl Viro 		write_seqlock(&UFS_I(inode)->meta_lock);
47454fb996aSEvgeniy Dushistov 		ufs_cpu_to_data_ptr(sb, p, result);
4751d582723SDan Carpenter 		UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
4761d582723SDan Carpenter 						fragment + count);
47709bf4f5bSAl Viro 		write_sequnlock(&UFS_I(inode)->meta_lock);
4781da177e4SLinus Torvalds 		if (newcount < request)
4791da177e4SLinus Torvalds 			ufs_free_fragments (inode, result + newcount, request - newcount);
4801da177e4SLinus Torvalds 		ufs_free_fragments (inode, tmp, oldcount);
48154fb996aSEvgeniy Dushistov 		UFSD("EXIT, result %llu\n", (unsigned long long)result);
4821da177e4SLinus Torvalds 		return result;
4831da177e4SLinus Torvalds 	}
4841da177e4SLinus Torvalds 
485cdd9eefdSFabian Frederick 	mutex_unlock(&UFS_SB(sb)->s_lock);
486abf5d15fSEvgeniy Dushistov 	UFSD("EXIT (FAILED)\n");
4871da177e4SLinus Torvalds 	return 0;
4881da177e4SLinus Torvalds }
4891da177e4SLinus Torvalds 
try_add_frags(struct inode * inode,unsigned frags)490eb315d2aSAl Viro static bool try_add_frags(struct inode *inode, unsigned frags)
491eb315d2aSAl Viro {
492eb315d2aSAl Viro 	unsigned size = frags * i_blocksize(inode);
493eb315d2aSAl Viro 	spin_lock(&inode->i_lock);
494eb315d2aSAl Viro 	__inode_add_bytes(inode, size);
495eb315d2aSAl Viro 	if (unlikely((u32)inode->i_blocks != inode->i_blocks)) {
496eb315d2aSAl Viro 		__inode_sub_bytes(inode, size);
497eb315d2aSAl Viro 		spin_unlock(&inode->i_lock);
498eb315d2aSAl Viro 		return false;
499eb315d2aSAl Viro 	}
500eb315d2aSAl Viro 	spin_unlock(&inode->i_lock);
501eb315d2aSAl Viro 	return true;
502eb315d2aSAl Viro }
503eb315d2aSAl Viro 
ufs_add_fragments(struct inode * inode,u64 fragment,unsigned oldcount,unsigned newcount)50454fb996aSEvgeniy Dushistov static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
50545641c82SFabian Frederick 			     unsigned oldcount, unsigned newcount)
5061da177e4SLinus Torvalds {
5071da177e4SLinus Torvalds 	struct super_block * sb;
5081da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
5091da177e4SLinus Torvalds 	struct ufs_cg_private_info * ucpi;
5101da177e4SLinus Torvalds 	struct ufs_cylinder_group * ucg;
5111da177e4SLinus Torvalds 	unsigned cgno, fragno, fragoff, count, fragsize, i;
5121da177e4SLinus Torvalds 
51354fb996aSEvgeniy Dushistov 	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
51454fb996aSEvgeniy Dushistov 	     (unsigned long long)fragment, oldcount, newcount);
5151da177e4SLinus Torvalds 
5161da177e4SLinus Torvalds 	sb = inode->i_sb;
5171da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
5181da177e4SLinus Torvalds 	count = newcount - oldcount;
5191da177e4SLinus Torvalds 
52054fb996aSEvgeniy Dushistov 	cgno = ufs_dtog(uspi, fragment);
5211da177e4SLinus Torvalds 	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
5221da177e4SLinus Torvalds 		return 0;
5231da177e4SLinus Torvalds 	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
5241da177e4SLinus Torvalds 		return 0;
5251da177e4SLinus Torvalds 	ucpi = ufs_load_cylinder (sb, cgno);
5261da177e4SLinus Torvalds 	if (!ucpi)
5271da177e4SLinus Torvalds 		return 0;
5289695ef16SEvgeniy Dushistov 	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
5291da177e4SLinus Torvalds 	if (!ufs_cg_chkmagic(sb, ucg)) {
5301da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_add_fragments",
5311da177e4SLinus Torvalds 			"internal error, bad magic number on cg %u", cgno);
5321da177e4SLinus Torvalds 		return 0;
5331da177e4SLinus Torvalds 	}
5341da177e4SLinus Torvalds 
53554fb996aSEvgeniy Dushistov 	fragno = ufs_dtogd(uspi, fragment);
5361da177e4SLinus Torvalds 	fragoff = ufs_fragnum (fragno);
5371da177e4SLinus Torvalds 	for (i = oldcount; i < newcount; i++)
5389695ef16SEvgeniy Dushistov 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
5391da177e4SLinus Torvalds 			return 0;
540eb315d2aSAl Viro 
541eb315d2aSAl Viro 	if (!try_add_frags(inode, count))
542eb315d2aSAl Viro 		return 0;
5431da177e4SLinus Torvalds 	/*
5441da177e4SLinus Torvalds 	 * Block can be extended
5451da177e4SLinus Torvalds 	 */
546a3fda0ffSArnd Bergmann 	ucg->cg_time = ufs_get_seconds(sb);
5471da177e4SLinus Torvalds 	for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
5489695ef16SEvgeniy Dushistov 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
5491da177e4SLinus Torvalds 			break;
5501da177e4SLinus Torvalds 	fragsize = i - oldcount;
5511da177e4SLinus Torvalds 	if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
5521da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_add_fragments",
5531da177e4SLinus Torvalds 			"internal error or corrupted bitmap on cg %u", cgno);
5541da177e4SLinus Torvalds 	fs32_sub(sb, &ucg->cg_frsum[fragsize], 1);
5551da177e4SLinus Torvalds 	if (fragsize != count)
5561da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
5571da177e4SLinus Torvalds 	for (i = oldcount; i < newcount; i++)
5589695ef16SEvgeniy Dushistov 		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds 	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
5611da177e4SLinus Torvalds 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
562ee3ffd6cSEvgeniy Dushistov 	uspi->cs_total.cs_nffree -= count;
5631da177e4SLinus Torvalds 
5649695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
5659695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
5661751e8a6SLinus Torvalds 	if (sb->s_flags & SB_SYNCHRONOUS)
5679cb569d6SChristoph Hellwig 		ubh_sync_block(UCPI_UBH(ucpi));
5689e9ad5f4SArtem Bityutskiy 	ufs_mark_sb_dirty(sb);
5691da177e4SLinus Torvalds 
57054fb996aSEvgeniy Dushistov 	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds 	return fragment;
5731da177e4SLinus Torvalds }
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds #define UFS_TEST_FREE_SPACE_CG \
5761da177e4SLinus Torvalds 	ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \
5771da177e4SLinus Torvalds 	if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \
5781da177e4SLinus Torvalds 		goto cg_found; \
5791da177e4SLinus Torvalds 	for (k = count; k < uspi->s_fpb; k++) \
5801da177e4SLinus Torvalds 		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
5811da177e4SLinus Torvalds 			goto cg_found;
5821da177e4SLinus Torvalds 
ufs_alloc_fragments(struct inode * inode,unsigned cgno,u64 goal,unsigned count,int * err)58354fb996aSEvgeniy Dushistov static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
58454fb996aSEvgeniy Dushistov 			       u64 goal, unsigned count, int *err)
5851da177e4SLinus Torvalds {
5861da177e4SLinus Torvalds 	struct super_block * sb;
5871da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
5881da177e4SLinus Torvalds 	struct ufs_cg_private_info * ucpi;
5891da177e4SLinus Torvalds 	struct ufs_cylinder_group * ucg;
59054fb996aSEvgeniy Dushistov 	unsigned oldcg, i, j, k, allocsize;
59154fb996aSEvgeniy Dushistov 	u64 result;
5921da177e4SLinus Torvalds 
59354fb996aSEvgeniy Dushistov 	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
59454fb996aSEvgeniy Dushistov 	     inode->i_ino, cgno, (unsigned long long)goal, count);
5951da177e4SLinus Torvalds 
5961da177e4SLinus Torvalds 	sb = inode->i_sb;
5971da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
5981da177e4SLinus Torvalds 	oldcg = cgno;
5991da177e4SLinus Torvalds 
6001da177e4SLinus Torvalds 	/*
6011da177e4SLinus Torvalds 	 * 1. searching on preferred cylinder group
6021da177e4SLinus Torvalds 	 */
6031da177e4SLinus Torvalds 	UFS_TEST_FREE_SPACE_CG
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 	/*
6061da177e4SLinus Torvalds 	 * 2. quadratic rehash
6071da177e4SLinus Torvalds 	 */
6081da177e4SLinus Torvalds 	for (j = 1; j < uspi->s_ncg; j *= 2) {
6091da177e4SLinus Torvalds 		cgno += j;
6101da177e4SLinus Torvalds 		if (cgno >= uspi->s_ncg)
6111da177e4SLinus Torvalds 			cgno -= uspi->s_ncg;
6121da177e4SLinus Torvalds 		UFS_TEST_FREE_SPACE_CG
6131da177e4SLinus Torvalds 	}
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 	/*
6161da177e4SLinus Torvalds 	 * 3. brute force search
6171da177e4SLinus Torvalds 	 * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step )
6181da177e4SLinus Torvalds 	 */
6191da177e4SLinus Torvalds 	cgno = (oldcg + 1) % uspi->s_ncg;
6201da177e4SLinus Torvalds 	for (j = 2; j < uspi->s_ncg; j++) {
6211da177e4SLinus Torvalds 		cgno++;
6221da177e4SLinus Torvalds 		if (cgno >= uspi->s_ncg)
6231da177e4SLinus Torvalds 			cgno = 0;
6241da177e4SLinus Torvalds 		UFS_TEST_FREE_SPACE_CG
6251da177e4SLinus Torvalds 	}
6261da177e4SLinus Torvalds 
627abf5d15fSEvgeniy Dushistov 	UFSD("EXIT (FAILED)\n");
6281da177e4SLinus Torvalds 	return 0;
6291da177e4SLinus Torvalds 
6301da177e4SLinus Torvalds cg_found:
6311da177e4SLinus Torvalds 	ucpi = ufs_load_cylinder (sb, cgno);
6321da177e4SLinus Torvalds 	if (!ucpi)
6331da177e4SLinus Torvalds 		return 0;
6349695ef16SEvgeniy Dushistov 	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
6351da177e4SLinus Torvalds 	if (!ufs_cg_chkmagic(sb, ucg))
6361da177e4SLinus Torvalds 		ufs_panic (sb, "ufs_alloc_fragments",
6371da177e4SLinus Torvalds 			"internal error, bad magic number on cg %u", cgno);
638a3fda0ffSArnd Bergmann 	ucg->cg_time = ufs_get_seconds(sb);
6391da177e4SLinus Torvalds 
6401da177e4SLinus Torvalds 	if (count == uspi->s_fpb) {
6411da177e4SLinus Torvalds 		result = ufs_alloccg_block (inode, ucpi, goal, err);
64254fb996aSEvgeniy Dushistov 		if (result == INVBLOCK)
6431da177e4SLinus Torvalds 			return 0;
6441da177e4SLinus Torvalds 		goto succed;
6451da177e4SLinus Torvalds 	}
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds 	for (allocsize = count; allocsize < uspi->s_fpb; allocsize++)
6481da177e4SLinus Torvalds 		if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0)
6491da177e4SLinus Torvalds 			break;
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 	if (allocsize == uspi->s_fpb) {
6521da177e4SLinus Torvalds 		result = ufs_alloccg_block (inode, ucpi, goal, err);
65354fb996aSEvgeniy Dushistov 		if (result == INVBLOCK)
6541da177e4SLinus Torvalds 			return 0;
65554fb996aSEvgeniy Dushistov 		goal = ufs_dtogd(uspi, result);
6561da177e4SLinus Torvalds 		for (i = count; i < uspi->s_fpb; i++)
6579695ef16SEvgeniy Dushistov 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
6581da177e4SLinus Torvalds 		i = uspi->s_fpb - count;
6591da177e4SLinus Torvalds 
660eb315d2aSAl Viro 		inode_sub_bytes(inode, i << uspi->s_fshift);
6611da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
662ee3ffd6cSEvgeniy Dushistov 		uspi->cs_total.cs_nffree += i;
6631da177e4SLinus Torvalds 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
6641da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_frsum[i], 1);
6651da177e4SLinus Torvalds 		goto succed;
6661da177e4SLinus Torvalds 	}
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
66954fb996aSEvgeniy Dushistov 	if (result == INVBLOCK)
6701da177e4SLinus Torvalds 		return 0;
671eb315d2aSAl Viro 	if (!try_add_frags(inode, count))
672eb315d2aSAl Viro 		return 0;
6731da177e4SLinus Torvalds 	for (i = 0; i < count; i++)
6749695ef16SEvgeniy Dushistov 		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds 	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
677ee3ffd6cSEvgeniy Dushistov 	uspi->cs_total.cs_nffree -= count;
6781da177e4SLinus Torvalds 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
6791da177e4SLinus Torvalds 	fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
6801da177e4SLinus Torvalds 
6811da177e4SLinus Torvalds 	if (count != allocsize)
6821da177e4SLinus Torvalds 		fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds succed:
6859695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
6869695ef16SEvgeniy Dushistov 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
6871751e8a6SLinus Torvalds 	if (sb->s_flags & SB_SYNCHRONOUS)
6889cb569d6SChristoph Hellwig 		ubh_sync_block(UCPI_UBH(ucpi));
6899e9ad5f4SArtem Bityutskiy 	ufs_mark_sb_dirty(sb);
6901da177e4SLinus Torvalds 
6911da177e4SLinus Torvalds 	result += cgno * uspi->s_fpg;
69254fb996aSEvgeniy Dushistov 	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
6931da177e4SLinus Torvalds 	return result;
6941da177e4SLinus Torvalds }
6951da177e4SLinus Torvalds 
ufs_alloccg_block(struct inode * inode,struct ufs_cg_private_info * ucpi,u64 goal,int * err)69654fb996aSEvgeniy Dushistov static u64 ufs_alloccg_block(struct inode *inode,
69754fb996aSEvgeniy Dushistov 			     struct ufs_cg_private_info *ucpi,
69854fb996aSEvgeniy Dushistov 			     u64 goal, int *err)
6991da177e4SLinus Torvalds {
7001da177e4SLinus Torvalds 	struct super_block * sb;
7011da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
7021da177e4SLinus Torvalds 	struct ufs_cylinder_group * ucg;
70354fb996aSEvgeniy Dushistov 	u64 result, blkno;
7041da177e4SLinus Torvalds 
70554fb996aSEvgeniy Dushistov 	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds 	sb = inode->i_sb;
7081da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
7099695ef16SEvgeniy Dushistov 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
7101da177e4SLinus Torvalds 
7111da177e4SLinus Torvalds 	if (goal == 0) {
7121da177e4SLinus Torvalds 		goal = ucpi->c_rotor;
7131da177e4SLinus Torvalds 		goto norot;
7141da177e4SLinus Torvalds 	}
7151da177e4SLinus Torvalds 	goal = ufs_blknum (goal);
71654fb996aSEvgeniy Dushistov 	goal = ufs_dtogd(uspi, goal);
7171da177e4SLinus Torvalds 
7181da177e4SLinus Torvalds 	/*
7191da177e4SLinus Torvalds 	 * If the requested block is available, use it.
7201da177e4SLinus Torvalds 	 */
7219695ef16SEvgeniy Dushistov 	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) {
7221da177e4SLinus Torvalds 		result = goal;
7231da177e4SLinus Torvalds 		goto gotit;
7241da177e4SLinus Torvalds 	}
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds norot:
7271da177e4SLinus Torvalds 	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
72854fb996aSEvgeniy Dushistov 	if (result == INVBLOCK)
72954fb996aSEvgeniy Dushistov 		return INVBLOCK;
7301da177e4SLinus Torvalds 	ucpi->c_rotor = result;
7311da177e4SLinus Torvalds gotit:
732eb315d2aSAl Viro 	if (!try_add_frags(inode, uspi->s_fpb))
733eb315d2aSAl Viro 		return 0;
7341da177e4SLinus Torvalds 	blkno = ufs_fragstoblks(result);
7359695ef16SEvgeniy Dushistov 	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
7361da177e4SLinus Torvalds 	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
7371da177e4SLinus Torvalds 		ufs_clusteracct (sb, ucpi, blkno, -1);
7381da177e4SLinus Torvalds 
7391da177e4SLinus Torvalds 	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
740ee3ffd6cSEvgeniy Dushistov 	uspi->cs_total.cs_nbfree--;
7411da177e4SLinus Torvalds 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
7421da177e4SLinus Torvalds 
74354fb996aSEvgeniy Dushistov 	if (uspi->fs_magic != UFS2_MAGIC) {
74454fb996aSEvgeniy Dushistov 		unsigned cylno = ufs_cbtocylno((unsigned)result);
74554fb996aSEvgeniy Dushistov 
74654fb996aSEvgeniy Dushistov 		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
74754fb996aSEvgeniy Dushistov 					  ufs_cbtorpos((unsigned)result)), 1);
74854fb996aSEvgeniy Dushistov 		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
74954fb996aSEvgeniy Dushistov 	}
75054fb996aSEvgeniy Dushistov 
75154fb996aSEvgeniy Dushistov 	UFSD("EXIT, result %llu\n", (unsigned long long)result);
7521da177e4SLinus Torvalds 
7531da177e4SLinus Torvalds 	return result;
7541da177e4SLinus Torvalds }
7551da177e4SLinus Torvalds 
ubh_scanc(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned size,unsigned char * table,unsigned char mask)7563e41f597SEvgeniy Dushistov static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
7573e41f597SEvgeniy Dushistov 			  struct ufs_buffer_head *ubh,
7583e41f597SEvgeniy Dushistov 			  unsigned begin, unsigned size,
7593e41f597SEvgeniy Dushistov 			  unsigned char *table, unsigned char mask)
7601da177e4SLinus Torvalds {
7613e41f597SEvgeniy Dushistov 	unsigned rest, offset;
7623e41f597SEvgeniy Dushistov 	unsigned char *cp;
7633e41f597SEvgeniy Dushistov 
7643e41f597SEvgeniy Dushistov 
7653e41f597SEvgeniy Dushistov 	offset = begin & ~uspi->s_fmask;
7663e41f597SEvgeniy Dushistov 	begin >>= uspi->s_fshift;
7673e41f597SEvgeniy Dushistov 	for (;;) {
7683e41f597SEvgeniy Dushistov 		if ((offset + size) < uspi->s_fsize)
7693e41f597SEvgeniy Dushistov 			rest = size;
7703e41f597SEvgeniy Dushistov 		else
7713e41f597SEvgeniy Dushistov 			rest = uspi->s_fsize - offset;
7723e41f597SEvgeniy Dushistov 		size -= rest;
7733e41f597SEvgeniy Dushistov 		cp = ubh->bh[begin]->b_data + offset;
7743e41f597SEvgeniy Dushistov 		while ((table[*cp++] & mask) == 0 && --rest)
7753e41f597SEvgeniy Dushistov 			;
7763e41f597SEvgeniy Dushistov 		if (rest || !size)
7773e41f597SEvgeniy Dushistov 			break;
7783e41f597SEvgeniy Dushistov 		begin++;
7793e41f597SEvgeniy Dushistov 		offset = 0;
7803e41f597SEvgeniy Dushistov 	}
7813e41f597SEvgeniy Dushistov 	return (size + rest);
7823e41f597SEvgeniy Dushistov }
7833e41f597SEvgeniy Dushistov 
7843e41f597SEvgeniy Dushistov /*
7853e41f597SEvgeniy Dushistov  * Find a block of the specified size in the specified cylinder group.
7863e41f597SEvgeniy Dushistov  * @sp: pointer to super block
7873e41f597SEvgeniy Dushistov  * @ucpi: pointer to cylinder group info
7883e41f597SEvgeniy Dushistov  * @goal: near which block we want find new one
7893e41f597SEvgeniy Dushistov  * @count: specified size
7903e41f597SEvgeniy Dushistov  */
ufs_bitmap_search(struct super_block * sb,struct ufs_cg_private_info * ucpi,u64 goal,unsigned count)79154fb996aSEvgeniy Dushistov static u64 ufs_bitmap_search(struct super_block *sb,
7923e41f597SEvgeniy Dushistov 			     struct ufs_cg_private_info *ucpi,
79354fb996aSEvgeniy Dushistov 			     u64 goal, unsigned count)
7943e41f597SEvgeniy Dushistov {
7953e41f597SEvgeniy Dushistov 	/*
7963e41f597SEvgeniy Dushistov 	 * Bit patterns for identifying fragments in the block map
7973e41f597SEvgeniy Dushistov 	 * used as ((map & mask_arr) == want_arr)
7983e41f597SEvgeniy Dushistov 	 */
7993e41f597SEvgeniy Dushistov 	static const int mask_arr[9] = {
8003e41f597SEvgeniy Dushistov 		0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
8013e41f597SEvgeniy Dushistov 	};
8023e41f597SEvgeniy Dushistov 	static const int want_arr[9] = {
8033e41f597SEvgeniy Dushistov 		0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
8043e41f597SEvgeniy Dushistov 	};
8053e41f597SEvgeniy Dushistov 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
80654fb996aSEvgeniy Dushistov 	unsigned start, length, loc;
8073e41f597SEvgeniy Dushistov 	unsigned pos, want, blockmap, mask, end;
80854fb996aSEvgeniy Dushistov 	u64 result;
8091da177e4SLinus Torvalds 
81054fb996aSEvgeniy Dushistov 	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
81154fb996aSEvgeniy Dushistov 	     (unsigned long long)goal, count);
8121da177e4SLinus Torvalds 
8131da177e4SLinus Torvalds 	if (goal)
81454fb996aSEvgeniy Dushistov 		start = ufs_dtogd(uspi, goal) >> 3;
8151da177e4SLinus Torvalds 	else
8161da177e4SLinus Torvalds 		start = ucpi->c_frotor >> 3;
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds 	length = ((uspi->s_fpg + 7) >> 3) - start;
8193e41f597SEvgeniy Dushistov 	loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length,
8201da177e4SLinus Torvalds 		(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
8211da177e4SLinus Torvalds 		1 << (count - 1 + (uspi->s_fpb & 7)));
8223e41f597SEvgeniy Dushistov 	if (loc == 0) {
8231da177e4SLinus Torvalds 		length = start + 1;
8243e41f597SEvgeniy Dushistov 		loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length,
8253e41f597SEvgeniy Dushistov 				(uspi->s_fpb == 8) ? ufs_fragtable_8fpb :
8263e41f597SEvgeniy Dushistov 				ufs_fragtable_other,
8271da177e4SLinus Torvalds 				1 << (count - 1 + (uspi->s_fpb & 7)));
8283e41f597SEvgeniy Dushistov 		if (loc == 0) {
8291da177e4SLinus Torvalds 			ufs_error(sb, "ufs_bitmap_search",
8303e41f597SEvgeniy Dushistov 				  "bitmap corrupted on cg %u, start %u,"
8313e41f597SEvgeniy Dushistov 				  " length %u, count %u, freeoff %u\n",
8323e41f597SEvgeniy Dushistov 				  ucpi->c_cgx, start, length, count,
8333e41f597SEvgeniy Dushistov 				  ucpi->c_freeoff);
83454fb996aSEvgeniy Dushistov 			return INVBLOCK;
8351da177e4SLinus Torvalds 		}
8361da177e4SLinus Torvalds 		start = 0;
8371da177e4SLinus Torvalds 	}
8383e41f597SEvgeniy Dushistov 	result = (start + length - loc) << 3;
8391da177e4SLinus Torvalds 	ucpi->c_frotor = result;
8401da177e4SLinus Torvalds 
8411da177e4SLinus Torvalds 	/*
8421da177e4SLinus Torvalds 	 * found the byte in the map
8431da177e4SLinus Torvalds 	 */
8443e41f597SEvgeniy Dushistov 
8453e41f597SEvgeniy Dushistov 	for (end = result + 8; result < end; result += uspi->s_fpb) {
8469695ef16SEvgeniy Dushistov 		blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result);
8473e41f597SEvgeniy Dushistov 		blockmap <<= 1;
8483e41f597SEvgeniy Dushistov 		mask = mask_arr[count];
8493e41f597SEvgeniy Dushistov 		want = want_arr[count];
8503e41f597SEvgeniy Dushistov 		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
8513e41f597SEvgeniy Dushistov 			if ((blockmap & mask) == want) {
85254fb996aSEvgeniy Dushistov 				UFSD("EXIT, result %llu\n",
85354fb996aSEvgeniy Dushistov 				     (unsigned long long)result);
8543e41f597SEvgeniy Dushistov 				return result + pos;
8551da177e4SLinus Torvalds  			}
8563e41f597SEvgeniy Dushistov 			mask <<= 1;
8573e41f597SEvgeniy Dushistov 			want <<= 1;
8581da177e4SLinus Torvalds  		}
8591da177e4SLinus Torvalds  	}
8603e41f597SEvgeniy Dushistov 
8613e41f597SEvgeniy Dushistov 	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
8623e41f597SEvgeniy Dushistov 		  ucpi->c_cgx);
863abf5d15fSEvgeniy Dushistov 	UFSD("EXIT (FAILED)\n");
86454fb996aSEvgeniy Dushistov 	return INVBLOCK;
8651da177e4SLinus Torvalds }
8661da177e4SLinus Torvalds 
ufs_clusteracct(struct super_block * sb,struct ufs_cg_private_info * ucpi,unsigned blkno,int cnt)8671da177e4SLinus Torvalds static void ufs_clusteracct(struct super_block * sb,
8681da177e4SLinus Torvalds 	struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
8691da177e4SLinus Torvalds {
8701da177e4SLinus Torvalds 	struct ufs_sb_private_info * uspi;
8711da177e4SLinus Torvalds 	int i, start, end, forw, back;
8721da177e4SLinus Torvalds 
8731da177e4SLinus Torvalds 	uspi = UFS_SB(sb)->s_uspi;
8741da177e4SLinus Torvalds 	if (uspi->s_contigsumsize <= 0)
8751da177e4SLinus Torvalds 		return;
8761da177e4SLinus Torvalds 
8771da177e4SLinus Torvalds 	if (cnt > 0)
8789695ef16SEvgeniy Dushistov 		ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
8791da177e4SLinus Torvalds 	else
8809695ef16SEvgeniy Dushistov 		ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
8811da177e4SLinus Torvalds 
8821da177e4SLinus Torvalds 	/*
8831da177e4SLinus Torvalds 	 * Find the size of the cluster going forward.
8841da177e4SLinus Torvalds 	 */
8851da177e4SLinus Torvalds 	start = blkno + 1;
8861da177e4SLinus Torvalds 	end = start + uspi->s_contigsumsize;
8871da177e4SLinus Torvalds 	if ( end >= ucpi->c_nclusterblks)
8881da177e4SLinus Torvalds 		end = ucpi->c_nclusterblks;
8899695ef16SEvgeniy Dushistov 	i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start);
8901da177e4SLinus Torvalds 	if (i > end)
8911da177e4SLinus Torvalds 		i = end;
8921da177e4SLinus Torvalds 	forw = i - start;
8931da177e4SLinus Torvalds 
8941da177e4SLinus Torvalds 	/*
8951da177e4SLinus Torvalds 	 * Find the size of the cluster going backward.
8961da177e4SLinus Torvalds 	 */
8971da177e4SLinus Torvalds 	start = blkno - 1;
8981da177e4SLinus Torvalds 	end = start - uspi->s_contigsumsize;
8991da177e4SLinus Torvalds 	if (end < 0 )
9001da177e4SLinus Torvalds 		end = -1;
9019695ef16SEvgeniy Dushistov 	i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end);
9021da177e4SLinus Torvalds 	if ( i < end)
9031da177e4SLinus Torvalds 		i = end;
9041da177e4SLinus Torvalds 	back = start - i;
9051da177e4SLinus Torvalds 
9061da177e4SLinus Torvalds 	/*
9071da177e4SLinus Torvalds 	 * Account for old cluster and the possibly new forward and
9081da177e4SLinus Torvalds 	 * back clusters.
9091da177e4SLinus Torvalds 	 */
9101da177e4SLinus Torvalds 	i = back + forw + 1;
9111da177e4SLinus Torvalds 	if (i > uspi->s_contigsumsize)
9121da177e4SLinus Torvalds 		i = uspi->s_contigsumsize;
9139695ef16SEvgeniy Dushistov 	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt);
9141da177e4SLinus Torvalds 	if (back > 0)
9159695ef16SEvgeniy Dushistov 		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt);
9161da177e4SLinus Torvalds 	if (forw > 0)
9179695ef16SEvgeniy Dushistov 		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt);
9181da177e4SLinus Torvalds }
9191da177e4SLinus Torvalds 
9201da177e4SLinus Torvalds 
9211da177e4SLinus Torvalds static unsigned char ufs_fragtable_8fpb[] = {
9221da177e4SLinus Torvalds 	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
9231da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
9241da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9251da177e4SLinus Torvalds 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
9261da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9271da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
9281da177e4SLinus Torvalds 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
9291da177e4SLinus Torvalds 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40,
9301da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9311da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
9321da177e4SLinus Torvalds 	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
9331da177e4SLinus Torvalds 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
9341da177e4SLinus Torvalds 	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
9351da177e4SLinus Torvalds 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12,
9361da177e4SLinus Torvalds 	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C,
9371da177e4SLinus Torvalds 	0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
9381da177e4SLinus Torvalds };
9391da177e4SLinus Torvalds 
9401da177e4SLinus Torvalds static unsigned char ufs_fragtable_other[] = {
9411da177e4SLinus Torvalds 	0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A,
9421da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9431da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9441da177e4SLinus Torvalds 	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
9451da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9461da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9471da177e4SLinus Torvalds 	0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE,
9481da177e4SLinus Torvalds 	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
9491da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9501da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9511da177e4SLinus Torvalds 	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
9521da177e4SLinus Torvalds 	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
9531da177e4SLinus Torvalds 	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
9541da177e4SLinus Torvalds 	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E,	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
9551da177e4SLinus Torvalds 	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
9561da177e4SLinus Torvalds 	0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A,
9571da177e4SLinus Torvalds };
958