balloc.c 27.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 *  linux/fs/ufs/balloc.c
 *
 * Copyright (C) 1998
 * Daniel Pirkl <daniel.pirkl@email.cz>
 * Charles University, Faculty of Mathematics and Physics
7 8
 *
 * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16
 */

#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/time.h>
#include <linux/string.h>
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
17
#include <linux/capability.h>
L
Linus Torvalds 已提交
18 19 20
#include <linux/bitops.h>
#include <asm/byteorder.h>

21
#include "ufs_fs.h"
22
#include "ufs.h"
L
Linus Torvalds 已提交
23 24 25
#include "swab.h"
#include "util.h"

26 27 28 29 30 31
#define INVBLOCK ((u64)-1L)

static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *);
static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
L
Linus Torvalds 已提交
32 33 34 35 36 37
static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);

/*
 * Free 'count' fragments from fragment number 'fragment'
 */
38
void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
39
{
L
Linus Torvalds 已提交
40 41 42 43 44
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
45 46
	unsigned cgno, bit, end_bit, bbase, blkmap, i;
	u64 blkno;
L
Linus Torvalds 已提交
47 48 49
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
50
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
51
	
52 53
	UFSD("ENTER, fragment %llu, count %u\n",
	     (unsigned long long)fragment, count);
L
Linus Torvalds 已提交
54 55 56 57 58 59
	
	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
		ufs_error (sb, "ufs_free_fragments", "internal error");
	
	lock_super(sb);
	
60 61
	cgno = ufs_dtog(uspi, fragment);
	bit = ufs_dtogd(uspi, fragment);
L
Linus Torvalds 已提交
62 63 64 65 66 67 68 69
	if (cgno >= uspi->s_ncg) {
		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
		goto failed;
	}
		
	ucpi = ufs_load_cylinder (sb, cgno);
	if (!ucpi) 
		goto failed;
E
Evgeniy Dushistov 已提交
70
	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
71 72 73 74 75 76 77
	if (!ufs_cg_chkmagic(sb, ucg)) {
		ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
		goto failed;
	}

	end_bit = bit + count;
	bbase = ufs_blknum (bit);
E
Evgeniy Dushistov 已提交
78
	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
L
Linus Torvalds 已提交
79 80
	ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
	for (i = bit; i < end_bit; i++) {
E
Evgeniy Dushistov 已提交
81 82
		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
E
Evgeniy 已提交
83 84 85
		else 
			ufs_error (sb, "ufs_free_fragments",
				   "bit already cleared for fragment %u", i);
L
Linus Torvalds 已提交
86 87 88 89 90 91
	}
	
	DQUOT_FREE_BLOCK (inode, count);

	
	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
92
	uspi->cs_total.cs_nffree += count;
L
Linus Torvalds 已提交
93
	fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
E
Evgeniy Dushistov 已提交
94
	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
L
Linus Torvalds 已提交
95 96 97 98 99 100
	ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);

	/*
	 * Trying to reassemble free fragments into block
	 */
	blkno = ufs_fragstoblks (bbase);
E
Evgeniy Dushistov 已提交
101
	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
L
Linus Torvalds 已提交
102
		fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
103
		uspi->cs_total.cs_nffree -= uspi->s_fpb;
L
Linus Torvalds 已提交
104 105 106 107
		fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
			ufs_clusteracct (sb, ucpi, blkno, 1);
		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
108
		uspi->cs_total.cs_nbfree++;
L
Linus Torvalds 已提交
109
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
110 111 112 113 114 115 116
		if (uspi->fs_magic != UFS2_MAGIC) {
			unsigned cylno = ufs_cbtocylno (bbase);

			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
						  ufs_cbtorpos(bbase)), 1);
			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
		}
L
Linus Torvalds 已提交
117 118
	}
	
E
Evgeniy Dushistov 已提交
119 120
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
121
	if (sb->s_flags & MS_SYNCHRONOUS) {
122
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
123
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
124 125 126 127
	}
	sb->s_dirt = 1;
	
	unlock_super (sb);
E
Evgeniy Dushistov 已提交
128
	UFSD("EXIT\n");
