fs/ntfs3: Add ntfs_bitmap_weight_le function and refactoring

Added ntfs_bitmap_weight_le function.
Changed argument types of bits/bitmap functions.

Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
This commit is contained in:
Konstantin Komarov 2022-10-06 19:42:24 +03:00
parent 095d8ce635
commit 08811ba59a
No known key found for this signature in database
GPG Key ID: A9B0331F832407B6
3 changed files with 63 additions and 52 deletions

View File

@ -30,7 +30,7 @@ static const u8 zero_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
* *
* Return: True if all bits [bit, bit+nbits) are zeros "0". * Return: True if all bits [bit, bit+nbits) are zeros "0".
*/ */
bool are_bits_clear(const ulong *lmap, size_t bit, size_t nbits) bool are_bits_clear(const void *lmap, size_t bit, size_t nbits)
{ {
size_t pos = bit & 7; size_t pos = bit & 7;
const u8 *map = (u8 *)lmap + (bit >> 3); const u8 *map = (u8 *)lmap + (bit >> 3);
@ -78,7 +78,7 @@ bool are_bits_clear(const ulong *lmap, size_t bit, size_t nbits)
* *
* Return: True if all bits [bit, bit+nbits) are ones "1". * Return: True if all bits [bit, bit+nbits) are ones "1".
*/ */
bool are_bits_set(const ulong *lmap, size_t bit, size_t nbits) bool are_bits_set(const void *lmap, size_t bit, size_t nbits)
{ {
u8 mask; u8 mask;
size_t pos = bit & 7; size_t pos = bit & 7;

View File

@ -59,7 +59,7 @@ void ntfs3_exit_bitmap(void)
* *
* Return: -1 if not found. * Return: -1 if not found.
*/ */
static size_t wnd_scan(const ulong *buf, size_t wbit, u32 wpos, u32 wend, static size_t wnd_scan(const void *buf, size_t wbit, u32 wpos, u32 wend,
size_t to_alloc, size_t *prev_tail, size_t *b_pos, size_t to_alloc, size_t *prev_tail, size_t *b_pos,
size_t *b_len) size_t *b_len)
{ {
@ -504,7 +504,6 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
u8 cluster_bits = sbi->cluster_bits; u8 cluster_bits = sbi->cluster_bits;
u32 wbits = 8 * sb->s_blocksize; u32 wbits = 8 * sb->s_blocksize;
u32 used, frb; u32 used, frb;
const ulong *buf;
size_t wpos, wbit, iw, vbo; size_t wpos, wbit, iw, vbo;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
CLST lcn, clen; CLST lcn, clen;
@ -558,9 +557,7 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
goto out; goto out;
} }
buf = (ulong *)bh->b_data; used = ntfs_bitmap_weight_le(bh->b_data, wbits);
used = __bitmap_weight(buf, wbits);
if (used < wbits) { if (used < wbits) {
frb = wbits - used; frb = wbits - used;
wnd->free_bits[iw] = frb; wnd->free_bits[iw] = frb;
@ -574,7 +571,7 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
wbits = wnd->nbits - wbit; wbits = wnd->nbits - wbit;
do { do {
used = find_next_zero_bit_le(buf, wbits, wpos); used = find_next_zero_bit_le(bh->b_data, wbits, wpos);
if (used > wpos && prev_tail) { if (used > wpos && prev_tail) {
wnd_add_free_ext(wnd, wbit + wpos - prev_tail, wnd_add_free_ext(wnd, wbit + wpos - prev_tail,
@ -590,7 +587,7 @@ static int wnd_rescan(struct wnd_bitmap *wnd)
break; break;
} }
frb = find_next_bit_le(buf, wbits, wpos); frb = find_next_bit_le(bh->b_data, wbits, wpos);
if (frb >= wbits) { if (frb >= wbits) {
/* Keep last free block. */ /* Keep last free block. */
prev_tail += frb - wpos; prev_tail += frb - wpos;
@ -718,7 +715,6 @@ int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
while (iw < wnd->nwnd && bits) { while (iw < wnd->nwnd && bits) {
u32 tail, op; u32 tail, op;
ulong *buf;
if (iw + 1 == wnd->nwnd) if (iw + 1 == wnd->nwnd)
wbits = wnd->bits_last; wbits = wnd->bits_last;
@ -732,11 +728,9 @@ int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits)
break; break;
} }
buf = (ulong *)bh->b_data;
lock_buffer(bh); lock_buffer(bh);
ntfs_bitmap_clear_le(buf, wbit, op); ntfs_bitmap_clear_le(bh->b_data, wbit, op);
wnd->free_bits[iw] += op; wnd->free_bits[iw] += op;
@ -771,7 +765,6 @@ int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
while (iw < wnd->nwnd && bits) { while (iw < wnd->nwnd && bits) {
u32 tail, op; u32 tail, op;
ulong *buf;
if (unlikely(iw + 1 == wnd->nwnd)) if (unlikely(iw + 1 == wnd->nwnd))
wbits = wnd->bits_last; wbits = wnd->bits_last;
@ -784,11 +777,10 @@ int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits)
err = PTR_ERR(bh); err = PTR_ERR(bh);
break; break;
} }
buf = (ulong *)bh->b_data;
lock_buffer(bh); lock_buffer(bh);
ntfs_bitmap_set_le(buf, wbit, op); ntfs_bitmap_set_le(bh->b_data, wbit, op);
wnd->free_bits[iw] -= op; wnd->free_bits[iw] -= op;
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
@ -836,7 +828,7 @@ static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits)
if (IS_ERR(bh)) if (IS_ERR(bh))
return false; return false;
ret = are_bits_clear((ulong *)bh->b_data, wbit, op); ret = are_bits_clear(bh->b_data, wbit, op);
put_bh(bh); put_bh(bh);
if (!ret) if (!ret)
@ -928,7 +920,7 @@ use_wnd:
if (IS_ERR(bh)) if (IS_ERR(bh))
goto out; goto out;
ret = are_bits_set((ulong *)bh->b_data, wbit, op); ret = are_bits_set(bh->b_data, wbit, op);
put_bh(bh); put_bh(bh);
if (!ret) if (!ret)
goto out; goto out;
@ -959,7 +951,6 @@ size_t wnd_find(struct wnd_bitmap *wnd, size_t to_alloc, size_t hint,
size_t fnd, max_alloc, b_len, b_pos; size_t fnd, max_alloc, b_len, b_pos;
size_t iw, prev_tail, nwnd, wbit, ebit, zbit, zend; size_t iw, prev_tail, nwnd, wbit, ebit, zbit, zend;
size_t to_alloc0 = to_alloc; size_t to_alloc0 = to_alloc;
const ulong *buf;
const struct e_node *e; const struct e_node *e;
const struct rb_node *pr, *cr; const struct rb_node *pr, *cr;
u8 log2_bits; u8 log2_bits;
@ -1185,14 +1176,13 @@ Again:
continue; continue;
} }
buf = (ulong *)bh->b_data;
/* Scan range [wbit, zbit). */ /* Scan range [wbit, zbit). */
if (wpos < wzbit) { if (wpos < wzbit) {
/* Scan range [wpos, zbit). */ /* Scan range [wpos, zbit). */
fnd = wnd_scan(buf, wbit, wpos, wzbit, fnd = wnd_scan(bh->b_data, wbit, wpos,
to_alloc, &prev_tail, wzbit, to_alloc,
&b_pos, &b_len); &prev_tail, &b_pos,
&b_len);
if (fnd != MINUS_ONE_T) { if (fnd != MINUS_ONE_T) {
put_bh(bh); put_bh(bh);
goto found; goto found;
@ -1203,7 +1193,7 @@ Again:
/* Scan range [zend, ebit). */ /* Scan range [zend, ebit). */
if (wzend < wbits) { if (wzend < wbits) {
fnd = wnd_scan(buf, wbit, fnd = wnd_scan(bh->b_data, wbit,
max(wzend, wpos), wbits, max(wzend, wpos), wbits,
to_alloc, &prev_tail, to_alloc, &prev_tail,
&b_pos, &b_len); &b_pos, &b_len);
@ -1242,11 +1232,9 @@ Again:
continue; continue;
} }
buf = (ulong *)bh->b_data;
/* Scan range [wpos, eBits). */ /* Scan range [wpos, eBits). */
fnd = wnd_scan(buf, wbit, wpos, wbits, to_alloc, &prev_tail, fnd = wnd_scan(bh->b_data, wbit, wpos, wbits, to_alloc,
&b_pos, &b_len); &prev_tail, &b_pos, &b_len);
put_bh(bh); put_bh(bh);
if (fnd != MINUS_ONE_T) if (fnd != MINUS_ONE_T)
goto found; goto found;
@ -1344,7 +1332,6 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
size_t frb; size_t frb;
u64 vbo, lbo, bytes; u64 vbo, lbo, bytes;
struct buffer_head *bh; struct buffer_head *bh;
ulong *buf;
if (iw + 1 == new_wnd) if (iw + 1 == new_wnd)
wbits = new_last; wbits = new_last;
@ -1361,10 +1348,9 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits)
return -EIO; return -EIO;
lock_buffer(bh); lock_buffer(bh);
buf = (ulong *)bh->b_data;
ntfs_bitmap_clear_le(buf, b0, blocksize * 8 - b0); ntfs_bitmap_clear_le(bh->b_data, b0, blocksize * 8 - b0);
frb = wbits - __bitmap_weight(buf, wbits); frb = wbits - ntfs_bitmap_weight_le(bh->b_data, wbits);
wnd->total_zeroes += frb - wnd->free_bits[iw]; wnd->total_zeroes += frb - wnd->free_bits[iw];
wnd->free_bits[iw] = frb; wnd->free_bits[iw] = frb;
@ -1411,7 +1397,6 @@ int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range)
CLST lcn_from = bytes_to_cluster(sbi, range->start); CLST lcn_from = bytes_to_cluster(sbi, range->start);
size_t iw = lcn_from >> (sb->s_blocksize_bits + 3); size_t iw = lcn_from >> (sb->s_blocksize_bits + 3);
u32 wbit = lcn_from & (wbits - 1); u32 wbit = lcn_from & (wbits - 1);
const ulong *buf;
CLST lcn_to; CLST lcn_to;
if (!minlen) if (!minlen)
@ -1446,10 +1431,8 @@ int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range)
break; break;
} }
buf = (ulong *)bh->b_data;
for (; wbit < wbits; wbit++) { for (; wbit < wbits; wbit++) {
if (!test_bit_le(wbit, buf)) { if (!test_bit_le(wbit, bh->b_data)) {
if (!len) if (!len)
lcn = lcn_wnd + wbit; lcn = lcn_wnd + wbit;
len += 1; len += 1;
@ -1482,42 +1465,69 @@ out:
return err; return err;
} }
void ntfs_bitmap_set_le(unsigned long *map, unsigned int start, int len) #if BITS_PER_LONG == 64
typedef __le64 bitmap_ulong;
#define cpu_to_ul(x) cpu_to_le64(x)
#define ul_to_cpu(x) le64_to_cpu(x)
#else
typedef __le32 bitmap_ulong;
#define cpu_to_ul(x) cpu_to_le32(x)
#define ul_to_cpu(x) le32_to_cpu(x)
#endif
void ntfs_bitmap_set_le(void *map, unsigned int start, int len)
{ {
unsigned long *p = map + BIT_WORD(start); bitmap_ulong *p = (bitmap_ulong *)map + BIT_WORD(start);
const unsigned int size = start + len; const unsigned int size = start + len;
int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_set = cpu_to_le32(BITMAP_FIRST_WORD_MASK(start)); bitmap_ulong mask_to_set = cpu_to_ul(BITMAP_FIRST_WORD_MASK(start));
while (len - bits_to_set >= 0) { while (len - bits_to_set >= 0) {
*p |= mask_to_set; *p |= mask_to_set;
len -= bits_to_set; len -= bits_to_set;
bits_to_set = BITS_PER_LONG; bits_to_set = BITS_PER_LONG;
mask_to_set = ~0UL; mask_to_set = cpu_to_ul(~0UL);
p++; p++;
} }
if (len) { if (len) {
mask_to_set &= cpu_to_le32(BITMAP_LAST_WORD_MASK(size)); mask_to_set &= cpu_to_ul(BITMAP_LAST_WORD_MASK(size));
*p |= mask_to_set; *p |= mask_to_set;
} }
} }
void ntfs_bitmap_clear_le(unsigned long *map, unsigned int start, int len) void ntfs_bitmap_clear_le(void *map, unsigned int start, int len)
{ {
unsigned long *p = map + BIT_WORD(start); bitmap_ulong *p = (bitmap_ulong *)map + BIT_WORD(start);
const unsigned int size = start + len; const unsigned int size = start + len;
int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_clear = cpu_to_le32(BITMAP_FIRST_WORD_MASK(start)); bitmap_ulong mask_to_clear = cpu_to_ul(BITMAP_FIRST_WORD_MASK(start));
while (len - bits_to_clear >= 0) { while (len - bits_to_clear >= 0) {
*p &= ~mask_to_clear; *p &= ~mask_to_clear;
len -= bits_to_clear; len -= bits_to_clear;
bits_to_clear = BITS_PER_LONG; bits_to_clear = BITS_PER_LONG;
mask_to_clear = ~0UL; mask_to_clear = cpu_to_ul(~0UL);
p++; p++;
} }
if (len) { if (len) {
mask_to_clear &= cpu_to_le32(BITMAP_LAST_WORD_MASK(size)); mask_to_clear &= cpu_to_ul(BITMAP_LAST_WORD_MASK(size));
*p &= ~mask_to_clear; *p &= ~mask_to_clear;
} }
} }
unsigned int ntfs_bitmap_weight_le(const void *bitmap, int bits)
{
const ulong *bmp = bitmap;
unsigned int k, lim = bits / BITS_PER_LONG;
unsigned int w = 0;
for (k = 0; k < lim; k++)
w += hweight_long(bmp[k]);
if (bits % BITS_PER_LONG) {
w += hweight_long(ul_to_cpu(((bitmap_ulong *)bitmap)[k]) &
BITMAP_LAST_WORD_MASK(bits));
}
return w;
}

View File

@ -472,9 +472,9 @@ static inline size_t al_aligned(size_t size)
} }
/* Globals from bitfunc.c */ /* Globals from bitfunc.c */
bool are_bits_clear(const ulong *map, size_t bit, size_t nbits); bool are_bits_clear(const void *map, size_t bit, size_t nbits);
bool are_bits_set(const ulong *map, size_t bit, size_t nbits); bool are_bits_set(const void *map, size_t bit, size_t nbits);
size_t get_set_bits_ex(const ulong *map, size_t bit, size_t nbits); size_t get_set_bits_ex(const void *map, size_t bit, size_t nbits);
/* Globals from dir.c */ /* Globals from dir.c */
int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const __le16 *name, u32 len, int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const __le16 *name, u32 len,
@ -839,8 +839,9 @@ int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits);
void wnd_zone_set(struct wnd_bitmap *wnd, size_t Lcn, size_t Len); void wnd_zone_set(struct wnd_bitmap *wnd, size_t Lcn, size_t Len);
int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range); int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range);
void ntfs_bitmap_set_le(unsigned long *map, unsigned int start, int len); void ntfs_bitmap_set_le(void *map, unsigned int start, int len);
void ntfs_bitmap_clear_le(unsigned long *map, unsigned int start, int len); void ntfs_bitmap_clear_le(void *map, unsigned int start, int len);
unsigned int ntfs_bitmap_weight_le(const void *bitmap, int bits);
/* Globals from upcase.c */ /* Globals from upcase.c */
int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2, int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,