1*f1b079b4SArtur Paszkiewicz /* SPDX-License-Identifier: BSD-3-Clause 2*f1b079b4SArtur Paszkiewicz * Copyright (c) Intel Corporation. 3*f1b079b4SArtur Paszkiewicz * All rights reserved. 4*f1b079b4SArtur Paszkiewicz */ 5*f1b079b4SArtur Paszkiewicz 6*f1b079b4SArtur Paszkiewicz #include "spdk/log.h" 7*f1b079b4SArtur Paszkiewicz #include "spdk/util.h" 8*f1b079b4SArtur Paszkiewicz 9*f1b079b4SArtur Paszkiewicz #include "ftl_bitmap.h" 10*f1b079b4SArtur Paszkiewicz #include "ftl_internal.h" 11*f1b079b4SArtur Paszkiewicz 12*f1b079b4SArtur Paszkiewicz typedef unsigned long bitmap_word; 13*f1b079b4SArtur Paszkiewicz 14*f1b079b4SArtur Paszkiewicz const size_t ftl_bitmap_buffer_alignment = sizeof(bitmap_word); 15*f1b079b4SArtur Paszkiewicz 16*f1b079b4SArtur Paszkiewicz #define FTL_BITMAP_WORD_SHIFT spdk_u32log2(sizeof(bitmap_word) * 8) 17*f1b079b4SArtur Paszkiewicz #define FTL_BITMAP_WORD_MASK (~(~0UL << FTL_BITMAP_WORD_SHIFT)) 18*f1b079b4SArtur Paszkiewicz 19*f1b079b4SArtur Paszkiewicz uint64_t 20*f1b079b4SArtur Paszkiewicz ftl_bitmap_bits_to_size(uint64_t bits) 21*f1b079b4SArtur Paszkiewicz { 22*f1b079b4SArtur Paszkiewicz uint64_t size; 23*f1b079b4SArtur Paszkiewicz 24*f1b079b4SArtur Paszkiewicz if (bits < ftl_bitmap_buffer_alignment) { 25*f1b079b4SArtur Paszkiewicz bits = ftl_bitmap_buffer_alignment; 26*f1b079b4SArtur Paszkiewicz } 27*f1b079b4SArtur Paszkiewicz 28*f1b079b4SArtur Paszkiewicz size = spdk_divide_round_up(bits, 8); 29*f1b079b4SArtur Paszkiewicz size = spdk_divide_round_up(size, ftl_bitmap_buffer_alignment) * ftl_bitmap_buffer_alignment; 30*f1b079b4SArtur Paszkiewicz 31*f1b079b4SArtur Paszkiewicz return size; 32*f1b079b4SArtur Paszkiewicz } 33*f1b079b4SArtur Paszkiewicz 34*f1b079b4SArtur Paszkiewicz uint64_t 35*f1b079b4SArtur Paszkiewicz ftl_bitmap_bits_to_blocks(uint64_t bits) 36*f1b079b4SArtur Paszkiewicz { 37*f1b079b4SArtur Paszkiewicz uint64_t size = ftl_bitmap_bits_to_size(bits); 38*f1b079b4SArtur Paszkiewicz 39*f1b079b4SArtur Paszkiewicz return spdk_divide_round_up(size, FTL_BLOCK_SIZE); 40*f1b079b4SArtur Paszkiewicz } 41*f1b079b4SArtur Paszkiewicz 42*f1b079b4SArtur Paszkiewicz struct ftl_bitmap { 43*f1b079b4SArtur Paszkiewicz bitmap_word *buf; 44*f1b079b4SArtur Paszkiewicz size_t size; 45*f1b079b4SArtur Paszkiewicz }; 46*f1b079b4SArtur Paszkiewicz 47*f1b079b4SArtur Paszkiewicz struct ftl_bitmap *ftl_bitmap_create(void *buf, size_t size) 48*f1b079b4SArtur Paszkiewicz { 49*f1b079b4SArtur Paszkiewicz struct ftl_bitmap *bitmap; 50*f1b079b4SArtur Paszkiewicz 51*f1b079b4SArtur Paszkiewicz if ((uintptr_t)buf % ftl_bitmap_buffer_alignment) { 52*f1b079b4SArtur Paszkiewicz SPDK_ERRLOG("Buffer for bitmap must be aligned to %lu bytes\n", 53*f1b079b4SArtur Paszkiewicz ftl_bitmap_buffer_alignment); 54*f1b079b4SArtur Paszkiewicz return NULL; 55*f1b079b4SArtur Paszkiewicz } 56*f1b079b4SArtur Paszkiewicz 57*f1b079b4SArtur Paszkiewicz if (size % ftl_bitmap_buffer_alignment) { 58*f1b079b4SArtur Paszkiewicz SPDK_ERRLOG("Size of buffer for bitmap must be divisible by %lu bytes\n", 59*f1b079b4SArtur Paszkiewicz ftl_bitmap_buffer_alignment); 60*f1b079b4SArtur Paszkiewicz return NULL; 61*f1b079b4SArtur Paszkiewicz } 62*f1b079b4SArtur Paszkiewicz 63*f1b079b4SArtur Paszkiewicz bitmap = calloc(1, sizeof(*bitmap)); 64*f1b079b4SArtur Paszkiewicz if (!bitmap) { 65*f1b079b4SArtur Paszkiewicz return NULL; 66*f1b079b4SArtur Paszkiewicz } 67*f1b079b4SArtur Paszkiewicz 68*f1b079b4SArtur Paszkiewicz bitmap->buf = buf; 69*f1b079b4SArtur Paszkiewicz bitmap->size = size / sizeof(bitmap_word); 70*f1b079b4SArtur Paszkiewicz 71*f1b079b4SArtur Paszkiewicz return bitmap; 72*f1b079b4SArtur Paszkiewicz } 73*f1b079b4SArtur Paszkiewicz 74*f1b079b4SArtur Paszkiewicz void 75*f1b079b4SArtur Paszkiewicz ftl_bitmap_destroy(struct ftl_bitmap *bitmap) 76*f1b079b4SArtur Paszkiewicz { 77*f1b079b4SArtur Paszkiewicz free(bitmap); 78*f1b079b4SArtur Paszkiewicz } 79*f1b079b4SArtur Paszkiewicz 80*f1b079b4SArtur Paszkiewicz static inline void 81*f1b079b4SArtur Paszkiewicz locate_bit(const struct ftl_bitmap *bitmap, uint64_t bit, 82*f1b079b4SArtur Paszkiewicz bitmap_word **word_out, uint8_t *word_bit_idx_out) 83*f1b079b4SArtur Paszkiewicz { 84*f1b079b4SArtur Paszkiewicz size_t word_idx = bit >> FTL_BITMAP_WORD_SHIFT; 85*f1b079b4SArtur Paszkiewicz 86*f1b079b4SArtur Paszkiewicz assert(word_idx < bitmap->size); 87*f1b079b4SArtur Paszkiewicz 88*f1b079b4SArtur Paszkiewicz *word_bit_idx_out = bit & FTL_BITMAP_WORD_MASK; 89*f1b079b4SArtur Paszkiewicz *word_out = &bitmap->buf[word_idx]; 90*f1b079b4SArtur Paszkiewicz } 91*f1b079b4SArtur Paszkiewicz 92*f1b079b4SArtur Paszkiewicz bool 93*f1b079b4SArtur Paszkiewicz ftl_bitmap_get(const struct ftl_bitmap *bitmap, uint64_t bit) 94*f1b079b4SArtur Paszkiewicz { 95*f1b079b4SArtur Paszkiewicz bitmap_word *word; 96*f1b079b4SArtur Paszkiewicz uint8_t word_bit_idx; 97*f1b079b4SArtur Paszkiewicz 98*f1b079b4SArtur Paszkiewicz locate_bit(bitmap, bit, &word, &word_bit_idx); 99*f1b079b4SArtur Paszkiewicz 100*f1b079b4SArtur Paszkiewicz return *word & (1UL << word_bit_idx); 101*f1b079b4SArtur Paszkiewicz } 102*f1b079b4SArtur Paszkiewicz 103*f1b079b4SArtur Paszkiewicz void 104*f1b079b4SArtur Paszkiewicz ftl_bitmap_set(struct ftl_bitmap *bitmap, uint64_t bit) 105*f1b079b4SArtur Paszkiewicz { 106*f1b079b4SArtur Paszkiewicz bitmap_word *word; 107*f1b079b4SArtur Paszkiewicz uint8_t word_bit_idx; 108*f1b079b4SArtur Paszkiewicz 109*f1b079b4SArtur Paszkiewicz locate_bit(bitmap, bit, &word, &word_bit_idx); 110*f1b079b4SArtur Paszkiewicz 111*f1b079b4SArtur Paszkiewicz *word |= (1UL << word_bit_idx); 112*f1b079b4SArtur Paszkiewicz } 113*f1b079b4SArtur Paszkiewicz 114*f1b079b4SArtur Paszkiewicz void 115*f1b079b4SArtur Paszkiewicz ftl_bitmap_clear(struct ftl_bitmap *bitmap, uint64_t bit) 116*f1b079b4SArtur Paszkiewicz { 117*f1b079b4SArtur Paszkiewicz bitmap_word *word; 118*f1b079b4SArtur Paszkiewicz uint8_t word_bit_idx; 119*f1b079b4SArtur Paszkiewicz 120*f1b079b4SArtur Paszkiewicz locate_bit(bitmap, bit, &word, &word_bit_idx); 121*f1b079b4SArtur Paszkiewicz 122*f1b079b4SArtur Paszkiewicz *word &= ~(1UL << word_bit_idx); 123*f1b079b4SArtur Paszkiewicz } 124*f1b079b4SArtur Paszkiewicz 125*f1b079b4SArtur Paszkiewicz static uint64_t 126*f1b079b4SArtur Paszkiewicz ftl_bitmap_find_first(struct ftl_bitmap *bitmap, uint64_t start_bit, 127*f1b079b4SArtur Paszkiewicz uint64_t end_bit, bool value) 128*f1b079b4SArtur Paszkiewicz { 129*f1b079b4SArtur Paszkiewicz bitmap_word skip = (value ? 0 : ~0UL); 130*f1b079b4SArtur Paszkiewicz bitmap_word word; 131*f1b079b4SArtur Paszkiewicz size_t i, end; 132*f1b079b4SArtur Paszkiewicz uint64_t ret; 133*f1b079b4SArtur Paszkiewicz 134*f1b079b4SArtur Paszkiewicz assert(start_bit <= end_bit); 135*f1b079b4SArtur Paszkiewicz 136*f1b079b4SArtur Paszkiewicz i = start_bit >> FTL_BITMAP_WORD_SHIFT; 137*f1b079b4SArtur Paszkiewicz assert(i < bitmap->size); 138*f1b079b4SArtur Paszkiewicz 139*f1b079b4SArtur Paszkiewicz word = (bitmap->buf[i] ^ skip) & (~0UL << (start_bit & FTL_BITMAP_WORD_MASK)); 140*f1b079b4SArtur Paszkiewicz if (word != 0) { 141*f1b079b4SArtur Paszkiewicz goto found; 142*f1b079b4SArtur Paszkiewicz } 143*f1b079b4SArtur Paszkiewicz 144*f1b079b4SArtur Paszkiewicz end = spdk_min((end_bit >> FTL_BITMAP_WORD_SHIFT) + 1, bitmap->size); 145*f1b079b4SArtur Paszkiewicz for (i = i + 1; i < end; i++) { 146*f1b079b4SArtur Paszkiewicz word = bitmap->buf[i] ^ skip; 147*f1b079b4SArtur Paszkiewicz if (word != 0) { 148*f1b079b4SArtur Paszkiewicz goto found; 149*f1b079b4SArtur Paszkiewicz } 150*f1b079b4SArtur Paszkiewicz } 151*f1b079b4SArtur Paszkiewicz 152*f1b079b4SArtur Paszkiewicz return UINT64_MAX; 153*f1b079b4SArtur Paszkiewicz found: 154*f1b079b4SArtur Paszkiewicz ret = (i << FTL_BITMAP_WORD_SHIFT) + __builtin_ctzl(word); 155*f1b079b4SArtur Paszkiewicz if (ret > end_bit) { 156*f1b079b4SArtur Paszkiewicz return UINT64_MAX; 157*f1b079b4SArtur Paszkiewicz } 158*f1b079b4SArtur Paszkiewicz return ret; 159*f1b079b4SArtur Paszkiewicz } 160*f1b079b4SArtur Paszkiewicz 161*f1b079b4SArtur Paszkiewicz uint64_t 162*f1b079b4SArtur Paszkiewicz ftl_bitmap_find_first_set(struct ftl_bitmap *bitmap, uint64_t start_bit, uint64_t end_bit) 163*f1b079b4SArtur Paszkiewicz { 164*f1b079b4SArtur Paszkiewicz return ftl_bitmap_find_first(bitmap, start_bit, end_bit, true); 165*f1b079b4SArtur Paszkiewicz } 166*f1b079b4SArtur Paszkiewicz 167*f1b079b4SArtur Paszkiewicz uint64_t 168*f1b079b4SArtur Paszkiewicz ftl_bitmap_find_first_clear(struct ftl_bitmap *bitmap, uint64_t start_bit, 169*f1b079b4SArtur Paszkiewicz uint64_t end_bit) 170*f1b079b4SArtur Paszkiewicz { 171*f1b079b4SArtur Paszkiewicz return ftl_bitmap_find_first(bitmap, start_bit, end_bit, false); 172*f1b079b4SArtur Paszkiewicz } 173*f1b079b4SArtur Paszkiewicz 174*f1b079b4SArtur Paszkiewicz uint64_t 175*f1b079b4SArtur Paszkiewicz ftl_bitmap_count_set(struct ftl_bitmap *bitmap) 176*f1b079b4SArtur Paszkiewicz { 177*f1b079b4SArtur Paszkiewicz size_t i; 178*f1b079b4SArtur Paszkiewicz bitmap_word *word = bitmap->buf; 179*f1b079b4SArtur Paszkiewicz uint64_t count = 0; 180*f1b079b4SArtur Paszkiewicz 181*f1b079b4SArtur Paszkiewicz for (i = 0; i < bitmap->size; i++, word++) { 182*f1b079b4SArtur Paszkiewicz count += __builtin_popcountl(*word); 183*f1b079b4SArtur Paszkiewicz } 184*f1b079b4SArtur Paszkiewicz 185*f1b079b4SArtur Paszkiewicz return count; 186*f1b079b4SArtur Paszkiewicz } 187