Home | History | Annotate | Download | only in ext2fs
      1 /*
      2  * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
      3  * 	also included here.
      4  *
      5  * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
      6  *
      7  * %Begin-Header%
      8  * This file may be redistributed under the terms of the GNU Library
      9  * General Public License, version 2.
     10  * %End-Header%
     11  */
     12 
     13 extern int ext2fs_set_bit(unsigned int nr,void * addr);
     14 extern int ext2fs_clear_bit(unsigned int nr, void * addr);
     15 extern int ext2fs_test_bit(unsigned int nr, const void * addr);
     16 extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
     17 extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
     18 extern __u16 ext2fs_swab16(__u16 val);
     19 extern __u32 ext2fs_swab32(__u32 val);
     20 extern __u64 ext2fs_swab64(__u64 val);
     21 
     22 #ifdef WORDS_BIGENDIAN
     23 #define ext2fs_cpu_to_le64(x) ext2fs_swab64((x))
     24 #define ext2fs_le64_to_cpu(x) ext2fs_swab64((x))
     25 #define ext2fs_cpu_to_le32(x) ext2fs_swab32((x))
     26 #define ext2fs_le32_to_cpu(x) ext2fs_swab32((x))
     27 #define ext2fs_cpu_to_le16(x) ext2fs_swab16((x))
     28 #define ext2fs_le16_to_cpu(x) ext2fs_swab16((x))
     29 #define ext2fs_cpu_to_be32(x) ((__u32)(x))
     30 #define ext2fs_be32_to_cpu(x) ((__u32)(x))
     31 #define ext2fs_cpu_to_be16(x) ((__u16)(x))
     32 #define ext2fs_be16_to_cpu(x) ((__u16)(x))
     33 #else
     34 #define ext2fs_cpu_to_le64(x) ((__u64)(x))
     35 #define ext2fs_le64_to_cpu(x) ((__u64)(x))
     36 #define ext2fs_cpu_to_le32(x) ((__u32)(x))
     37 #define ext2fs_le32_to_cpu(x) ((__u32)(x))
     38 #define ext2fs_cpu_to_le16(x) ((__u16)(x))
     39 #define ext2fs_le16_to_cpu(x) ((__u16)(x))
     40 #define ext2fs_cpu_to_be32(x) ext2fs_swab32((x))
     41 #define ext2fs_be32_to_cpu(x) ext2fs_swab32((x))
     42 #define ext2fs_cpu_to_be16(x) ext2fs_swab16((x))
     43 #define ext2fs_be16_to_cpu(x) ext2fs_swab16((x))
     44 #endif
     45 
     46 /*
     47  * EXT2FS bitmap manipulation routines.
     48  */
     49 
     50 /* Support for sending warning messages from the inline subroutines */
     51 extern const char *ext2fs_block_string;
     52 extern const char *ext2fs_inode_string;
     53 extern const char *ext2fs_mark_string;
     54 extern const char *ext2fs_unmark_string;
     55 extern const char *ext2fs_test_string;
     56 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
     57 			       const char *description);
     58 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
     59 				int code, unsigned long arg);
     60 
     61 extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
     62 extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
     63 				       blk_t block);
     64 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
     65 
     66 extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
     67 extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     68 				       ext2_ino_t inode);
     69 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
     70 
     71 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
     72 					  blk_t block);
     73 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
     74 					    blk_t block);
     75 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
     76 					 blk_t block);
     77 
     78 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     79 					  ext2_ino_t inode);
     80 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
     81 					    ext2_ino_t inode);
     82 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
     83 					 ext2_ino_t inode);
     84 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
     85 extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
     86 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
     87 extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
     88 
     89 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
     90 					   blk_t block, int num);
     91 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
     92 					     blk_t block, int num);
     93 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
     94 					  blk_t block, int num);
     95 extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
     96 					  ino_t inode, int num);
     97 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
     98 						blk_t block, int num);
     99 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    100 						  blk_t block, int num);
    101 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    102 					       blk_t block, int num);
    103 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
    104 
    105 /* These routines moved to gen_bitmap.c */
    106 extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
    107 					 __u32 bitno);
    108 extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
    109 					   blk_t bitno);
    110 extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
    111 				      blk_t bitno);
    112 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    113 					  blk_t block, int num);
    114 extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
    115 extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
    116 
    117 /*
    118  * The inline routines themselves...
    119  *
    120  * If NO_INLINE_FUNCS is defined, then we won't try to do inline
    121  * functions at all; they will be included as normal functions in
    122  * inline.c
    123  */
    124 #ifdef NO_INLINE_FUNCS
    125 #if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
    126 			   defined(__i586__) || defined(__mc68000__)))
    127 	/* This prevents bitops.c from trying to include the C */
    128 	/* function version of these functions */
    129 #define _EXT2_HAVE_ASM_BITOPS_
    130 #endif
    131 #endif /* NO_INLINE_FUNCS */
    132 
    133 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
    134 #ifdef INCLUDE_INLINE_FUNCS
    135 #define _INLINE_ extern
    136 #else
    137 #ifdef __GNUC__
    138 #define _INLINE_ extern __inline__
    139 #else				/* For Watcom C */
    140 #define _INLINE_ extern inline
    141 #endif
    142 #endif
    143 
    144 /*
    145  * Fast bit set/clear functions that doesn't need to return the
    146  * previous bit value.
    147  */
    148 
    149 _INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
    150 {
    151 	unsigned char	*ADDR = (unsigned char *) addr;
    152 
    153 	ADDR += nr >> 3;
    154 	*ADDR |= (1 << (nr & 0x07));
    155 }
    156 
    157 _INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
    158 {
    159 	unsigned char	*ADDR = (unsigned char *) addr;
    160 
    161 	ADDR += nr >> 3;
    162 	*ADDR &= ~(1 << (nr & 0x07));
    163 }
    164 
    165 
    166 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
    167      (defined(__i386__) || defined(__i486__) || defined(__i586__)))
    168 
    169 #define _EXT2_HAVE_ASM_BITOPS_
    170 #define _EXT2_HAVE_ASM_SWAB_
    171 
    172 /*
    173  * These are done by inline assembly for speed reasons.....
    174  *
    175  * All bitoperations return 0 if the bit was cleared before the
    176  * operation and != 0 if it was not.  Bit 0 is the LSB of addr; bit 32
    177  * is the LSB of (addr+1).
    178  */
    179 
    180 /*
    181  * Some hacks to defeat gcc over-optimizations..
    182  */
    183 struct __dummy_h { unsigned long a[100]; };
    184 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
    185 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
    186 
    187 _INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
    188 {
    189 	int oldbit;
    190 
    191 	addr = (void *) (((unsigned char *) addr) + (nr >> 3));
    192 	__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
    193 		:"=r" (oldbit),"+m" (EXT2FS_ADDR)
    194 		:"r" (nr & 7));
    195 	return oldbit;
    196 }
    197 
    198 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
    199 {
    200 	int oldbit;
    201 
    202 	addr = (void *) (((unsigned char *) addr) + (nr >> 3));
    203 	__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
    204 		:"=r" (oldbit),"+m" (EXT2FS_ADDR)
    205 		:"r" (nr & 7));
    206 	return oldbit;
    207 }
    208 
    209 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
    210 {
    211 	int oldbit;
    212 
    213 	addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
    214 	__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
    215 		:"=r" (oldbit)
    216 		:"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
    217 	return oldbit;
    218 }
    219 
    220 _INLINE_ __u32 ext2fs_swab32(__u32 val)
    221 {
    222 #ifdef EXT2FS_REQUIRE_486
    223 	__asm__("bswap %0" : "=r" (val) : "0" (val));
    224 #else
    225 	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
    226 		"rorl $16,%0\n\t"	/* swap words		*/
    227 		"xchgb %b0,%h0"		/* swap higher bytes	*/
    228 		:"=q" (val)
    229 		: "0" (val));
    230 #endif
    231 	return val;
    232 }
    233 
    234 _INLINE_ __u16 ext2fs_swab16(__u16 val)
    235 {
    236 	__asm__("xchgb %b0,%h0"		/* swap bytes		*/ \
    237 		: "=q" (val) \
    238 		:  "0" (val)); \
    239 		return val;
    240 }
    241 
    242 #undef EXT2FS_ADDR
    243 
    244 #endif	/* i386 */
    245 
    246 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
    247      (defined(__mc68000__)))
    248 
    249 #define _EXT2_HAVE_ASM_BITOPS_
    250 
    251 _INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr)
    252 {
    253 	char retval;
    254 
    255 	__asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
    256 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    257 
    258 	return retval;
    259 }
    260 
    261 _INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
    262 {
    263 	char retval;
    264 
    265 	__asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
    266 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    267 
    268 	return retval;
    269 }
    270 
    271 _INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
    272 {
    273 	char retval;
    274 
    275 	__asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
    276 	     : "=d" (retval) : "d" (nr^7), "a" (addr));
    277 
    278 	return retval;
    279 }
    280 
    281 #endif /* __mc68000__ */
    282 
    283 
    284 #if !defined(_EXT2_HAVE_ASM_SWAB_)
    285 
    286 _INLINE_ __u16 ext2fs_swab16(__u16 val)
    287 {
    288 	return (val >> 8) | (val << 8);
    289 }
    290 
    291 _INLINE_ __u32 ext2fs_swab32(__u32 val)
    292 {
    293 	return ((val>>24) | ((val>>8)&0xFF00) |
    294 		((val<<8)&0xFF0000) | (val<<24));
    295 }
    296 
    297 #endif /* !_EXT2_HAVE_ASM_SWAB */
    298 
    299 _INLINE_ __u64 ext2fs_swab64(__u64 val)
    300 {
    301 	return (ext2fs_swab32(val >> 32) |
    302 		(((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
    303 }
    304 
    305 _INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
    306 				       blk_t block)
    307 {
    308 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    309 					  block);
    310 }
    311 
    312 _INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
    313 					 blk_t block)
    314 {
    315 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    316 					    block);
    317 }
    318 
    319 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
    320 				       blk_t block)
    321 {
    322 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    323 					  block);
    324 }
    325 
    326 _INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    327 				       ext2_ino_t inode)
    328 {
    329 	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    330 					  inode);
    331 }
    332 
    333 _INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    334 					 ext2_ino_t inode)
    335 {
    336 	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    337 				     inode);
    338 }
    339 
    340 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
    341 				       ext2_ino_t inode)
    342 {
    343 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    344 					  inode);
    345 }
    346 
    347 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
    348 					    blk_t block)
    349 {
    350 	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
    351 }
    352 
    353 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
    354 					      blk_t block)
    355 {
    356 	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
    357 }
    358 
    359 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
    360 					    blk_t block)
    361 {
    362 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    363 					  block);
    364 }
    365 
    366 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    367 					    ext2_ino_t inode)
    368 {
    369 	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
    370 }
    371 
    372 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
    373 					      ext2_ino_t inode)
    374 {
    375 	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
    376 }
    377 
    378 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
    379 					   ext2_ino_t inode)
    380 {
    381 	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
    382 					  inode);
    383 }
    384 
    385 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
    386 {
    387 	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
    388 }
    389 
    390 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
    391 {
    392 	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
    393 }
    394 
    395 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
    396 {
    397 	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
    398 }
    399 
    400 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
    401 {
    402 	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
    403 }
    404 
    405 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
    406 						 blk_t block, int num)
    407 {
    408 	return ext2fs_test_block_bitmap_range(bitmap, block, num);
    409 }
    410 
    411 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    412 						  blk_t block, int num)
    413 {
    414 	ext2fs_mark_block_bitmap_range(bitmap, block, num);
    415 }
    416 
    417 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
    418 						    blk_t block, int num)
    419 {
    420 	ext2fs_unmark_block_bitmap_range(bitmap, block, num);
    421 }
    422 #undef _INLINE_
    423 #endif
    424 
    425