2 * bitops.h --- Bitmap frobbing code. The byte swapping routines are
5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
12 * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
17 extern int ext2fs_set_bit(int nr,void * addr);
18 extern int ext2fs_clear_bit(int nr, void * addr);
19 extern int ext2fs_test_bit(int nr, const void * addr);
20 extern __u16 ext2fs_swab16(__u16 val);
21 extern __u32 ext2fs_swab32(__u32 val);
24 * EXT2FS bitmap manipulation routines.
27 /* Support for sending warning messages from the inline subroutines */
28 extern const char *ext2fs_block_string;
29 extern const char *ext2fs_inode_string;
30 extern const char *ext2fs_mark_string;
31 extern const char *ext2fs_unmark_string;
32 extern const char *ext2fs_test_string;
33 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
34 const char *description);
35 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
36 int code, unsigned long arg);
38 extern void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
39 extern void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
41 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
43 extern void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
44 extern void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
46 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
48 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
50 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
52 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
55 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
57 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
59 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
61 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
62 extern ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
63 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
64 extern ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
66 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
67 blk_t block, int num);
68 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
69 blk_t block, int num);
70 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
71 blk_t block, int num);
72 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
73 blk_t block, int num);
74 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
75 blk_t block, int num);
76 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
77 blk_t block, int num);
78 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
81 * The inline routines themselves...
83 * If NO_INLINE_FUNCS is defined, then we won't try to do inline
84 * functions at all; they will be included as normal functions in
87 #ifdef NO_INLINE_FUNCS
88 #if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
89 defined(__i586__) || defined(__mc68000__) || \
91 /* This prevents bitops.c from trying to include the C */
92 /* function version of these functions */
93 #define _EXT2_HAVE_ASM_BITOPS_
95 #endif /* NO_INLINE_FUNCS */
97 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
98 #ifdef INCLUDE_INLINE_FUNCS
99 #define _INLINE_ extern
102 #define _INLINE_ extern __inline__
103 #else /* For Watcom C */
104 #define _INLINE_ extern inline
108 #if ((defined __GNUC__) && (defined(__i386__) || defined(__i486__) || \
111 #define _EXT2_HAVE_ASM_BITOPS_
114 * These are done by inline assembly for speed reasons.....
116 * All bitoperations return 0 if the bit was cleared before the
117 * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
118 * is the LSB of (addr+1).
122 * Some hacks to defeat gcc over-optimizations..
124 struct __dummy_h { unsigned long a[100]; };
125 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
126 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
128 _INLINE_ int ext2fs_set_bit(int nr, void * addr)
132 __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
133 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
138 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
142 __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
143 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
148 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
152 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
154 :"m" (EXT2FS_CONST_ADDR),"r" (nr));
164 #define _EXT2_HAVE_ASM_BITOPS_
166 _INLINE_ int ext2fs_set_bit(int nr,void * addr)
170 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
171 : "=d" (retval) : "d" (nr^7), "a" (addr));
176 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
180 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
181 : "=d" (retval) : "d" (nr^7), "a" (addr));
186 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
190 __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
191 : "=d" (retval) : "d" (nr^7), "a" (addr));
196 #endif /* __mc68000__ */
200 #define _EXT2_HAVE_ASM_BITOPS_
202 #ifndef EXT2_OLD_BITOPS
205 * Do the bitops so that we are compatible with the standard i386
209 _INLINE_ int ext2fs_set_bit(int nr,void * addr)
213 unsigned char *ADDR = (unsigned char *) addr;
216 mask = 1 << (nr & 0x07);
217 __asm__ __volatile__("ldub [%0], %%g6\n\t"
218 "or %%g6, %2, %%g5\n\t"
222 : "0" (ADDR), "r" (mask)
227 unsigned char *ADDR = (unsigned char *) addr;
230 mask = 1 << (nr & 0x07);
231 retval = (mask & *ADDR) != 0;
237 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
241 unsigned char *ADDR = (unsigned char *) addr;
244 mask = 1 << (nr & 0x07);
245 __asm__ __volatile__("ldub [%0], %%g6\n\t"
246 "andn %%g6, %2, %%g5\n\t"
250 : "0" (ADDR), "r" (mask)
256 unsigned char *ADDR = (unsigned char *) addr;
259 mask = 1 << (nr & 0x07);
260 retval = (mask & *ADDR) != 0;
266 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
269 const unsigned char *ADDR = (const unsigned char *) addr;
272 mask = 1 << (nr & 0x07);
273 return ((mask & *ADDR) != 0);
278 /* Do things the old, unplesant way. */
280 _INLINE_ int ext2fs_set_bit(int nr, void *addr)
283 unsigned long *ADDR = (unsigned long *) addr;
286 mask = 1 << (nr & 31);
287 retval = ((mask & *ADDR) != 0);
292 _INLINE_ int ext2fs_clear_bit(int nr, void *addr)
295 unsigned long *ADDR = (unsigned long *) addr;
298 mask = 1 << (nr & 31);
299 retval = ((mask & *ADDR) != 0);
304 _INLINE_ int ext2fs_test_bit(int nr, const void *addr)
307 const unsigned long *ADDR = (const unsigned long *) addr;
310 mask = 1 << (nr & 31);
311 return ((mask & *ADDR) != 0);
315 #endif /* __sparc__ */
317 #ifndef _EXT2_HAVE_ASM_SWAB
319 _INLINE_ __u16 ext2fs_swab16(__u16 val)
321 return (val >> 8) | (val << 8);
324 _INLINE_ __u32 ext2fs_swab32(__u32 val)
326 return ((val>>24) | ((val>>8)&0xFF00) |
327 ((val<<8)&0xFF0000) | (val<<24));
330 #endif /* !_EXT2_HAVE_ASM_SWAB */
332 _INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
334 _INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
336 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
339 _INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
342 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
343 ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
346 ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
349 _INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
352 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
353 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
356 ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
359 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
362 if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
363 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
366 return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
369 _INLINE_ void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
372 ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
375 _INLINE_ void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
378 ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
381 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
384 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
388 _INLINE_ void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
391 ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
394 _INLINE_ void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
397 ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
400 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
403 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
407 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
410 #ifdef EXT2FS_DEBUG_FAST_OPS
411 if ((block < bitmap->start) || (block > bitmap->end)) {
412 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
413 bitmap->description);
417 ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
420 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
423 #ifdef EXT2FS_DEBUG_FAST_OPS
424 if ((block < bitmap->start) || (block > bitmap->end)) {
425 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
426 block, bitmap->description);
430 ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
433 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
436 #ifdef EXT2FS_DEBUG_FAST_OPS
437 if ((block < bitmap->start) || (block > bitmap->end)) {
438 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
439 block, bitmap->description);
443 return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
446 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
449 #ifdef EXT2FS_DEBUG_FAST_OPS
450 if ((inode < bitmap->start) || (inode > bitmap->end)) {
451 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
452 inode, bitmap->description);
456 ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
459 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
462 #ifdef EXT2FS_DEBUG_FAST_OPS
463 if ((inode < bitmap->start) || (inode > bitmap->end)) {
464 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
465 inode, bitmap->description);
469 ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
472 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
475 #ifdef EXT2FS_DEBUG_FAST_OPS
476 if ((inode < bitmap->start) || (inode > bitmap->end)) {
477 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
478 inode, bitmap->description);
482 return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
485 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
487 return bitmap->start;
490 _INLINE_ ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
492 return bitmap->start;
495 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
500 _INLINE_ ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
505 _INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
506 blk_t block, int num)
510 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
511 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
512 block, bitmap->description);
515 for (i=0; i < num; i++) {
516 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
522 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
523 blk_t block, int num)
527 #ifdef EXT2FS_DEBUG_FAST_OPS
528 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
529 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
530 block, bitmap->description);
534 for (i=0; i < num; i++) {
535 if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
541 _INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
542 blk_t block, int num)
546 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
547 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
548 bitmap->description);
551 for (i=0; i < num; i++)
552 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
555 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
556 blk_t block, int num)
560 #ifdef EXT2FS_DEBUG_FAST_OPS
561 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
562 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
563 bitmap->description);
567 for (i=0; i < num; i++)
568 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
571 _INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
572 blk_t block, int num)
576 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
577 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
578 bitmap->description);
581 for (i=0; i < num; i++)
582 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
585 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
586 blk_t block, int num)
590 #ifdef EXT2FS_DEBUG_FAST_OPS
591 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
592 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
593 bitmap->description);
597 for (i=0; i < num; i++)
598 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);