L
Linus Torvalds 已提交
129 130 131 132
	return;

failed:
	unlock_super (sb);
E
Evgeniy Dushistov 已提交
133
	UFSD("EXIT (FAILED)\n");
L
Linus Torvalds 已提交
134 135 136 137 138 139
	return;
}

/*
 * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
 */
140
void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
141
{
L
Linus Torvalds 已提交
142 143 144 145 146
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
147 148
	unsigned overflow, cgno, bit, end_bit, i;
	u64 blkno;
L
Linus Torvalds 已提交
149 150 151
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
152
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
153

154 155
	UFSD("ENTER, fragment %llu, count %u\n",
	     (unsigned long long)fragment, count);
L
Linus Torvalds 已提交
156 157 158
	
	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
		ufs_error (sb, "ufs_free_blocks", "internal error, "
159 160
			   "fragment %llu, count %u\n",
			   (unsigned long long)fragment, count);
L
Linus Torvalds 已提交
161 162 163 164 165 166 167
		goto failed;
	}

	lock_super(sb);
	
do_more:
	overflow = 0;
168 169
	cgno = ufs_dtog(uspi, fragment);
	bit = ufs_dtogd(uspi, fragment);
L
Linus Torvalds 已提交
170 171
	if (cgno >= uspi->s_ncg) {
		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
172
		goto failed_unlock;
L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180 181 182
	}
	end_bit = bit + count;
	if (end_bit > uspi->s_fpg) {
		overflow = bit + count - uspi->s_fpg;
		count -= overflow;
		end_bit -= overflow;
	}

	ucpi = ufs_load_cylinder (sb, cgno);
	if (!ucpi) 
183
		goto failed_unlock;
E
Evgeniy Dushistov 已提交
184
	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
185 186
	if (!ufs_cg_chkmagic(sb, ucg)) {
		ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
187
		goto failed_unlock;
L
Linus Torvalds 已提交
188 189 190 191
	}

	for (i = bit; i < end_bit; i += uspi->s_fpb) {
		blkno = ufs_fragstoblks(i);
E
Evgeniy Dushistov 已提交
192
		if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
L
Linus Torvalds 已提交
193 194
			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
		}
E
Evgeniy Dushistov 已提交
195
		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
L
Linus Torvalds 已提交
196 197 198 199 200
		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
			ufs_clusteracct (sb, ucpi, blkno, 1);
		DQUOT_FREE_BLOCK(inode, uspi->s_fpb);

		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
201
		uspi->cs_total.cs_nbfree++;
L
Linus Torvalds 已提交
202
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
203 204 205 206 207 208 209 210

		if (uspi->fs_magic != UFS2_MAGIC) {
			unsigned cylno = ufs_cbtocylno(i);

			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
						  ufs_cbtorpos(i)), 1);
			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
		}
L
Linus Torvalds 已提交
211 212
	}

E
Evgeniy Dushistov 已提交
213 214
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
215
	if (sb->s_flags & MS_SYNCHRONOUS) {
216
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
217
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
218 219 220 221 222 223 224 225 226 227
	}

	if (overflow) {
		fragment += count;
		count = overflow;
		goto do_more;
	}

	sb->s_dirt = 1;
	unlock_super (sb);
E
Evgeniy Dushistov 已提交
228
	UFSD("EXIT\n");
L
Linus Torvalds 已提交
229 230
	return;

231
failed_unlock:
L
Linus Torvalds 已提交
232
	unlock_super (sb);
233
failed:
E
Evgeniy Dushistov 已提交
234
	UFSD("EXIT (FAILED)\n");
L
Linus Torvalds 已提交
235 236 237
	return;
}

238 239 240 241 242 243 244 245 246 247
/*
 * Modify inode page cache in such way:
 * have - blocks with b_blocknr equal to oldb...oldb+count-1
 * get - blocks with b_blocknr equal to newb...newb+count-1
 * also we suppose that oldb...oldb+count-1 blocks
 * situated at the end of file.
 *
 * We can come here from ufs_writepage or ufs_prepare_write,
 * locked_page is argument of these functions, so we already lock it.
 */
