Commit 692223d1 authored by Fan Li's avatar Fan Li Committed by Jaegeuk Kim

f2fs: optimize __find_rev_next_bit

1. Skip __reverse_ulong if the bitmap is empty.
2. Reduce branches and codes.
According to my test, the performance of this new version is 5% higher on
an empty bitmap of 64bytes, and remains about the same in the worst scenario.
Signed-off-by: default avatarFan li <fanofcode.li@samsung.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent eb7e813c
...@@ -86,6 +86,7 @@ static inline unsigned long __reverse_ffs(unsigned long word) ...@@ -86,6 +86,7 @@ static inline unsigned long __reverse_ffs(unsigned long word)
/* /*
* __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c because * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c because
* f2fs_set_bit makes MSB and LSB reversed in a byte. * f2fs_set_bit makes MSB and LSB reversed in a byte.
* @size must be integral times of unsigned long.
* Example: * Example:
* MSB <--> LSB * MSB <--> LSB
* f2fs_set_bit(0, bitmap) => 1000 0000 * f2fs_set_bit(0, bitmap) => 1000 0000
...@@ -95,47 +96,36 @@ static unsigned long __find_rev_next_bit(const unsigned long *addr, ...@@ -95,47 +96,36 @@ static unsigned long __find_rev_next_bit(const unsigned long *addr,
unsigned long size, unsigned long offset) unsigned long size, unsigned long offset)
{ {
const unsigned long *p = addr + BIT_WORD(offset); const unsigned long *p = addr + BIT_WORD(offset);
unsigned long result = offset & ~(BITS_PER_LONG - 1); unsigned long result = size;
unsigned long tmp; unsigned long tmp;
if (offset >= size) if (offset >= size)
return size; return size;
size -= result; size -= (offset & ~(BITS_PER_LONG - 1));
offset %= BITS_PER_LONG; offset %= BITS_PER_LONG;
if (!offset)
goto aligned;
tmp = __reverse_ulong((unsigned char *)p); while (1) {
tmp &= ~0UL >> offset; if (*p == 0)
goto pass;
if (size < BITS_PER_LONG)
goto found_first;
if (tmp)
goto found_middle;
size -= BITS_PER_LONG;
result += BITS_PER_LONG;
p++;
aligned:
while (size & ~(BITS_PER_LONG-1)) {
tmp = __reverse_ulong((unsigned char *)p); tmp = __reverse_ulong((unsigned char *)p);
tmp &= ~0UL >> offset;
if (size < BITS_PER_LONG)
tmp &= (~0UL << (BITS_PER_LONG - size));
if (tmp) if (tmp)
goto found_middle; goto found;
result += BITS_PER_LONG; pass:
if (size <= BITS_PER_LONG)
break;
size -= BITS_PER_LONG; size -= BITS_PER_LONG;
offset = 0;
p++; p++;
} }
if (!size) return result;
return result; found:
return result - size + __reverse_ffs(tmp);
tmp = __reverse_ulong((unsigned char *)p);
found_first:
tmp &= (~0UL << (BITS_PER_LONG - size));
if (!tmp) /* Are any bits set? */
return result + size; /* Nope. */
found_middle:
return result + __reverse_ffs(tmp);
} }
static unsigned long __find_rev_next_zero_bit(const unsigned long *addr, static unsigned long __find_rev_next_zero_bit(const unsigned long *addr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment