Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7930d0a0 authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

sbitmap: introduce __sbitmap_for_each_set()



For blk-mq, we need to be able to iterate software queues starting
from any queue in a round robin fashion, so introduce this helper.

Reviewed-by: default avatarOmar Sandoval <osandov@fb.com>
Cc: Omar Sandoval <osandov@fb.com>
Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent caf8eb0d
Loading
Loading
Loading
Loading
+47 −17
Original line number Original line Diff line number Diff line
@@ -211,10 +211,14 @@ bool sbitmap_any_bit_set(const struct sbitmap *sb);
 */
 */
bool sbitmap_any_bit_clear(const struct sbitmap *sb);
bool sbitmap_any_bit_clear(const struct sbitmap *sb);


#define SB_NR_TO_INDEX(sb, bitnr) ((bitnr) >> (sb)->shift)
#define SB_NR_TO_BIT(sb, bitnr) ((bitnr) & ((1U << (sb)->shift) - 1U))

typedef bool (*sb_for_each_fn)(struct sbitmap *, unsigned int, void *);
typedef bool (*sb_for_each_fn)(struct sbitmap *, unsigned int, void *);


/**
/**
 * sbitmap_for_each_set() - Iterate over each set bit in a &struct sbitmap.
 * __sbitmap_for_each_set() - Iterate over each set bit in a &struct sbitmap.
 * @start: Where to start the iteration.
 * @sb: Bitmap to iterate over.
 * @sb: Bitmap to iterate over.
 * @fn: Callback. Should return true to continue or false to break early.
 * @fn: Callback. Should return true to continue or false to break early.
 * @data: Pointer to pass to callback.
 * @data: Pointer to pass to callback.
@@ -222,35 +226,61 @@ typedef bool (*sb_for_each_fn)(struct sbitmap *, unsigned int, void *);
 * This is inline even though it's non-trivial so that the function calls to the
 * This is inline even though it's non-trivial so that the function calls to the
 * callback will hopefully get optimized away.
 * callback will hopefully get optimized away.
 */
 */
static inline void sbitmap_for_each_set(struct sbitmap *sb, sb_for_each_fn fn,
static inline void __sbitmap_for_each_set(struct sbitmap *sb,
					void *data)
					  unsigned int start,
					  sb_for_each_fn fn, void *data)
{
{
	unsigned int i;
	unsigned int index;
	unsigned int nr;
	unsigned int scanned = 0;


	for (i = 0; i < sb->map_nr; i++) {
	if (start >= sb->depth)
		struct sbitmap_word *word = &sb->map[i];
		start = 0;
		unsigned int off, nr;
	index = SB_NR_TO_INDEX(sb, start);
	nr = SB_NR_TO_BIT(sb, start);


	while (scanned < sb->depth) {
		struct sbitmap_word *word = &sb->map[index];
		unsigned int depth = min_t(unsigned int, word->depth - nr,
					   sb->depth - scanned);

		scanned += depth;
		if (!word->word)
		if (!word->word)
			continue;
			goto next;


		nr = 0;
		/*
		off = i << sb->shift;
		 * On the first iteration of the outer loop, we need to add the
		 * bit offset back to the size of the word for find_next_bit().
		 * On all other iterations, nr is zero, so this is a noop.
		 */
		depth += nr;
		while (1) {
		while (1) {
			nr = find_next_bit(&word->word, word->depth, nr);
			nr = find_next_bit(&word->word, depth, nr);
			if (nr >= word->depth)
			if (nr >= depth)
				break;
				break;

			if (!fn(sb, (index << sb->shift) + nr, data))
			if (!fn(sb, off + nr, data))
				return;
				return;


			nr++;
			nr++;
		}
		}
next:
		nr = 0;
		if (++index >= sb->map_nr)
			index = 0;
	}
	}
}
}


#define SB_NR_TO_INDEX(sb, bitnr) ((bitnr) >> (sb)->shift)
/**
#define SB_NR_TO_BIT(sb, bitnr) ((bitnr) & ((1U << (sb)->shift) - 1U))
 * sbitmap_for_each_set() - Iterate over each set bit in a &struct sbitmap.
 * @sb: Bitmap to iterate over.
 * @fn: Callback. Should return true to continue or false to break early.
 * @data: Pointer to pass to callback.
 */
static inline void sbitmap_for_each_set(struct sbitmap *sb, sb_for_each_fn fn,
					void *data)
{
	__sbitmap_for_each_set(sb, 0, fn, data);
}


static inline unsigned long *__sbitmap_word(struct sbitmap *sb,
static inline unsigned long *__sbitmap_word(struct sbitmap *sb,
					    unsigned int bitnr)
					    unsigned int bitnr)