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