diff options
Diffstat (limited to 'fs/ufs/util.h')
-rw-r--r-- | fs/ufs/util.h | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/fs/ufs/util.h b/fs/ufs/util.h new file mode 100644 index 000000000000..b2640076679a --- /dev/null +++ b/fs/ufs/util.h | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * linux/fs/ufs/util.h | ||
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/buffer_head.h> | ||
10 | #include <linux/fs.h> | ||
11 | #include "swab.h" | ||
12 | |||
13 | |||
14 | /* | ||
15 | * some useful macros | ||
16 | */ | ||
17 | #define in_range(b,first,len) ((b)>=(first)&&(b)<(first)+(len)) | ||
18 | |||
19 | /* | ||
20 | * macros used for retyping | ||
21 | */ | ||
22 | #define UCPI_UBH ((struct ufs_buffer_head *)ucpi) | ||
23 | #define USPI_UBH ((struct ufs_buffer_head *)uspi) | ||
24 | |||
25 | |||
26 | |||
27 | /* | ||
28 | * macros used for accessing structures | ||
29 | */ | ||
30 | static inline s32 | ||
31 | ufs_get_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1, | ||
32 | struct ufs_super_block_third *usb3) | ||
33 | { | ||
34 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | ||
35 | case UFS_ST_SUN: | ||
36 | return fs32_to_cpu(sb, usb3->fs_u2.fs_sun.fs_state); | ||
37 | case UFS_ST_SUNx86: | ||
38 | return fs32_to_cpu(sb, usb1->fs_u1.fs_sunx86.fs_state); | ||
39 | case UFS_ST_44BSD: | ||
40 | default: | ||
41 | return fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_state); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | static inline void | ||
46 | ufs_set_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1, | ||
47 | struct ufs_super_block_third *usb3, s32 value) | ||
48 | { | ||
49 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | ||
50 | case UFS_ST_SUN: | ||
51 | usb3->fs_u2.fs_sun.fs_state = cpu_to_fs32(sb, value); | ||
52 | break; | ||
53 | case UFS_ST_SUNx86: | ||
54 | usb1->fs_u1.fs_sunx86.fs_state = cpu_to_fs32(sb, value); | ||
55 | break; | ||
56 | case UFS_ST_44BSD: | ||
57 | usb3->fs_u2.fs_44.fs_state = cpu_to_fs32(sb, value); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static inline u32 | ||
63 | ufs_get_fs_npsect(struct super_block *sb, struct ufs_super_block_first *usb1, | ||
64 | struct ufs_super_block_third *usb3) | ||
65 | { | ||
66 | if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86) | ||
67 | return fs32_to_cpu(sb, usb3->fs_u2.fs_sunx86.fs_npsect); | ||
68 | else | ||
69 | return fs32_to_cpu(sb, usb1->fs_u1.fs_sun.fs_npsect); | ||
70 | } | ||
71 | |||
72 | static inline u64 | ||
73 | ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3) | ||
74 | { | ||
75 | __fs64 tmp; | ||
76 | |||
77 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | ||
78 | case UFS_ST_SUN: | ||
79 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0]; | ||
80 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1]; | ||
81 | break; | ||
82 | case UFS_ST_SUNx86: | ||
83 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0]; | ||
84 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1]; | ||
85 | break; | ||
86 | case UFS_ST_44BSD: | ||
87 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0]; | ||
88 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1]; | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | return fs64_to_cpu(sb, tmp); | ||
93 | } | ||
94 | |||
95 | static inline u64 | ||
96 | ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3) | ||
97 | { | ||
98 | __fs64 tmp; | ||
99 | |||
100 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | ||
101 | case UFS_ST_SUN: | ||
102 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0]; | ||
103 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1]; | ||
104 | break; | ||
105 | case UFS_ST_SUNx86: | ||
106 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0]; | ||
107 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1]; | ||
108 | break; | ||
109 | case UFS_ST_44BSD: | ||
110 | ((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0]; | ||
111 | ((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1]; | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | return fs64_to_cpu(sb, tmp); | ||
116 | } | ||
117 | |||
118 | static inline u16 | ||
119 | ufs_get_de_namlen(struct super_block *sb, struct ufs_dir_entry *de) | ||
120 | { | ||
121 | if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) == UFS_DE_OLD) | ||
122 | return fs16_to_cpu(sb, de->d_u.d_namlen); | ||
123 | else | ||
124 | return de->d_u.d_44.d_namlen; /* XXX this seems wrong */ | ||
125 | } | ||
126 | |||
127 | static inline void | ||
128 | ufs_set_de_namlen(struct super_block *sb, struct ufs_dir_entry *de, u16 value) | ||
129 | { | ||
130 | if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) == UFS_DE_OLD) | ||
131 | de->d_u.d_namlen = cpu_to_fs16(sb, value); | ||
132 | else | ||
133 | de->d_u.d_44.d_namlen = value; /* XXX this seems wrong */ | ||
134 | } | ||
135 | |||
136 | static inline void | ||
137 | ufs_set_de_type(struct super_block *sb, struct ufs_dir_entry *de, int mode) | ||
138 | { | ||
139 | if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) != UFS_DE_44BSD) | ||
140 | return; | ||
141 | |||
142 | /* | ||
143 | * TODO turn this into a table lookup | ||
144 | */ | ||
145 | switch (mode & S_IFMT) { | ||
146 | case S_IFSOCK: | ||
147 | de->d_u.d_44.d_type = DT_SOCK; | ||
148 | break; | ||
149 | case S_IFLNK: | ||
150 | de->d_u.d_44.d_type = DT_LNK; | ||
151 | break; | ||
152 | case S_IFREG: | ||
153 | de->d_u.d_44.d_type = DT_REG; | ||
154 | break; | ||
155 | case S_IFBLK: | ||
156 | de->d_u.d_44.d_type = DT_BLK; | ||
157 | break; | ||
158 | case S_IFDIR: | ||
159 | de->d_u.d_44.d_type = DT_DIR; | ||
160 | break; | ||
161 | case S_IFCHR: | ||
162 | de->d_u.d_44.d_type = DT_CHR; | ||
163 | break; | ||
164 | case S_IFIFO: | ||
165 | de->d_u.d_44.d_type = DT_FIFO; | ||
166 | break; | ||
167 | default: | ||
168 | de->d_u.d_44.d_type = DT_UNKNOWN; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static inline u32 | ||
173 | ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode) | ||
174 | { | ||
175 | switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) { | ||
176 | case UFS_UID_EFT: | ||
177 | return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid); | ||
178 | case UFS_UID_44BSD: | ||
179 | return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_uid); | ||
180 | default: | ||
181 | return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static inline void | ||
186 | ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value) | ||
187 | { | ||
188 | switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) { | ||
189 | case UFS_UID_EFT: | ||
190 | inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value); | ||
191 | break; | ||
192 | case UFS_UID_44BSD: | ||
193 | inode->ui_u3.ui_44.ui_uid = cpu_to_fs32(sb, value); | ||
194 | break; | ||
195 | } | ||
196 | inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value); | ||
197 | } | ||
198 | |||
199 | static inline u32 | ||
200 | ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode) | ||
201 | { | ||
202 | switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) { | ||
203 | case UFS_UID_EFT: | ||
204 | return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid); | ||
205 | case UFS_UID_44BSD: | ||
206 | return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid); | ||
207 | default: | ||
208 | return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static inline void | ||
213 | ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value) | ||
214 | { | ||
215 | switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) { | ||
216 | case UFS_UID_EFT: | ||
217 | inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value); | ||
218 | break; | ||
219 | case UFS_UID_44BSD: | ||
220 | inode->ui_u3.ui_44.ui_gid = cpu_to_fs32(sb, value); | ||
221 | break; | ||
222 | } | ||
223 | inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value); | ||
224 | } | ||
225 | |||
226 | extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *); | ||
227 | extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t); | ||
228 | |||
229 | /* | ||
230 | * These functions manipulate ufs buffers | ||
231 | */ | ||
232 | #define ubh_bread(sb,fragment,size) _ubh_bread_(uspi,sb,fragment,size) | ||
233 | extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, u64 , u64); | ||
234 | extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, u64, u64); | ||
235 | extern void ubh_brelse (struct ufs_buffer_head *); | ||
236 | extern void ubh_brelse_uspi (struct ufs_sb_private_info *); | ||
237 | extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *); | ||
238 | extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int); | ||
239 | extern void ubh_ll_rw_block (int, unsigned, struct ufs_buffer_head **); | ||
240 | extern void ubh_wait_on_buffer (struct ufs_buffer_head *); | ||
241 | extern unsigned ubh_max_bcount (struct ufs_buffer_head *); | ||
242 | extern void ubh_bforget (struct ufs_buffer_head *); | ||
243 | extern int ubh_buffer_dirty (struct ufs_buffer_head *); | ||
244 | #define ubh_ubhcpymem(mem,ubh,size) _ubh_ubhcpymem_(uspi,mem,ubh,size) | ||
245 | extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struct ufs_buffer_head *, unsigned); | ||
246 | #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) | ||
247 | extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); | ||
248 | |||
249 | |||
250 | |||
251 | /* | ||
252 | * macros to get important structures from ufs_buffer_head | ||
253 | */ | ||
254 | #define ubh_get_usb_first(ubh) \ | ||
255 | ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data)) | ||
256 | |||
257 | #define ubh_get_usb_second(ubh) \ | ||
258 | ((struct ufs_super_block_second *)(ubh)-> \ | ||
259 | bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask)) | ||
260 | |||
261 | #define ubh_get_usb_third(ubh) \ | ||
262 | ((struct ufs_super_block_third *)((ubh)-> \ | ||
263 | bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask))) | ||
264 | |||
265 | #define ubh_get_ucg(ubh) \ | ||
266 | ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) | ||
267 | |||
268 | |||
269 | /* | ||
270 | * Extract byte from ufs_buffer_head | ||
271 | * Extract the bits for a block from a map inside ufs_buffer_head | ||
272 | */ | ||
273 | #define ubh_get_addr8(ubh,begin) \ | ||
274 | ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + \ | ||
275 | ((begin) & ~uspi->s_fmask)) | ||
276 | |||
277 | #define ubh_get_addr16(ubh,begin) \ | ||
278 | (((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \ | ||
279 | ((begin) & (uspi->fsize>>1) - 1))) | ||
280 | |||
281 | #define ubh_get_addr32(ubh,begin) \ | ||
282 | (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \ | ||
283 | ((begin) & ((uspi->s_fsize>>2) - 1))) | ||
284 | |||
285 | #define ubh_get_addr ubh_get_addr8 | ||
286 | |||
287 | #define ubh_blkmap(ubh,begin,bit) \ | ||
288 | ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) | ||
289 | |||
290 | |||
291 | /* | ||
292 | * Macros for access to superblock array structures | ||
293 | */ | ||
294 | #define ubh_postbl(ubh,cylno,i) \ | ||
295 | ((uspi->s_postblformat != UFS_DYNAMICPOSTBLFMT) \ | ||
296 | ? (*(__s16*)(ubh_get_addr(ubh, \ | ||
297 | (unsigned)(&((struct ufs_super_block *)0)->fs_opostbl) \ | ||
298 | + (((cylno) * 16 + (i)) << 1) ) )) \ | ||
299 | : (*(__s16*)(ubh_get_addr(ubh, \ | ||
300 | uspi->s_postbloff + (((cylno) * uspi->s_nrpos + (i)) << 1) )))) | ||
301 | |||
302 | #define ubh_rotbl(ubh,i) \ | ||
303 | ((uspi->s_postblformat != UFS_DYNAMICPOSTBLFMT) \ | ||
304 | ? (*(__u8*)(ubh_get_addr(ubh, \ | ||
305 | (unsigned)(&((struct ufs_super_block *)0)->fs_space) + (i)))) \ | ||
306 | : (*(__u8*)(ubh_get_addr(ubh, uspi->s_rotbloff + (i))))) | ||
307 | |||
308 | /* | ||
309 | * Determine the number of available frags given a | ||
310 | * percentage to hold in reserve. | ||
311 | */ | ||
312 | #define ufs_freespace(usb, percentreserved) \ | ||
313 | (ufs_blkstofrags(fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nbfree)) + \ | ||
314 | fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nffree) - (uspi->s_dsize * (percentreserved) / 100)) | ||
315 | |||
316 | /* | ||
317 | * Macros to access cylinder group array structures | ||
318 | */ | ||
319 | #define ubh_cg_blktot(ucpi,cylno) \ | ||
320 | (*((__fs32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2)))) | ||
321 | |||
322 | #define ubh_cg_blks(ucpi,cylno,rpos) \ | ||
323 | (*((__fs16*)ubh_get_addr(UCPI_UBH, \ | ||
324 | (ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 )))) | ||
325 | |||
326 | /* | ||
327 | * Bitmap operations | ||
328 | * These functions work like classical bitmap operations. | ||
329 | * The difference is that we don't have the whole bitmap | ||
330 | * in one contiguous chunk of memory, but in several buffers. | ||
331 | * The parameters of each function are super_block, ufs_buffer_head and | ||
332 | * position of the beginning of the bitmap. | ||
333 | */ | ||
334 | #define ubh_setbit(ubh,begin,bit) \ | ||
335 | (*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) |= (1 << ((bit) & 7))) | ||
336 | |||
337 | #define ubh_clrbit(ubh,begin,bit) \ | ||
338 | (*ubh_get_addr (ubh, (begin) + ((bit) >> 3)) &= ~(1 << ((bit) & 7))) | ||
339 | |||
340 | #define ubh_isset(ubh,begin,bit) \ | ||
341 | (*ubh_get_addr (ubh, (begin) + ((bit) >> 3)) & (1 << ((bit) & 7))) | ||
342 | |||
343 | #define ubh_isclr(ubh,begin,bit) (!ubh_isset(ubh,begin,bit)) | ||
344 | |||
345 | #define ubh_find_first_zero_bit(ubh,begin,size) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0) | ||
346 | |||
347 | #define ubh_find_next_zero_bit(ubh,begin,size,offset) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset) | ||
348 | static inline unsigned _ubh_find_next_zero_bit_( | ||
349 | struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, | ||
350 | unsigned begin, unsigned size, unsigned offset) | ||
351 | { | ||
352 | unsigned base, count, pos; | ||
353 | |||
354 | size -= offset; | ||
355 | begin <<= 3; | ||
356 | offset += begin; | ||
357 | base = offset >> uspi->s_bpfshift; | ||
358 | offset &= uspi->s_bpfmask; | ||
359 | for (;;) { | ||
360 | count = min_t(unsigned int, size + offset, uspi->s_bpf); | ||
361 | size -= count - offset; | ||
362 | pos = ext2_find_next_zero_bit (ubh->bh[base]->b_data, count, offset); | ||
363 | if (pos < count || !size) | ||
364 | break; | ||
365 | base++; | ||
366 | offset = 0; | ||
367 | } | ||
368 | return (base << uspi->s_bpfshift) + pos - begin; | ||
369 | } | ||
370 | |||
371 | static inline unsigned find_last_zero_bit (unsigned char * bitmap, | ||
372 | unsigned size, unsigned offset) | ||
373 | { | ||
374 | unsigned bit, i; | ||
375 | unsigned char * mapp; | ||
376 | unsigned char map; | ||
377 | |||
378 | mapp = bitmap + (size >> 3); | ||
379 | map = *mapp--; | ||
380 | bit = 1 << (size & 7); | ||
381 | for (i = size; i > offset; i--) { | ||
382 | if ((map & bit) == 0) | ||
383 | break; | ||
384 | if ((i & 7) != 0) { | ||
385 | bit >>= 1; | ||
386 | } else { | ||
387 | map = *mapp--; | ||
388 | bit = 1 << 7; | ||
389 | } | ||
390 | } | ||
391 | return i; | ||
392 | } | ||
393 | |||
394 | #define ubh_find_last_zero_bit(ubh,begin,size,offset) _ubh_find_last_zero_bit_(uspi,ubh,begin,size,offset) | ||
395 | static inline unsigned _ubh_find_last_zero_bit_( | ||
396 | struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, | ||
397 | unsigned begin, unsigned start, unsigned end) | ||
398 | { | ||
399 | unsigned base, count, pos, size; | ||
400 | |||
401 | size = start - end; | ||
402 | begin <<= 3; | ||
403 | start += begin; | ||
404 | base = start >> uspi->s_bpfshift; | ||
405 | start &= uspi->s_bpfmask; | ||
406 | for (;;) { | ||
407 | count = min_t(unsigned int, | ||
408 | size + (uspi->s_bpf - start), uspi->s_bpf) | ||
409 | - (uspi->s_bpf - start); | ||
410 | size -= count; | ||
411 | pos = find_last_zero_bit (ubh->bh[base]->b_data, | ||
412 | start, start - count); | ||
413 | if (pos > start - count || !size) | ||
414 | break; | ||
415 | base--; | ||
416 | start = uspi->s_bpf; | ||
417 | } | ||
418 | return (base << uspi->s_bpfshift) + pos - begin; | ||
419 | } | ||
420 | |||
421 | #define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block)) | ||
422 | |||
423 | #define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block) | ||
424 | static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, | ||
425 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) | ||
426 | { | ||
427 | switch (uspi->s_fpb) { | ||
428 | case 8: | ||
429 | return (*ubh_get_addr (ubh, begin + block) == 0xff); | ||
430 | case 4: | ||
431 | return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); | ||
432 | case 2: | ||
433 | return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); | ||
434 | case 1: | ||
435 | return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); | ||
436 | } | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | #define ubh_clrblock(ubh,begin,block) _ubh_clrblock_(uspi,ubh,begin,block) | ||
441 | static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi, | ||
442 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) | ||
443 | { | ||
444 | switch (uspi->s_fpb) { | ||
445 | case 8: | ||
446 | *ubh_get_addr (ubh, begin + block) = 0x00; | ||
447 | return; | ||
448 | case 4: | ||
449 | *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2)); | ||
450 | return; | ||
451 | case 2: | ||
452 | *ubh_get_addr (ubh, begin + (block >> 2)) &= ~(0x03 << ((block & 0x03) << 1)); | ||
453 | return; | ||
454 | case 1: | ||
455 | *ubh_get_addr (ubh, begin + (block >> 3)) &= ~(0x01 << ((block & 0x07))); | ||
456 | return; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | #define ubh_setblock(ubh,begin,block) _ubh_setblock_(uspi,ubh,begin,block) | ||
461 | static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi, | ||
462 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) | ||
463 | { | ||
464 | switch (uspi->s_fpb) { | ||
465 | case 8: | ||
466 | *ubh_get_addr(ubh, begin + block) = 0xff; | ||
467 | return; | ||
468 | case 4: | ||
469 | *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2)); | ||
470 | return; | ||
471 | case 2: | ||
472 | *ubh_get_addr(ubh, begin + (block >> 2)) |= (0x03 << ((block & 0x03) << 1)); | ||
473 | return; | ||
474 | case 1: | ||
475 | *ubh_get_addr(ubh, begin + (block >> 3)) |= (0x01 << ((block & 0x07))); | ||
476 | return; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap, | ||
481 | __fs32 * fraglist, int cnt) | ||
482 | { | ||
483 | struct ufs_sb_private_info * uspi; | ||
484 | unsigned fragsize, pos; | ||
485 | |||
486 | uspi = UFS_SB(sb)->s_uspi; | ||
487 | |||
488 | fragsize = 0; | ||
489 | for (pos = 0; pos < uspi->s_fpb; pos++) { | ||
490 | if (blockmap & (1 << pos)) { | ||
491 | fragsize++; | ||
492 | } | ||
493 | else if (fragsize > 0) { | ||
494 | fs32_add(sb, &fraglist[fragsize], cnt); | ||
495 | fragsize = 0; | ||
496 | } | ||
497 | } | ||
498 | if (fragsize > 0 && fragsize < uspi->s_fpb) | ||
499 | fs32_add(sb, &fraglist[fragsize], cnt); | ||
500 | } | ||
501 | |||
502 | #define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask) | ||
503 | static inline unsigned _ubh_scanc_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, | ||
504 | unsigned begin, unsigned size, unsigned char * table, unsigned char mask) | ||
505 | { | ||
506 | unsigned rest, offset; | ||
507 | unsigned char * cp; | ||
508 | |||
509 | |||
510 | offset = begin & ~uspi->s_fmask; | ||
511 | begin >>= uspi->s_fshift; | ||
512 | for (;;) { | ||
513 | if ((offset + size) < uspi->s_fsize) | ||
514 | rest = size; | ||
515 | else | ||
516 | rest = uspi->s_fsize - offset; | ||
517 | size -= rest; | ||
518 | cp = ubh->bh[begin]->b_data + offset; | ||
519 | while ((table[*cp++] & mask) == 0 && --rest); | ||
520 | if (rest || !size) | ||
521 | break; | ||
522 | begin++; | ||
523 | offset = 0; | ||
524 | } | ||
525 | return (size + rest); | ||
526 | } | ||