[Concept,14/15] ext4l: Fix bit operations for bits beyond first word
Commit Message
From: Simon Glass <simon.glass@canonical.com>
The set_bit(), clear_bit(), and change_bit() functions only modify the
first word of a bitmap, regardless of the bit number. For bit numbers
>= 64 on 64-bit systems, the shift wraps around and modifies the wrong
bit position.
Fix these functions to properly calculate the word offset before
modifying the bit. This is needed for block bitmap operations where bit
numbers can be in the thousands.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---
fs/ext4l/stub.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
@@ -77,26 +77,27 @@ typedef struct journal_s journal_t;
/*
* Bit operations - sandbox declares these extern but doesn't implement them.
+ * These work on bitmaps where nr is the absolute bit number.
*/
void set_bit(int nr, void *addr)
{
- unsigned long *p = (unsigned long *)addr;
+ unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG);
- *p |= (1UL << nr);
+ *p |= (1UL << (nr % BITS_PER_LONG));
}
void clear_bit(int nr, void *addr)
{
- unsigned long *p = (unsigned long *)addr;
+ unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG);
- *p &= ~(1UL << nr);
+ *p &= ~(1UL << (nr % BITS_PER_LONG));
}
void change_bit(int nr, void *addr)
{
- unsigned long *p = (unsigned long *)addr;
+ unsigned long *p = (unsigned long *)addr + (nr / BITS_PER_LONG);
- *p ^= (1UL << nr);
+ *p ^= (1UL << (nr % BITS_PER_LONG));
}
/*