248 249 250
static void ufs_change_blocknr(struct inode *inode, sector_t beg,
			       unsigned int count, sector_t oldb,
			       sector_t newb, struct page *locked_page)
251
{
252 253 254
	const unsigned blks_per_page =
		1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
	const unsigned mask = blks_per_page - 1;
255
	struct address_space * const mapping = inode->i_mapping;
256 257 258
	pgoff_t index, cur_index, last_index;
	unsigned pos, j, lblock;
	sector_t end, i;
259 260 261
	struct page *page;
	struct buffer_head *head, *bh;

262 263 264
	UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n",
	      inode->i_ino, count,
	     (unsigned long long)oldb, (unsigned long long)newb);
265

266
	BUG_ON(!locked_page);
267 268
	BUG_ON(!PageLocked(locked_page));

269
	cur_index = locked_page->index;
270 271 272 273
	end = count + beg;
	last_index = end >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
	for (i = beg; i < end; i = (i | mask) + 1) {
		index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
274 275 276

		if (likely(cur_index != index)) {
			page = ufs_get_locked_page(mapping, index);
277 278 279 280 281 282
			if (!page)/* it was truncated */
				continue;
			if (IS_ERR(page)) {/* or EIO */
				ufs_error(inode->i_sb, __FUNCTION__,
					  "read of page %llu failed\n",
					  (unsigned long long)index);
283
				continue;
284
			}
285 286 287 288 289
		} else
			page = locked_page;

		head = page_buffers(page);
		bh = head;
290
		pos = i & mask;
291 292
		for (j = 0; j < pos; ++j)
			bh = bh->b_this_page;
293 294 295 296 297 298 299


		if (unlikely(index == last_index))
			lblock = end & mask;
		else
			lblock = blks_per_page;

300
		do {
301 302 303 304 305 306 307 308 309 310 311 312 313
			if (j >= lblock)
				break;
			pos = (i - beg) + j;

			if (!buffer_mapped(bh))
					map_bh(bh, inode->i_sb, oldb + pos);
			if (!buffer_uptodate(bh)) {
				ll_rw_block(READ, 1, &bh);
				wait_on_buffer(bh);
				if (!buffer_uptodate(bh)) {
					ufs_error(inode->i_sb, __FUNCTION__,
						  "read of block failed\n");
					break;
314
				}
315 316
			}

317
			UFSD(" change from %llu to %llu, pos %u\n",
318 319
			     (unsigned long long)(pos + oldb),
			     (unsigned long long)(pos + newb), pos);
320 321 322 323 324 325

			bh->b_blocknr = newb + pos;
			unmap_underlying_metadata(bh->b_bdev,
						  bh->b_blocknr);
			mark_buffer_dirty(bh);
			++j;
326 327 328
			bh = bh->b_this_page;
		} while (bh != head);

329 330
		if (likely(cur_index != index))
			ufs_put_locked_page(page);
331
 	}
E
Evgeniy Dushistov 已提交
332
	UFSD("EXIT\n");
333 334
}

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
			    int sync)
{
	struct buffer_head *bh;
	sector_t end = beg + n;

	for (; beg < end; ++beg) {
		bh = sb_getblk(inode->i_sb, beg);
		lock_buffer(bh);
		memset(bh->b_data, 0, inode->i_sb->s_blocksize);
		set_buffer_uptodate(bh);
		mark_buffer_dirty(bh);
		unlock_buffer(bh);
		if (IS_SYNC(inode) || sync)
			sync_dirty_buffer(bh);
		brelse(bh);
	}
}

354 355 356
u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
			   u64 goal, unsigned count, int *err,
			   struct page *locked_page)
L
Linus Torvalds 已提交
357 358 359 360
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
361 362
	unsigned cgno, oldcount, newcount;
	u64 tmp, request, result;
L
Linus Torvalds 已提交
363
	
364 365 366
	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
	     inode->i_ino, (unsigned long long)fragment,
	     (unsigned long long)goal, count);
L
Linus Torvalds 已提交
367 368 369
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
370
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
371 372 373
	*err = -ENOSPC;

	lock_super (sb);
374 375
	tmp = ufs_data_ptr_to_cpu(sb, p);

