sbitmap: push per-cpu last_tag into sbitmap_queue

Allocating your own per-cpu allocation hint separately makes for an
awkward API. Instead, allocate the per-cpu hint as part of the struct
sbitmap_queue. There's no point for a struct sbitmap_queue without the
cache, but you can still use a bare struct sbitmap.

Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
Omar Sandoval 2016-09-17 01:28:23 -07:00 committed by Jens Axboe
parent 48e28166a7
commit 40aabb6746
6 changed files with 98 additions and 42 deletions

View file

@ -205,11 +205,18 @@ int sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth,
if (ret)
return ret;
sbq->alloc_hint = alloc_percpu_gfp(unsigned int, flags);
if (!sbq->alloc_hint) {
sbitmap_free(&sbq->sb);
return -ENOMEM;
}
sbq->wake_batch = sbq_calc_wake_batch(depth);
atomic_set(&sbq->wake_index, 0);
sbq->ws = kzalloc_node(SBQ_WAIT_QUEUES * sizeof(*sbq->ws), flags, node);
if (!sbq->ws) {
free_percpu(sbq->alloc_hint);
sbitmap_free(&sbq->sb);
return -ENOMEM;
}
@ -229,6 +236,29 @@ void sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth)
}
EXPORT_SYMBOL_GPL(sbitmap_queue_resize);
int __sbitmap_queue_get(struct sbitmap_queue *sbq, bool round_robin)
{
unsigned int hint;
int nr;
hint = this_cpu_read(*sbq->alloc_hint);
nr = sbitmap_get(&sbq->sb, hint, round_robin);
if (nr == -1) {
/* If the map is full, a hint won't do us much good. */
this_cpu_write(*sbq->alloc_hint, 0);
} else if (nr == hint || unlikely(round_robin)) {
/* Only update the hint if we used it. */
hint = nr + 1;
if (hint >= sbq->sb.depth - 1)
hint = 0;
this_cpu_write(*sbq->alloc_hint, hint);
}
return nr;
}
EXPORT_SYMBOL_GPL(__sbitmap_queue_get);
static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq)
{
int i, wake_index;
@ -273,10 +303,13 @@ static void sbq_wake_up(struct sbitmap_queue *sbq)
}
}
void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr)
void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr,
bool round_robin, unsigned int cpu)
{
sbitmap_clear_bit(&sbq->sb, nr);
sbq_wake_up(sbq);
if (likely(!round_robin))
*per_cpu_ptr(sbq->alloc_hint, cpu) = nr;
}
EXPORT_SYMBOL_GPL(sbitmap_queue_clear);