blob: b01804baa120f630c1fe2480a970086e96e58cde [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/ufs/balloc.c
3 *
4 * Copyright (C) 1998
5 * Daniel Pirkl <daniel.pirkl@email.cz>
6 * Charles University, Faculty of Mathematics and Physics
7 */
8
9#include <linux/fs.h>
10#include <linux/ufs_fs.h>
11#include <linux/stat.h>
12#include <linux/time.h>
13#include <linux/string.h>
14#include <linux/quotaops.h>
15#include <linux/buffer_head.h>
Randy Dunlap16f7e0f2006-01-11 12:17:46 -080016#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/sched.h>
18#include <linux/bitops.h>
19#include <asm/byteorder.h>
20
21#include "swab.h"
22#include "util.h"
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
25static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
26static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
27static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
28static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
29static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
30
31/*
32 * Free 'count' fragments from fragment number 'fragment'
33 */
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -070034void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
35{
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 struct super_block * sb;
37 struct ufs_sb_private_info * uspi;
38 struct ufs_super_block_first * usb1;
39 struct ufs_cg_private_info * ucpi;
40 struct ufs_cylinder_group * ucg;
41 unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;
42
43 sb = inode->i_sb;
44 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +030045 usb1 = ubh_get_usb_first(uspi);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -070047 UFSD("ENTER, fragment %u, count %u\n", fragment, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49 if (ufs_fragnum(fragment) + count > uspi->s_fpg)
50 ufs_error (sb, "ufs_free_fragments", "internal error");
51
52 lock_super(sb);
53
54 cgno = ufs_dtog(fragment);
55 bit = ufs_dtogd(fragment);
56 if (cgno >= uspi->s_ncg) {
57 ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
58 goto failed;
59 }
60
61 ucpi = ufs_load_cylinder (sb, cgno);
62 if (!ucpi)
63 goto failed;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -070064 ucg = ubh_get_ucg (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 if (!ufs_cg_chkmagic(sb, ucg)) {
66 ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
67 goto failed;
68 }
69
70 end_bit = bit + count;
71 bbase = ufs_blknum (bit);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -070072 blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
74 for (i = bit; i < end_bit; i++) {
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -070075 if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
76 ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
Evgeniy7b4ee732006-01-14 11:42:06 +030077 else
78 ufs_error (sb, "ufs_free_fragments",
79 "bit already cleared for fragment %u", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 }
81
82 DQUOT_FREE_BLOCK (inode, count);
83
84
85 fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -070086 uspi->cs_total.cs_nffree += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -070088 blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
90
91 /*
92 * Trying to reassemble free fragments into block
93 */
94 blkno = ufs_fragstoblks (bbase);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -070095 if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -070097 uspi->cs_total.cs_nffree -= uspi->s_fpb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
99 if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
100 ufs_clusteracct (sb, ucpi, blkno, 1);
101 fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700102 uspi->cs_total.cs_nbfree++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
104 cylno = ufs_cbtocylno (bbase);
105 fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
106 fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
107 }
108
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700109 ubh_mark_buffer_dirty (USPI_UBH(uspi));
110 ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 if (sb->s_flags & MS_SYNCHRONOUS) {
Evgeniy Dushistov098d5af2006-06-25 05:47:31 -0700112 ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700113 ubh_wait_on_buffer (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 }
115 sb->s_dirt = 1;
116
117 unlock_super (sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700118 UFSD("EXIT\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 return;
120
121failed:
122 unlock_super (sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700123 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 return;
125}
126
127/*
128 * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
129 */
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700130void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
131{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 struct super_block * sb;
133 struct ufs_sb_private_info * uspi;
134 struct ufs_super_block_first * usb1;
135 struct ufs_cg_private_info * ucpi;
136 struct ufs_cylinder_group * ucg;
137 unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;
138
139 sb = inode->i_sb;
140 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +0300141 usb1 = ubh_get_usb_first(uspi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700143 UFSD("ENTER, fragment %u, count %u\n", fragment, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145 if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
146 ufs_error (sb, "ufs_free_blocks", "internal error, "
147 "fragment %u, count %u\n", fragment, count);
148 goto failed;
149 }
150
151 lock_super(sb);
152
153do_more:
154 overflow = 0;
155 cgno = ufs_dtog (fragment);
156 bit = ufs_dtogd (fragment);
157 if (cgno >= uspi->s_ncg) {
158 ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
Evgeniy Dushistov2e006392006-06-25 05:47:26 -0700159 goto failed_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 }
161 end_bit = bit + count;
162 if (end_bit > uspi->s_fpg) {
163 overflow = bit + count - uspi->s_fpg;
164 count -= overflow;
165 end_bit -= overflow;
166 }
167
168 ucpi = ufs_load_cylinder (sb, cgno);
169 if (!ucpi)
Evgeniy Dushistov2e006392006-06-25 05:47:26 -0700170 goto failed_unlock;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700171 ucg = ubh_get_ucg (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 if (!ufs_cg_chkmagic(sb, ucg)) {
173 ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
Evgeniy Dushistov2e006392006-06-25 05:47:26 -0700174 goto failed_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 }
176
177 for (i = bit; i < end_bit; i += uspi->s_fpb) {
178 blkno = ufs_fragstoblks(i);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700179 if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
181 }
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700182 ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
184 ufs_clusteracct (sb, ucpi, blkno, 1);
185 DQUOT_FREE_BLOCK(inode, uspi->s_fpb);
186
187 fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700188 uspi->cs_total.cs_nbfree++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
190 cylno = ufs_cbtocylno(i);
191 fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
192 fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
193 }
194
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700195 ubh_mark_buffer_dirty (USPI_UBH(uspi));
196 ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 if (sb->s_flags & MS_SYNCHRONOUS) {
Evgeniy Dushistov098d5af2006-06-25 05:47:31 -0700198 ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700199 ubh_wait_on_buffer (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 }
201
202 if (overflow) {
203 fragment += count;
204 count = overflow;
205 goto do_more;
206 }
207
208 sb->s_dirt = 1;
209 unlock_super (sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700210 UFSD("EXIT\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return;
212
Evgeniy Dushistov2e006392006-06-25 05:47:26 -0700213failed_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 unlock_super (sb);
Evgeniy Dushistov2e006392006-06-25 05:47:26 -0700215failed:
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700216 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 return;
218}
219
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700220/*
221 * Modify inode page cache in such way:
222 * have - blocks with b_blocknr equal to oldb...oldb+count-1
223 * get - blocks with b_blocknr equal to newb...newb+count-1
224 * also we suppose that oldb...oldb+count-1 blocks
225 * situated at the end of file.
226 *
227 * We can come here from ufs_writepage or ufs_prepare_write,
228 * locked_page is argument of these functions, so we already lock it.
229 */
Evgeniy Dushistovf3914752006-06-25 05:47:28 -0700230static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
231 unsigned int count, unsigned int oldb,
232 unsigned int newb, struct page *locked_page)
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700233{
234 unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700235 struct address_space *mapping = inode->i_mapping;
236 pgoff_t index, cur_index = locked_page->index;
237 unsigned int i, j;
238 struct page *page;
239 struct buffer_head *head, *bh;
240
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700241 UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
242 inode->i_ino, count, oldb, newb);
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700243
244 BUG_ON(!PageLocked(locked_page));
245
246 for (i = 0; i < count; i += blk_per_page) {
247 index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
248
249 if (likely(cur_index != index)) {
250 page = ufs_get_locked_page(mapping, index);
251 if (IS_ERR(page))
252 continue;
253 } else
254 page = locked_page;
255
256 j = i;
257 head = page_buffers(page);
258 bh = head;
259 do {
260 if (likely(bh->b_blocknr == j + oldb && j < count)) {
261 unmap_underlying_metadata(bh->b_bdev,
262 bh->b_blocknr);
263 bh->b_blocknr = newb + j++;
264 mark_buffer_dirty(bh);
265 }
266
267 bh = bh->b_this_page;
268 } while (bh != head);
269
270 set_page_dirty(page);
271
Evgeniy Dushistov10e5dce2006-07-01 04:36:24 -0700272 if (likely(cur_index != index))
273 ufs_put_locked_page(page);
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700274 }
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700275 UFSD("EXIT\n");
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700276}
277
278unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
279 unsigned goal, unsigned count, int * err, struct page *locked_page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
281 struct super_block * sb;
282 struct ufs_sb_private_info * uspi;
283 struct ufs_super_block_first * usb1;
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700284 unsigned cgno, oldcount, newcount, tmp, request, result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700286 UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288 sb = inode->i_sb;
289 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +0300290 usb1 = ubh_get_usb_first(uspi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 *err = -ENOSPC;
292
293 lock_super (sb);
294
295 tmp = fs32_to_cpu(sb, *p);
296 if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
297 ufs_warning (sb, "ufs_new_fragments", "internal warning"
298 " fragment %u, count %u", fragment, count);
299 count = uspi->s_fpb - ufs_fragnum(fragment);
300 }
301 oldcount = ufs_fragnum (fragment);
302 newcount = oldcount + count;
303
304 /*
305 * Somebody else has just allocated our fragments
306 */
307 if (oldcount) {
308 if (!tmp) {
309 ufs_error (sb, "ufs_new_fragments", "internal error, "
310 "fragment %u, tmp %u\n", fragment, tmp);
311 unlock_super (sb);
312 return (unsigned)-1;
313 }
314 if (fragment < UFS_I(inode)->i_lastfrag) {
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700315 UFSD("EXIT (ALREADY ALLOCATED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 unlock_super (sb);
317 return 0;
318 }
319 }
320 else {
321 if (tmp) {
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700322 UFSD("EXIT (ALREADY ALLOCATED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 unlock_super(sb);
324 return 0;
325 }
326 }
327
328 /*
329 * There is not enough space for user on the device
330 */
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700331 if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 unlock_super (sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700333 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return 0;
335 }
336
337 if (goal >= uspi->s_size)
338 goal = 0;
339 if (goal == 0)
340 cgno = ufs_inotocg (inode->i_ino);
341 else
342 cgno = ufs_dtog (goal);
343
344 /*
345 * allocate new fragment
346 */
347 if (oldcount == 0) {
348 result = ufs_alloc_fragments (inode, cgno, goal, count, err);
349 if (result) {
350 *p = cpu_to_fs32(sb, result);
351 *err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 }
354 unlock_super(sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700355 UFSD("EXIT, result %u\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 return result;
357 }
358
359 /*
360 * resize block
361 */
362 result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);
363 if (result) {
364 *err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 unlock_super(sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700367 UFSD("EXIT, result %u\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 return result;
369 }
370
371 /*
372 * allocate new block and move data
373 */
374 switch (fs32_to_cpu(sb, usb1->fs_optim)) {
375 case UFS_OPTSPACE:
376 request = newcount;
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700377 if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
378 > uspi->s_dsize * uspi->s_minfree / (2 * 100))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 break;
380 usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
381 break;
382 default:
383 usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
384
385 case UFS_OPTTIME:
386 request = uspi->s_fpb;
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700387 if (uspi->cs_total.cs_nffree < uspi->s_dsize *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 (uspi->s_minfree - 2) / 100)
389 break;
390 usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
391 break;
392 }
393 result = ufs_alloc_fragments (inode, cgno, goal, request, err);
394 if (result) {
Evgeniy Dushistovf3914752006-06-25 05:47:28 -0700395 ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
396 result, locked_page);
Evgeniy Dushistov6ef4d6b2006-06-25 05:47:20 -0700397
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 *p = cpu_to_fs32(sb, result);
399 *err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 unlock_super(sb);
402 if (newcount < request)
403 ufs_free_fragments (inode, result + newcount, request - newcount);
404 ufs_free_fragments (inode, tmp, oldcount);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700405 UFSD("EXIT, result %u\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 return result;
407 }
408
409 unlock_super(sb);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700410 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 return 0;
412}
413
414static unsigned
415ufs_add_fragments (struct inode * inode, unsigned fragment,
416 unsigned oldcount, unsigned newcount, int * err)
417{
418 struct super_block * sb;
419 struct ufs_sb_private_info * uspi;
420 struct ufs_super_block_first * usb1;
421 struct ufs_cg_private_info * ucpi;
422 struct ufs_cylinder_group * ucg;
423 unsigned cgno, fragno, fragoff, count, fragsize, i;
424
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700425 UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427 sb = inode->i_sb;
428 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +0300429 usb1 = ubh_get_usb_first (uspi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 count = newcount - oldcount;
431
432 cgno = ufs_dtog(fragment);
433 if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
434 return 0;
435 if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
436 return 0;
437 ucpi = ufs_load_cylinder (sb, cgno);
438 if (!ucpi)
439 return 0;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700440 ucg = ubh_get_ucg (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 if (!ufs_cg_chkmagic(sb, ucg)) {
442 ufs_panic (sb, "ufs_add_fragments",
443 "internal error, bad magic number on cg %u", cgno);
444 return 0;
445 }
446
447 fragno = ufs_dtogd (fragment);
448 fragoff = ufs_fragnum (fragno);
449 for (i = oldcount; i < newcount; i++)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700450 if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return 0;
452 /*
453 * Block can be extended
454 */
455 ucg->cg_time = cpu_to_fs32(sb, get_seconds());
456 for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700457 if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 break;
459 fragsize = i - oldcount;
460 if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
461 ufs_panic (sb, "ufs_add_fragments",
462 "internal error or corrupted bitmap on cg %u", cgno);
463 fs32_sub(sb, &ucg->cg_frsum[fragsize], 1);
464 if (fragsize != count)
465 fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
466 for (i = oldcount; i < newcount; i++)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700467 ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 if(DQUOT_ALLOC_BLOCK(inode, count)) {
469 *err = -EDQUOT;
470 return 0;
471 }
472
473 fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
474 fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700475 uspi->cs_total.cs_nffree -= count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700477 ubh_mark_buffer_dirty (USPI_UBH(uspi));
478 ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 if (sb->s_flags & MS_SYNCHRONOUS) {
Evgeniy Dushistov098d5af2006-06-25 05:47:31 -0700480 ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700481 ubh_wait_on_buffer (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 }
483 sb->s_dirt = 1;
484
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700485 UFSD("EXIT, fragment %u\n", fragment);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
487 return fragment;
488}
489
490#define UFS_TEST_FREE_SPACE_CG \
491 ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \
492 if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \
493 goto cg_found; \
494 for (k = count; k < uspi->s_fpb; k++) \
495 if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
496 goto cg_found;
497
498static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
499 unsigned goal, unsigned count, int * err)
500{
501 struct super_block * sb;
502 struct ufs_sb_private_info * uspi;
503 struct ufs_super_block_first * usb1;
504 struct ufs_cg_private_info * ucpi;
505 struct ufs_cylinder_group * ucg;
506 unsigned oldcg, i, j, k, result, allocsize;
507
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700508 UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 sb = inode->i_sb;
511 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +0300512 usb1 = ubh_get_usb_first(uspi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 oldcg = cgno;
514
515 /*
516 * 1. searching on preferred cylinder group
517 */
518 UFS_TEST_FREE_SPACE_CG
519
520 /*
521 * 2. quadratic rehash
522 */
523 for (j = 1; j < uspi->s_ncg; j *= 2) {
524 cgno += j;
525 if (cgno >= uspi->s_ncg)
526 cgno -= uspi->s_ncg;
527 UFS_TEST_FREE_SPACE_CG
528 }
529
530 /*
531 * 3. brute force search
532 * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step )
533 */
534 cgno = (oldcg + 1) % uspi->s_ncg;
535 for (j = 2; j < uspi->s_ncg; j++) {
536 cgno++;
537 if (cgno >= uspi->s_ncg)
538 cgno = 0;
539 UFS_TEST_FREE_SPACE_CG
540 }
541
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700542 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 return 0;
544
545cg_found:
546 ucpi = ufs_load_cylinder (sb, cgno);
547 if (!ucpi)
548 return 0;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700549 ucg = ubh_get_ucg (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 if (!ufs_cg_chkmagic(sb, ucg))
551 ufs_panic (sb, "ufs_alloc_fragments",
552 "internal error, bad magic number on cg %u", cgno);
553 ucg->cg_time = cpu_to_fs32(sb, get_seconds());
554
555 if (count == uspi->s_fpb) {
556 result = ufs_alloccg_block (inode, ucpi, goal, err);
557 if (result == (unsigned)-1)
558 return 0;
559 goto succed;
560 }
561
562 for (allocsize = count; allocsize < uspi->s_fpb; allocsize++)
563 if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0)
564 break;
565
566 if (allocsize == uspi->s_fpb) {
567 result = ufs_alloccg_block (inode, ucpi, goal, err);
568 if (result == (unsigned)-1)
569 return 0;
570 goal = ufs_dtogd (result);
571 for (i = count; i < uspi->s_fpb; i++)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700572 ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 i = uspi->s_fpb - count;
574 DQUOT_FREE_BLOCK(inode, i);
575
576 fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700577 uspi->cs_total.cs_nffree += i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
579 fs32_add(sb, &ucg->cg_frsum[i], 1);
580 goto succed;
581 }
582
583 result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
584 if (result == (unsigned)-1)
585 return 0;
586 if(DQUOT_ALLOC_BLOCK(inode, count)) {
587 *err = -EDQUOT;
588 return 0;
589 }
590 for (i = 0; i < count; i++)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700591 ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700594 uspi->cs_total.cs_nffree -= count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
596 fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
597
598 if (count != allocsize)
599 fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);
600
601succed:
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700602 ubh_mark_buffer_dirty (USPI_UBH(uspi));
603 ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (sb->s_flags & MS_SYNCHRONOUS) {
Evgeniy Dushistov098d5af2006-06-25 05:47:31 -0700605 ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700606 ubh_wait_on_buffer (UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 }
608 sb->s_dirt = 1;
609
610 result += cgno * uspi->s_fpg;
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700611 UFSD("EXIT3, result %u\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 return result;
613}
614
615static unsigned ufs_alloccg_block (struct inode * inode,
616 struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
617{
618 struct super_block * sb;
619 struct ufs_sb_private_info * uspi;
620 struct ufs_super_block_first * usb1;
621 struct ufs_cylinder_group * ucg;
622 unsigned result, cylno, blkno;
623
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700624 UFSD("ENTER, goal %u\n", goal);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
626 sb = inode->i_sb;
627 uspi = UFS_SB(sb)->s_uspi;
Evgeniy7b4ee732006-01-14 11:42:06 +0300628 usb1 = ubh_get_usb_first(uspi);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700629 ucg = ubh_get_ucg(UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 if (goal == 0) {
632 goal = ucpi->c_rotor;
633 goto norot;
634 }
635 goal = ufs_blknum (goal);
636 goal = ufs_dtogd (goal);
637
638 /*
639 * If the requested block is available, use it.
640 */
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700641 if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 result = goal;
643 goto gotit;
644 }
645
646norot:
647 result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
648 if (result == (unsigned)-1)
649 return (unsigned)-1;
650 ucpi->c_rotor = result;
651gotit:
652 blkno = ufs_fragstoblks(result);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700653 ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
655 ufs_clusteracct (sb, ucpi, blkno, -1);
656 if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
657 *err = -EDQUOT;
658 return (unsigned)-1;
659 }
660
661 fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
Evgeniy Dushistovee3ffd62006-06-25 05:47:30 -0700662 uspi->cs_total.cs_nbfree--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
664 cylno = ufs_cbtocylno(result);
665 fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
666 fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
667
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700668 UFSD("EXIT, result %u\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
670 return result;
671}
672
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700673static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
674 struct ufs_buffer_head *ubh,
675 unsigned begin, unsigned size,
676 unsigned char *table, unsigned char mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700678 unsigned rest, offset;
679 unsigned char *cp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700682 offset = begin & ~uspi->s_fmask;
683 begin >>= uspi->s_fshift;
684 for (;;) {
685 if ((offset + size) < uspi->s_fsize)
686 rest = size;
687 else
688 rest = uspi->s_fsize - offset;
689 size -= rest;
690 cp = ubh->bh[begin]->b_data + offset;
691 while ((table[*cp++] & mask) == 0 && --rest)
692 ;
693 if (rest || !size)
694 break;
695 begin++;
696 offset = 0;
697 }
698 return (size + rest);
699}
700
701/*
702 * Find a block of the specified size in the specified cylinder group.
703 * @sp: pointer to super block
704 * @ucpi: pointer to cylinder group info
705 * @goal: near which block we want find new one
706 * @count: specified size
707 */
708static unsigned ufs_bitmap_search(struct super_block *sb,
709 struct ufs_cg_private_info *ucpi,
710 unsigned goal, unsigned count)
711{
712 /*
713 * Bit patterns for identifying fragments in the block map
714 * used as ((map & mask_arr) == want_arr)
715 */
716 static const int mask_arr[9] = {
717 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
718 };
719 static const int want_arr[9] = {
720 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
721 };
722 struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
723 struct ufs_super_block_first *usb1;
724 struct ufs_cylinder_group *ucg;
725 unsigned start, length, loc, result;
726 unsigned pos, want, blockmap, mask, end;
727
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700728 UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700729
Evgeniy7b4ee732006-01-14 11:42:06 +0300730 usb1 = ubh_get_usb_first (uspi);
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700731 ucg = ubh_get_ucg(UCPI_UBH(ucpi));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 if (goal)
734 start = ufs_dtogd(goal) >> 3;
735 else
736 start = ucpi->c_frotor >> 3;
737
738 length = ((uspi->s_fpg + 7) >> 3) - start;
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700739 loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
741 1 << (count - 1 + (uspi->s_fpb & 7)));
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700742 if (loc == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 length = start + 1;
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700744 loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length,
745 (uspi->s_fpb == 8) ? ufs_fragtable_8fpb :
746 ufs_fragtable_other,
747 1 << (count - 1 + (uspi->s_fpb & 7)));
748 if (loc == 0) {
749 ufs_error(sb, "ufs_bitmap_search",
750 "bitmap corrupted on cg %u, start %u,"
751 " length %u, count %u, freeoff %u\n",
752 ucpi->c_cgx, start, length, count,
753 ucpi->c_freeoff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return (unsigned)-1;
755 }
756 start = 0;
757 }
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700758 result = (start + length - loc) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 ucpi->c_frotor = result;
760
761 /*
762 * found the byte in the map
763 */
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700764
765 for (end = result + 8; result < end; result += uspi->s_fpb) {
766 blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result);
767 blockmap <<= 1;
768 mask = mask_arr[count];
769 want = want_arr[count];
770 for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
771 if ((blockmap & mask) == want) {
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700772 UFSD("EXIT, result %u\n", result);
Evgeniy Dushistov3e41f592006-06-25 05:47:23 -0700773 return result + pos;
774 }
775 mask <<= 1;
776 want <<= 1;
777 }
778 }
779
780 ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
781 ucpi->c_cgx);
Evgeniy Dushistovabf5d152006-06-25 05:47:24 -0700782 UFSD("EXIT (FAILED)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return (unsigned)-1;
784}
785
786static void ufs_clusteracct(struct super_block * sb,
787 struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
788{
789 struct ufs_sb_private_info * uspi;
790 int i, start, end, forw, back;
791
792 uspi = UFS_SB(sb)->s_uspi;
793 if (uspi->s_contigsumsize <= 0)
794 return;
795
796 if (cnt > 0)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700797 ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 else
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700799 ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
801 /*
802 * Find the size of the cluster going forward.
803 */
804 start = blkno + 1;
805 end = start + uspi->s_contigsumsize;
806 if ( end >= ucpi->c_nclusterblks)
807 end = ucpi->c_nclusterblks;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700808 i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (i > end)
810 i = end;
811 forw = i - start;
812
813 /*
814 * Find the size of the cluster going backward.
815 */
816 start = blkno - 1;
817 end = start - uspi->s_contigsumsize;
818 if (end < 0 )
819 end = -1;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700820 i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 if ( i < end)
822 i = end;
823 back = start - i;
824
825 /*
826 * Account for old cluster and the possibly new forward and
827 * back clusters.
828 */
829 i = back + forw + 1;
830 if (i > uspi->s_contigsumsize)
831 i = uspi->s_contigsumsize;
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700832 fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 if (back > 0)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700834 fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 if (forw > 0)
Evgeniy Dushistov9695ef12006-06-25 05:47:22 -0700836 fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837}
838
839
840static unsigned char ufs_fragtable_8fpb[] = {
841 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
842 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
843 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
844 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
845 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
846 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
847 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
848 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40,
849 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
850 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
851 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
852 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
853 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A,
854 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12,
855 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C,
856 0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
857};
858
859static unsigned char ufs_fragtable_other[] = {
860 0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A,
861 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
862 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
863 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
864 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
865 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
866 0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE,
867 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
868 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
869 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
870 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E,
871 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
872 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA,
873 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE,
874 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE,
875 0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A,
876};