L
Linus Torvalds 已提交
376
	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
377 378 379
		ufs_warning(sb, "ufs_new_fragments", "internal warning"
			    " fragment %llu, count %u",
			    (unsigned long long)fragment, count);
L
Linus Torvalds 已提交
380 381 382 383 384 385 386 387 388 389
		count = uspi->s_fpb - ufs_fragnum(fragment); 
	}
	oldcount = ufs_fragnum (fragment);
	newcount = oldcount + count;

	/*
	 * Somebody else has just allocated our fragments
	 */
	if (oldcount) {
		if (!tmp) {
390 391 392 393 394 395
			ufs_error(sb, "ufs_new_fragments", "internal error, "
				  "fragment %llu, tmp %llu\n",
				  (unsigned long long)fragment,
				  (unsigned long long)tmp);
			unlock_super(sb);
			return INVBLOCK;
L
Linus Torvalds 已提交
396 397
		}
		if (fragment < UFS_I(inode)->i_lastfrag) {
E
Evgeniy Dushistov 已提交
398
			UFSD("EXIT (ALREADY ALLOCATED)\n");
L
Linus Torvalds 已提交
399 400 401 402 403 404
			unlock_super (sb);
			return 0;
		}
	}
	else {
		if (tmp) {
E
Evgeniy Dushistov 已提交
405
			UFSD("EXIT (ALREADY ALLOCATED)\n");
L
Linus Torvalds 已提交
406 407 408 409 410 411 412 413
			unlock_super(sb);
			return 0;
		}
	}

	/*
	 * There is not enough space for user on the device
	 */
414
	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
L
Linus Torvalds 已提交
415
		unlock_super (sb);
E
Evgeniy Dushistov 已提交
416
		UFSD("EXIT (FAILED)\n");
L
Linus Torvalds 已提交
417 418 419 420 421 422 423 424
		return 0;
	}

	if (goal >= uspi->s_size) 
		goal = 0;
	if (goal == 0) 
		cgno = ufs_inotocg (inode->i_ino);
	else
425
		cgno = ufs_dtog(uspi, goal);
L
Linus Torvalds 已提交
426 427 428 429 430 431 432
	 
	/*
	 * allocate new fragment
	 */
	if (oldcount == 0) {
		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
		if (result) {
433
			ufs_cpu_to_data_ptr(sb, p, result);
L
Linus Torvalds 已提交
434
			*err = 0;
435 436 437 438 439
			UFS_I(inode)->i_lastfrag =
				max_t(u32, UFS_I(inode)->i_lastfrag,
				      fragment + count);
			ufs_clear_frags(inode, result + oldcount,
					newcount - oldcount, locked_page != NULL);
L
Linus Torvalds 已提交
440 441
		}
		unlock_super(sb);
442
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
L
Linus Torvalds 已提交
443 444 445 446 447 448 449 450 451 452
		return result;
	}

	/*
	 * resize block
	 */
	result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);
	if (result) {
		*err = 0;
		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
453 454
		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
				locked_page != NULL);
L
Linus Torvalds 已提交
455
		unlock_super(sb);
456
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
L
Linus Torvalds 已提交
457 458 459 460 461 462 463 464 465
		return result;
	}

	/*
	 * allocate new block and move data
	 */
	switch (fs32_to_cpu(sb, usb1->fs_optim)) {
	    case UFS_OPTSPACE:
		request = newcount;
466 467
		if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
		    > uspi->s_dsize * uspi->s_minfree / (2 * 100))
L
Linus Torvalds 已提交
468 469 470 471 472 473 474 475
			break;
		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
		break;
	    default:
		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
	
	    case UFS_OPTTIME:
		request = uspi->s_fpb;
476
		if (uspi->cs_total.cs_nffree < uspi->s_dsize *
L
Linus Torvalds 已提交
477 478 479 480 481 482 483
		    (uspi->s_minfree - 2) / 100)
			break;
		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
		break;
	}
	result = ufs_alloc_fragments (inode, cgno, goal, request, err);
	if (result) {
484 485
		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
				locked_page != NULL);
