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 int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
39
extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
41
extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
43
extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
44
extern int 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_ int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
334
_INLINE_ int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
336
_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
339
_INLINE_ int 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
return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
349
_INLINE_ int 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
return 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_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
372
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
377
_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
380
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
384
_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
387
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
391
_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
394
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
398
_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
401
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
405
_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
408
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
412
_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
415
#ifdef EXT2FS_DEBUG_FAST_OPS
416
if ((block < bitmap->start) || (block > bitmap->end)) {
417
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
418
bitmap->description);
422
ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
425
_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
428
#ifdef EXT2FS_DEBUG_FAST_OPS
429
if ((block < bitmap->start) || (block > bitmap->end)) {
430
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
431
block, bitmap->description);
435
ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
438
_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
441
#ifdef EXT2FS_DEBUG_FAST_OPS
442
if ((block < bitmap->start) || (block > bitmap->end)) {
443
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
444
block, bitmap->description);
448
return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
451
_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
454
#ifdef EXT2FS_DEBUG_FAST_OPS
455
if ((inode < bitmap->start) || (inode > bitmap->end)) {
456
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
457
inode, bitmap->description);
461
ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
464
_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
467
#ifdef EXT2FS_DEBUG_FAST_OPS
468
if ((inode < bitmap->start) || (inode > bitmap->end)) {
469
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
470
inode, bitmap->description);
474
ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
477
_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
480
#ifdef EXT2FS_DEBUG_FAST_OPS
481
if ((inode < bitmap->start) || (inode > bitmap->end)) {
482
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
483
inode, bitmap->description);
487
return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
490
_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
492
return bitmap->start;
495
_INLINE_ ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
497
return bitmap->start;
500
_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
505
_INLINE_ ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
510
_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
511
blk_t block, int num)
515
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
516
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
517
block, bitmap->description);
520
for (i=0; i < num; i++) {
521
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
527
_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
528
blk_t block, int num)
532
#ifdef EXT2FS_DEBUG_FAST_OPS
533
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
534
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
535
block, bitmap->description);
539
for (i=0; i < num; i++) {
540
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
546
_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
547
blk_t block, int num)
551
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
552
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
553
bitmap->description);
556
for (i=0; i < num; i++)
557
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
560
_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
561
blk_t block, int num)
565
#ifdef EXT2FS_DEBUG_FAST_OPS
566
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
567
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
568
bitmap->description);
572
for (i=0; i < num; i++)
573
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
576
_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
577
blk_t block, int num)
581
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
582
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
583
bitmap->description);
586
for (i=0; i < num; i++)
587
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
590
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
591
blk_t block, int num)
595
#ifdef EXT2FS_DEBUG_FAST_OPS
596
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
597
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
598
bitmap->description);
602
for (i=0; i < num; i++)
603
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);