aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sbitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sbitmap.c')
-rw-r--r--lib/sbitmap.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/lib/sbitmap.c b/lib/sbitmap.c
index 60e800e0b5a0..80aa8d5463fa 100644
--- a/lib/sbitmap.c
+++ b/lib/sbitmap.c
@@ -79,15 +79,15 @@ void sbitmap_resize(struct sbitmap *sb, unsigned int depth)
79} 79}
80EXPORT_SYMBOL_GPL(sbitmap_resize); 80EXPORT_SYMBOL_GPL(sbitmap_resize);
81 81
82static int __sbitmap_get_word(struct sbitmap_word *word, unsigned int hint, 82static int __sbitmap_get_word(unsigned long *word, unsigned long depth,
83 bool wrap) 83 unsigned int hint, bool wrap)
84{ 84{
85 unsigned int orig_hint = hint; 85 unsigned int orig_hint = hint;
86 int nr; 86 int nr;
87 87
88 while (1) { 88 while (1) {
89 nr = find_next_zero_bit(&word->word, word->depth, hint); 89 nr = find_next_zero_bit(word, depth, hint);
90 if (unlikely(nr >= word->depth)) { 90 if (unlikely(nr >= depth)) {
91 /* 91 /*
92 * We started with an offset, and we didn't reset the 92 * We started with an offset, and we didn't reset the
93 * offset to 0 in a failure case, so start from 0 to 93 * offset to 0 in a failure case, so start from 0 to
@@ -100,11 +100,11 @@ static int __sbitmap_get_word(struct sbitmap_word *word, unsigned int hint,
100 return -1; 100 return -1;
101 } 101 }
102 102
103 if (!test_and_set_bit(nr, &word->word)) 103 if (!test_and_set_bit(nr, word))
104 break; 104 break;
105 105
106 hint = nr + 1; 106 hint = nr + 1;
107 if (hint >= word->depth - 1) 107 if (hint >= depth - 1)
108 hint = 0; 108 hint = 0;
109 } 109 }
110 110
@@ -119,7 +119,8 @@ int sbitmap_get(struct sbitmap *sb, unsigned int alloc_hint, bool round_robin)
119 index = SB_NR_TO_INDEX(sb, alloc_hint); 119 index = SB_NR_TO_INDEX(sb, alloc_hint);
120 120
121 for (i = 0; i < sb->map_nr; i++) { 121 for (i = 0; i < sb->map_nr; i++) {
122 nr = __sbitmap_get_word(&sb->map[index], 122 nr = __sbitmap_get_word(&sb->map[index].word,
123 sb->map[index].depth,
123 SB_NR_TO_BIT(sb, alloc_hint), 124 SB_NR_TO_BIT(sb, alloc_hint),
124 !round_robin); 125 !round_robin);
125 if (nr != -1) { 126 if (nr != -1) {
@@ -141,6 +142,37 @@ int sbitmap_get(struct sbitmap *sb, unsigned int alloc_hint, bool round_robin)
141} 142}
142EXPORT_SYMBOL_GPL(sbitmap_get); 143EXPORT_SYMBOL_GPL(sbitmap_get);
143 144
145int sbitmap_get_shallow(struct sbitmap *sb, unsigned int alloc_hint,
146 unsigned long shallow_depth)
147{
148 unsigned int i, index;
149 int nr = -1;
150
151 index = SB_NR_TO_INDEX(sb, alloc_hint);
152
153 for (i = 0; i < sb->map_nr; i++) {
154 nr = __sbitmap_get_word(&sb->map[index].word,
155 min(sb->map[index].depth, shallow_depth),
156 SB_NR_TO_BIT(sb, alloc_hint), true);
157 if (nr != -1) {
158 nr += index << sb->shift;
159 break;
160 }
161
162 /* Jump to next index. */
163 index++;
164 alloc_hint = index << sb->shift;
165
166 if (index >= sb->map_nr) {
167 index = 0;
168 alloc_hint = 0;
169 }
170 }
171
172 return nr;
173}
174EXPORT_SYMBOL_GPL(sbitmap_get_shallow);
175
144bool sbitmap_any_bit_set(const struct sbitmap *sb) 176bool sbitmap_any_bit_set(const struct sbitmap *sb)
145{ 177{
146 unsigned int i; 178 unsigned int i;
@@ -342,6 +374,35 @@ int __sbitmap_queue_get(struct sbitmap_queue *sbq)
342} 374}
343EXPORT_SYMBOL_GPL(__sbitmap_queue_get); 375EXPORT_SYMBOL_GPL(__sbitmap_queue_get);
344 376
377int __sbitmap_queue_get_shallow(struct sbitmap_queue *sbq,
378 unsigned int shallow_depth)
379{
380 unsigned int hint, depth;
381 int nr;
382
383 hint = this_cpu_read(*sbq->alloc_hint);
384 depth = READ_ONCE(sbq->sb.depth);
385 if (unlikely(hint >= depth)) {
386 hint = depth ? prandom_u32() % depth : 0;
387 this_cpu_write(*sbq->alloc_hint, hint);
388 }
389 nr = sbitmap_get_shallow(&sbq->sb, hint, shallow_depth);
390
391 if (nr == -1) {
392 /* If the map is full, a hint won't do us much good. */
393 this_cpu_write(*sbq->alloc_hint, 0);
394 } else if (nr == hint || unlikely(sbq->round_robin)) {
395 /* Only update the hint if we used it. */
396 hint = nr + 1;
397 if (hint >= depth - 1)
398 hint = 0;
399 this_cpu_write(*sbq->alloc_hint, hint);
400 }
401
402 return nr;
403}
404EXPORT_SYMBOL_GPL(__sbitmap_queue_get_shallow);
405
345static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) 406static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq)
346{ 407{
347 int i, wake_index; 408 int i, wake_index;