486 487 488
		ufs_change_blocknr(inode, fragment - oldcount, oldcount,
				   uspi->s_sbbase + tmp,
				   uspi->s_sbbase + result, locked_page);
489
		ufs_cpu_to_data_ptr(sb, p, result);
L
Linus Torvalds 已提交
490 491 492 493 494 495
		*err = 0;
		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
		unlock_super(sb);
		if (newcount < request)
			ufs_free_fragments (inode, result + newcount, request - newcount);
		ufs_free_fragments (inode, tmp, oldcount);
496
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
L
Linus Torvalds 已提交
497 498 499 500
		return result;
	}

	unlock_super(sb);
E
Evgeniy Dushistov 已提交
501
	UFSD("EXIT (FAILED)\n");
L
Linus Torvalds 已提交
502 503 504
	return 0;
}		

505 506
static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
			     unsigned oldcount, unsigned newcount, int *err)
L
Linus Torvalds 已提交
507 508 509 510 511 512 513 514
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	unsigned cgno, fragno, fragoff, count, fragsize, i;
	
515 516
	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
	     (unsigned long long)fragment, oldcount, newcount);
L
Linus Torvalds 已提交
517 518 519
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
520
	usb1 = ubh_get_usb_first (uspi);
L
Linus Torvalds 已提交
521 522
	count = newcount - oldcount;
	
523
	cgno = ufs_dtog(uspi, fragment);
L
Linus Torvalds 已提交
524 525 526 527 528 529 530
	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
		return 0;
	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
		return 0;
	ucpi = ufs_load_cylinder (sb, cgno);
	if (!ucpi)
		return 0;
E
Evgeniy Dushistov 已提交
531
	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
532 533 534 535 536 537
	if (!ufs_cg_chkmagic(sb, ucg)) {
		ufs_panic (sb, "ufs_add_fragments",
			"internal error, bad magic number on cg %u", cgno);
		return 0;
	}

538
	fragno = ufs_dtogd(uspi, fragment);
L
Linus Torvalds 已提交
539 540
	fragoff = ufs_fragnum (fragno);
	for (i = oldcount; i < newcount; i++)
E
Evgeniy Dushistov 已提交
541
		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
L
Linus Torvalds 已提交
542 543 544 545 546 547
			return 0;
	/*
	 * Block can be extended
	 */
	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
	for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
E
Evgeniy Dushistov 已提交
548
		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
L
Linus Torvalds 已提交
549 550 551 552 553 554 555 556 557
			break;
	fragsize = i - oldcount;
	if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
		ufs_panic (sb, "ufs_add_fragments",
			"internal error or corrupted bitmap on cg %u", cgno);
	fs32_sub(sb, &ucg->cg_frsum[fragsize], 1);
	if (fragsize != count)
		fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
	for (i = oldcount; i < newcount; i++)
E
Evgeniy Dushistov 已提交
558
		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
L
Linus Torvalds 已提交
559 560 561 562 563 564 565
	if(DQUOT_ALLOC_BLOCK(inode, count)) {
		*err = -EDQUOT;
		return 0;
	}

	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
566
	uspi->cs_total.cs_nffree -= count;
L
Linus Torvalds 已提交
567
	
E
Evgeniy Dushistov 已提交
568 569
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
570
	if (sb->s_flags & MS_SYNCHRONOUS) {
571
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
572
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
573 574 575
	}
	sb->s_dirt = 1;

576
	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
L
Linus Torvalds 已提交
577 578 579 580 581 582 583 584 585 586 587 588
	
	return fragment;
}

#define UFS_TEST_FREE_SPACE_CG \
	ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \
	if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \
		goto cg_found; \
	for (k = count; k < uspi->s_fpb; k++) \
		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
			goto cg_found; 

589 590
static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
			       u64 goal, unsigned count, int *err)
L
Linus Torvalds 已提交
591 592 593 594 595 596
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
597 598
	unsigned oldcg, i, j, k, allocsize;
	u64 result;
L
Linus Torvalds 已提交
599
	
600 601
	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
	     inode->i_ino, cgno, (unsigned long long)goal, count);
L
Linus Torvalds 已提交
602 603 604

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
605
	usb1 = ubh_get_usb_first(uspi);
