aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sbitmap.c
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2018-05-09 20:16:31 -0400
committerJens Axboe <axboe@kernel.dk>2018-05-10 13:27:36 -0400
commita327553965dede92587e6ccbe7df98dba36edcea (patch)
treefe246813d7d48402820808661697ff3f544ed484 /lib/sbitmap.c
parentbd7d4ef6a4c9b3611fa487a0065bf042c71ce620 (diff)
sbitmap: fix missed wakeups caused by sbitmap_queue_get_shallow()
The sbitmap queue wake batch is calculated such that once allocations start blocking, all of the bits which are already allocated must be enough to fulfill the batch counters of all of the waitqueues. However, the shallow allocation depth can break this invariant, since we block before our full depth is being utilized. Add sbitmap_queue_min_shallow_depth(), which saves the minimum shallow depth the sbq will use, and update sbq_calc_wake_batch() to take it into account. Acked-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'lib/sbitmap.c')
-rw-r--r--lib/sbitmap.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/lib/sbitmap.c b/lib/sbitmap.c
index e6a9c06ec70c..d21473b42465 100644
--- a/lib/sbitmap.c
+++ b/lib/sbitmap.c
@@ -270,18 +270,33 @@ void sbitmap_bitmap_show(struct sbitmap *sb, struct seq_file *m)
270} 270}
271EXPORT_SYMBOL_GPL(sbitmap_bitmap_show); 271EXPORT_SYMBOL_GPL(sbitmap_bitmap_show);
272 272
273static unsigned int sbq_calc_wake_batch(unsigned int depth) 273static unsigned int sbq_calc_wake_batch(struct sbitmap_queue *sbq,
274 unsigned int depth)
274{ 275{
275 unsigned int wake_batch; 276 unsigned int wake_batch;
277 unsigned int shallow_depth;
276 278
277 /* 279 /*
278 * For each batch, we wake up one queue. We need to make sure that our 280 * For each batch, we wake up one queue. We need to make sure that our
279 * batch size is small enough that the full depth of the bitmap is 281 * batch size is small enough that the full depth of the bitmap,
280 * enough to wake up all of the queues. 282 * potentially limited by a shallow depth, is enough to wake up all of
283 * the queues.
284 *
285 * Each full word of the bitmap has bits_per_word bits, and there might
286 * be a partial word. There are depth / bits_per_word full words and
287 * depth % bits_per_word bits left over. In bitwise arithmetic:
288 *
289 * bits_per_word = 1 << shift
290 * depth / bits_per_word = depth >> shift
291 * depth % bits_per_word = depth & ((1 << shift) - 1)
292 *
293 * Each word can be limited to sbq->min_shallow_depth bits.
281 */ 294 */
282 wake_batch = SBQ_WAKE_BATCH; 295 shallow_depth = min(1U << sbq->sb.shift, sbq->min_shallow_depth);
283 if (wake_batch > depth / SBQ_WAIT_QUEUES) 296 depth = ((depth >> sbq->sb.shift) * shallow_depth +
284 wake_batch = max(1U, depth / SBQ_WAIT_QUEUES); 297 min(depth & ((1U << sbq->sb.shift) - 1), shallow_depth));
298 wake_batch = clamp_t(unsigned int, depth / SBQ_WAIT_QUEUES, 1,
299 SBQ_WAKE_BATCH);
285 300
286 return wake_batch; 301 return wake_batch;
287} 302}
@@ -307,7 +322,8 @@ int sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth,
307 *per_cpu_ptr(sbq->alloc_hint, i) = prandom_u32() % depth; 322 *per_cpu_ptr(sbq->alloc_hint, i) = prandom_u32() % depth;
308 } 323 }
309 324
310 sbq->wake_batch = sbq_calc_wake_batch(depth); 325 sbq->min_shallow_depth = UINT_MAX;
326 sbq->wake_batch = sbq_calc_wake_batch(sbq, depth);
311 atomic_set(&sbq->wake_index, 0); 327 atomic_set(&sbq->wake_index, 0);
312 328
313 sbq->ws = kzalloc_node(SBQ_WAIT_QUEUES * sizeof(*sbq->ws), flags, node); 329 sbq->ws = kzalloc_node(SBQ_WAIT_QUEUES * sizeof(*sbq->ws), flags, node);
@@ -327,9 +343,10 @@ int sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth,
327} 343}
328EXPORT_SYMBOL_GPL(sbitmap_queue_init_node); 344EXPORT_SYMBOL_GPL(sbitmap_queue_init_node);
329 345
330void sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth) 346static void sbitmap_queue_update_wake_batch(struct sbitmap_queue *sbq,
347 unsigned int depth)
331{ 348{
332 unsigned int wake_batch = sbq_calc_wake_batch(depth); 349 unsigned int wake_batch = sbq_calc_wake_batch(sbq, depth);
333 int i; 350 int i;
334 351
335 if (sbq->wake_batch != wake_batch) { 352 if (sbq->wake_batch != wake_batch) {
@@ -342,6 +359,11 @@ void sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth)
342 for (i = 0; i < SBQ_WAIT_QUEUES; i++) 359 for (i = 0; i < SBQ_WAIT_QUEUES; i++)
343 atomic_set(&sbq->ws[i].wait_cnt, 1); 360 atomic_set(&sbq->ws[i].wait_cnt, 1);
344 } 361 }
362}
363
364void sbitmap_queue_resize(struct sbitmap_queue *sbq, unsigned int depth)
365{
366 sbitmap_queue_update_wake_batch(sbq, depth);
345 sbitmap_resize(&sbq->sb, depth); 367 sbitmap_resize(&sbq->sb, depth);
346} 368}
347EXPORT_SYMBOL_GPL(sbitmap_queue_resize); 369EXPORT_SYMBOL_GPL(sbitmap_queue_resize);
@@ -403,6 +425,14 @@ int __sbitmap_queue_get_shallow(struct sbitmap_queue *sbq,
403} 425}
404EXPORT_SYMBOL_GPL(__sbitmap_queue_get_shallow); 426EXPORT_SYMBOL_GPL(__sbitmap_queue_get_shallow);
405 427
428void sbitmap_queue_min_shallow_depth(struct sbitmap_queue *sbq,
429 unsigned int min_shallow_depth)
430{
431 sbq->min_shallow_depth = min_shallow_depth;
432 sbitmap_queue_update_wake_batch(sbq, sbq->sb.depth);
433}
434EXPORT_SYMBOL_GPL(sbitmap_queue_min_shallow_depth);
435
406static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) 436static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq)
407{ 437{
408 int i, wake_index; 438 int i, wake_index;
@@ -528,5 +558,6 @@ void sbitmap_queue_show(struct sbitmap_queue *sbq, struct seq_file *m)
528 seq_puts(m, "}\n"); 558 seq_puts(m, "}\n");
529 559
530 seq_printf(m, "round_robin=%d\n", sbq->round_robin); 560 seq_printf(m, "round_robin=%d\n", sbq->round_robin);
561 seq_printf(m, "min_shallow_depth=%u\n", sbq->min_shallow_depth);
531} 562}
532EXPORT_SYMBOL_GPL(sbitmap_queue_show); 563EXPORT_SYMBOL_GPL(sbitmap_queue_show);