mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
![Eric Sandeen](/assets/img/avatar_default.png)
xfs_count_bits is only called once, and is then compared to 0. IOW, what it really wants to know is, is the bitmap empty. This can be done more simply, certainly. SGI-PV: 966503 SGI-Modid: xfs-linux-melb:xfs-kern:28944a Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
223 lines
5.2 KiB
C
223 lines
5.2 KiB
C
/*
|
|
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include "xfs.h"
|
|
#include "xfs_bit.h"
|
|
#include "xfs_log.h"
|
|
#include "xfs_trans.h"
|
|
#include "xfs_buf_item.h"
|
|
|
|
/*
|
|
* XFS bit manipulation routines, used in non-realtime code.
|
|
*/
|
|
|
|
#ifndef HAVE_ARCH_HIGHBIT
|
|
/*
|
|
* Index of high bit number in byte, -1 for none set, 0..7 otherwise.
|
|
*/
|
|
static const char xfs_highbit[256] = {
|
|
-1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
|
|
3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
|
|
4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
|
|
4, 4, 4, 4, 4, 4, 4, 4, /* 18 .. 1f */
|
|
5, 5, 5, 5, 5, 5, 5, 5, /* 20 .. 27 */
|
|
5, 5, 5, 5, 5, 5, 5, 5, /* 28 .. 2f */
|
|
5, 5, 5, 5, 5, 5, 5, 5, /* 30 .. 37 */
|
|
5, 5, 5, 5, 5, 5, 5, 5, /* 38 .. 3f */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 40 .. 47 */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 48 .. 4f */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 50 .. 57 */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 58 .. 5f */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 60 .. 67 */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 68 .. 6f */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 70 .. 77 */
|
|
6, 6, 6, 6, 6, 6, 6, 6, /* 78 .. 7f */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* 80 .. 87 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* 88 .. 8f */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* 90 .. 97 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* 98 .. 9f */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* a0 .. a7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* a8 .. af */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* b0 .. b7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* b8 .. bf */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* c0 .. c7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* c8 .. cf */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* d0 .. d7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* d8 .. df */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* e0 .. e7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* e8 .. ef */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* f0 .. f7 */
|
|
7, 7, 7, 7, 7, 7, 7, 7, /* f8 .. ff */
|
|
};
|
|
#endif
|
|
|
|
/*
|
|
* xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
|
|
*/
|
|
inline int
|
|
xfs_highbit32(
|
|
__uint32_t v)
|
|
{
|
|
#ifdef HAVE_ARCH_HIGHBIT
|
|
return highbit32(v);
|
|
#else
|
|
int i;
|
|
|
|
if (v & 0xffff0000)
|
|
if (v & 0xff000000)
|
|
i = 24;
|
|
else
|
|
i = 16;
|
|
else if (v & 0x0000ffff)
|
|
if (v & 0x0000ff00)
|
|
i = 8;
|
|
else
|
|
i = 0;
|
|
else
|
|
return -1;
|
|
return i + xfs_highbit[(v >> i) & 0xff];
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set.
|
|
*/
|
|
int
|
|
xfs_lowbit64(
|
|
__uint64_t v)
|
|
{
|
|
__uint32_t w = (__uint32_t)v;
|
|
int n = 0;
|
|
|
|
if (w) { /* lower bits */
|
|
n = ffs(w);
|
|
} else { /* upper bits */
|
|
w = (__uint32_t)(v >> 32);
|
|
if (w && (n = ffs(w)))
|
|
n += 32;
|
|
}
|
|
return n - 1;
|
|
}
|
|
|
|
/*
|
|
* xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set.
|
|
*/
|
|
int
|
|
xfs_highbit64(
|
|
__uint64_t v)
|
|
{
|
|
__uint32_t h = (__uint32_t)(v >> 32);
|
|
|
|
if (h)
|
|
return xfs_highbit32(h) + 32;
|
|
return xfs_highbit32((__uint32_t)v);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return whether bitmap is empty.
|
|
* Size is number of words in the bitmap, which is padded to word boundary
|
|
* Returns 1 for empty, 0 for non-empty.
|
|
*/
|
|
int
|
|
xfs_bitmap_empty(uint *map, uint size)
|
|
{
|
|
uint i;
|
|
uint ret = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
ret |= map[i];
|
|
}
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
/*
|
|
* Count the number of contiguous bits set in the bitmap starting with bit
|
|
* start_bit. Size is the size of the bitmap in words.
|
|
*/
|
|
int
|
|
xfs_contig_bits(uint *map, uint size, uint start_bit)
|
|
{
|
|
uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
|
|
uint result = 0;
|
|
uint tmp;
|
|
|
|
size <<= BIT_TO_WORD_SHIFT;
|
|
|
|
ASSERT(start_bit < size);
|
|
size -= start_bit & ~(NBWORD - 1);
|
|
start_bit &= (NBWORD - 1);
|
|
if (start_bit) {
|
|
tmp = *p++;
|
|
/* set to one first offset bits prior to start */
|
|
tmp |= (~0U >> (NBWORD-start_bit));
|
|
if (tmp != ~0U)
|
|
goto found;
|
|
result += NBWORD;
|
|
size -= NBWORD;
|
|
}
|
|
while (size) {
|
|
if ((tmp = *p++) != ~0U)
|
|
goto found;
|
|
result += NBWORD;
|
|
size -= NBWORD;
|
|
}
|
|
return result - start_bit;
|
|
found:
|
|
return result + ffz(tmp) - start_bit;
|
|
}
|
|
|
|
/*
|
|
* This takes the bit number to start looking from and
|
|
* returns the next set bit from there. It returns -1
|
|
* if there are no more bits set or the start bit is
|
|
* beyond the end of the bitmap.
|
|
*
|
|
* Size is the number of words, not bytes, in the bitmap.
|
|
*/
|
|
int xfs_next_bit(uint *map, uint size, uint start_bit)
|
|
{
|
|
uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
|
|
uint result = start_bit & ~(NBWORD - 1);
|
|
uint tmp;
|
|
|
|
size <<= BIT_TO_WORD_SHIFT;
|
|
|
|
if (start_bit >= size)
|
|
return -1;
|
|
size -= result;
|
|
start_bit &= (NBWORD - 1);
|
|
if (start_bit) {
|
|
tmp = *p++;
|
|
/* set to zero first offset bits prior to start */
|
|
tmp &= (~0U << start_bit);
|
|
if (tmp != 0U)
|
|
goto found;
|
|
result += NBWORD;
|
|
size -= NBWORD;
|
|
}
|
|
while (size) {
|
|
if ((tmp = *p++) != 0U)
|
|
goto found;
|
|
result += NBWORD;
|
|
size -= NBWORD;
|
|
}
|
|
return -1;
|
|
found:
|
|
return result + ffs(tmp) - 1;
|
|
}
|