L
Linus Torvalds 已提交
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
	oldcg = cgno;
	
	/*
	 * 1. searching on preferred cylinder group
	 */
	UFS_TEST_FREE_SPACE_CG

	/*
	 * 2. quadratic rehash
	 */
	for (j = 1; j < uspi->s_ncg; j *= 2) {
		cgno += j;
		if (cgno >= uspi->s_ncg) 
			cgno -= uspi->s_ncg;
		UFS_TEST_FREE_SPACE_CG
	}

	/*
	 * 3. brute force search
	 * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step )
	 */
	cgno = (oldcg + 1) % uspi->s_ncg;
	for (j = 2; j < uspi->s_ncg; j++) {
		cgno++;
		if (cgno >= uspi->s_ncg)
			cgno = 0;
		UFS_TEST_FREE_SPACE_CG
	}
	
E
Evgeniy Dushistov 已提交
635
	UFSD("EXIT (FAILED)\n");
L
Linus Torvalds 已提交
636 637 638 639 640 641
	return 0;

cg_found:
	ucpi = ufs_load_cylinder (sb, cgno);
	if (!ucpi)
		return 0;
E
Evgeniy Dushistov 已提交
642
	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
643 644 645 646 647 648 649
	if (!ufs_cg_chkmagic(sb, ucg)) 
		ufs_panic (sb, "ufs_alloc_fragments",
			"internal error, bad magic number on cg %u", cgno);
	ucg->cg_time = cpu_to_fs32(sb, get_seconds());

	if (count == uspi->s_fpb) {
		result = ufs_alloccg_block (inode, ucpi, goal, err);
650
		if (result == INVBLOCK)
L
Linus Torvalds 已提交
651 652 653 654 655 656 657 658 659 660
			return 0;
		goto succed;
	}

	for (allocsize = count; allocsize < uspi->s_fpb; allocsize++)
		if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0)
			break;
	
	if (allocsize == uspi->s_fpb) {
		result = ufs_alloccg_block (inode, ucpi, goal, err);
661
		if (result == INVBLOCK)
L
Linus Torvalds 已提交
662
			return 0;
663
		goal = ufs_dtogd(uspi, result);
L
Linus Torvalds 已提交
664
		for (i = count; i < uspi->s_fpb; i++)
E
Evgeniy Dushistov 已提交
665
			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
L
Linus Torvalds 已提交
666 667 668 669
		i = uspi->s_fpb - count;
		DQUOT_FREE_BLOCK(inode, i);

		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
670
		uspi->cs_total.cs_nffree += i;
L
Linus Torvalds 已提交
671 672 673 674 675 676
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
		fs32_add(sb, &ucg->cg_frsum[i], 1);
		goto succed;
	}

	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
677
	if (result == INVBLOCK)
L
Linus Torvalds 已提交
678 679 680 681 682 683
		return 0;
	if(DQUOT_ALLOC_BLOCK(inode, count)) {
		*err = -EDQUOT;
		return 0;
	}
	for (i = 0; i < count; i++)
E
Evgeniy Dushistov 已提交
684
		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
L
Linus Torvalds 已提交
685 686
	
	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
687
	uspi->cs_total.cs_nffree -= count;
L
Linus Torvalds 已提交
688 689 690 691 692 693 694
	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
	fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);

	if (count != allocsize)
		fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);

succed:
E
Evgeniy Dushistov 已提交
695 696
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
697
	if (sb->s_flags & MS_SYNCHRONOUS) {
698
		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
E
Evgeniy Dushistov 已提交
699
		ubh_wait_on_buffer (UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
700 701 702 703
	}
	sb->s_dirt = 1;

	result += cgno * uspi->s_fpg;
704
	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
L
Linus Torvalds 已提交
705 706 707
	return result;
}

708 709 710
static u64 ufs_alloccg_block(struct inode *inode,
			     struct ufs_cg_private_info *ucpi,
			     u64 goal, int *err)
L
Linus Torvalds 已提交
711 712 713 714 715
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cylinder_group * ucg;
716
	u64 result, blkno;
L
Linus Torvalds 已提交
717

718
	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
L
Linus Torvalds 已提交
719 720 721

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
E
Evgeniy 已提交
722
	usb1 = ubh_get_usb_first(uspi);
E
Evgeniy Dushistov 已提交
723
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
724 725 726 727 728 729

	if (goal == 0) {
		goal = ucpi->c_rotor;
		goto norot;
	}
	goal = ufs_blknum (goal);
730
	goal = ufs_dtogd(uspi, goal);
L
Linus Torvalds 已提交
731 732 733 734
	
	/*
	 * If the requested block is available, use it.
	 */
E
Evgeniy Dushistov 已提交
735
	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) {
L
Linus Torvalds 已提交
736 737 738 739 740 741
		result = goal;
		goto gotit;
	}
	
norot:	
	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
742 743
	if (result == INVBLOCK)
		return INVBLOCK;
L
Linus Torvalds 已提交
744 745 746
	ucpi->c_rotor = result;
gotit:
	blkno = ufs_fragstoblks(result);
E
Evgeniy Dushistov 已提交
747
	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
L
Linus Torvalds 已提交
748 749 750 751
	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
		ufs_clusteracct (sb, ucpi, blkno, -1);
	if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
		*err = -EDQUOT;
752
		return INVBLOCK;
L
Linus Torvalds 已提交
753 754 755
	}

	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
756
	uspi->cs_total.cs_nbfree--;
L
Linus Torvalds 已提交
757
	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
758 759 760 761 762 763 764 765

	if (uspi->fs_magic != UFS2_MAGIC) {
		unsigned cylno = ufs_cbtocylno((unsigned)result);

		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
					  ufs_cbtorpos((unsigned)result)), 1);
		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
	}
L
Linus Torvalds 已提交
766
	
767
	UFSD("EXIT, result %llu\n", (unsigned long long)result);
L
Linus Torvalds 已提交
768 769 770 771

	return result;
}

772 773 774 775
static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
			  struct ufs_buffer_head *ubh,
			  unsigned begin, unsigned size,
			  unsigned char *table, unsigned char mask)
L
Linus Torvalds 已提交
776
{
777 778
	unsigned rest, offset;
	unsigned char *cp;
L
Linus Torvalds 已提交
779 780
	

781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
	offset = begin & ~uspi->s_fmask;
	begin >>= uspi->s_fshift;
	for (;;) {
		if ((offset + size) < uspi->s_fsize)
			rest = size;
		else
			rest = uspi->s_fsize - offset;
		size -= rest;
		cp = ubh->bh[begin]->b_data + offset;
		while ((table[*cp++] & mask) == 0 && --rest)
			;
		if (rest || !size)
			break;
		begin++;
		offset = 0;
	}
	return (size + rest);
}

/*
 * Find a block of the specified size in the specified cylinder group.
 * @sp: pointer to super block
 * @ucpi: pointer to cylinder group info
 * @goal: near which block we want find new one
 * @count: specified size
 */
807 808 809
static u64 ufs_bitmap_search(struct super_block *sb,
			     struct ufs_cg_private_info *ucpi,
			     u64 goal, unsigned count)
810 811 812 813 814 815 816 817 818 819 820 821 822 823
{
	/*
	 * Bit patterns for identifying fragments in the block map
	 * used as ((map & mask_arr) == want_arr)
	 */
	static const int mask_arr[9] = {
		0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
	};
	static const int want_arr[9] = {
		0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
	};
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	struct ufs_super_block_first *usb1;
	struct ufs_cylinder_group *ucg;
824
	unsigned start, length, loc;
825
	unsigned pos, want, blockmap, mask, end;
826
	u64 result;
827

828 829
	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
	     (unsigned long long)goal, count);
830

E
Evgeniy 已提交
831
	usb1 = ubh_get_usb_first (uspi);
E
Evgeniy Dushistov 已提交
832
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
L
Linus Torvalds 已提交
833 834

	if (goal)
835
		start = ufs_dtogd(uspi, goal) >> 3;
L
Linus Torvalds 已提交
836 837 838 839
	else
		start = ucpi->c_frotor >> 3;
		
	length = ((uspi->s_fpg + 7) >> 3) - start;
840
	loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length,
L
Linus Torvalds 已提交
841 842
		(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
		1 << (count - 1 + (uspi->s_fpb & 7))); 
843
	if (loc == 0) {
L
Linus Torvalds 已提交
844
		length = start + 1;
845 846 847 848 849 850 851 852 853 854
		loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length,
				(uspi->s_fpb == 8) ? ufs_fragtable_8fpb :
				ufs_fragtable_other,
				1 << (count - 1 + (uspi->s_fpb & 7)));
		if (loc == 0) {
			ufs_error(sb, "ufs_bitmap_search",
				  "bitmap corrupted on cg %u, start %u,"
				  " length %u, count %u, freeoff %u\n",
				  ucpi->c_cgx, start, length, count,
				  ucpi->c_freeoff);
855
			return INVBLOCK;
L
Linus Torvalds 已提交
856 857 858
		}
		start = 0;
	}
859
	result = (start + length - loc) << 3;
L
Linus Torvalds 已提交
860 861 862 863 864
	ucpi->c_frotor = result;

	/*
	 * found the byte in the map
	 */
865 866 867 868 869 870 871 872

	for (end = result + 8; result < end; result += uspi->s_fpb) {
		blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result);
		blockmap <<= 1;
		mask = mask_arr[count];
		want = want_arr[count];
		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
			if ((blockmap & mask) == want) {
873 874
				UFSD("EXIT, result %llu\n",
				     (unsigned long long)result);
875 876 877 878 879 880 881 882 883
				return result + pos;
 			}
			mask <<= 1;
			want <<= 1;
 		}
 	}

	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
		  ucpi->c_cgx);
E
Evgeniy Dushistov 已提交
884
	UFSD("EXIT (FAILED)\n");
885
	return INVBLOCK;
L
Linus Torvalds 已提交
886 887 888 889 890 891 892 893 894 895 896 897 898
}

static void ufs_clusteracct(struct super_block * sb,
	struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
{
	struct ufs_sb_private_info * uspi;
	int i, start, end, forw, back;
	
	uspi = UFS_SB(sb)->s_uspi;
	if (uspi->s_contigsumsize <= 0)
		return;

	if (cnt > 0)
E
Evgeniy Dushistov 已提交
899
		ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
L
Linus Torvalds 已提交
900
	else
E
Evgeniy Dushistov 已提交
901
		ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
L
Linus Torvalds 已提交
902 903 904 905 906 907 908 909

	/*
	 * Find the size of the cluster going forward.
	 */
	start = blkno + 1;
	end = start + uspi->s_contigsumsize;
	if ( end >= ucpi->c_nclusterblks)
		end = ucpi->c_nclusterblks;
E
Evgeniy Dushistov 已提交
910
	i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start);
L
Linus Torvalds 已提交
911 912 913 914 915 916 917 918 919 920 921
	if (i > end)
		i = end;
	forw = i - start;
	
	/*
	 * Find the size of the cluster going backward.
	 */
	start = blkno - 1;
	end = start - uspi->s_contigsumsize;
	if (end < 0 ) 
		end = -1;
E
Evgeniy Dushistov 已提交
922
	i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end);
L
Linus Torvalds 已提交
923 924 925 926 927 928 929 930 931 932 933
	if ( i < end) 
		i = end;
	back = start - i;
	
	/*
	 * Account for old cluster and the possibly new forward and
	 * back clusters.
	 */
	i = back + forw + 1;
	if (i > uspi->s_contigsumsize)
		i = uspi->s_contigsumsize;
E
Evgeniy Dushistov 已提交
934
	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt);
L
Linus Torvalds 已提交
935
	if (back > 0)
E
Evgeniy Dushistov 已提交
936
		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt);
L
Linus Torvalds 已提交
937
	if (forw > 0)
E
Evgeniy Dushistov 已提交
938
		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt);
L
Linus Torvalds 已提交
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
}


static unsigned char ufs_fragtable_8fpb[] = {
	0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,	
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
	0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
	0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12,
	0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C,
	0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
};

static unsigned char ufs_fragtable_other[] = {
	0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE,
	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
	0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E,	0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
	0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
	0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A,
};