Blame view

block/blk-mq-tag.c 13.7 KB
75bb4625b   Jens Axboe   blk-mq: add file ...
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * Fast and scalable bitmap tagging variant. Uses sparser bitmaps spread
   * over multiple cachelines to avoid ping-pong between multiple submitters
   * or submitter and completer. Uses rolling wakeups to avoid falling of
   * the scaling cliff when we run out of tags and have to start putting
   * submitters to sleep.
   *
   * Uses active queue tracking to support fairer distribution of tags
   * between multiple submitters when a shared tag map is used.
   *
   * Copyright (C) 2013-2014 Jens Axboe
   */
320ae51fe   Jens Axboe   blk-mq: new multi...
13
14
  #include <linux/kernel.h>
  #include <linux/module.h>
4bb659b15   Jens Axboe   blk-mq: implement...
15
  #include <linux/random.h>
320ae51fe   Jens Axboe   blk-mq: new multi...
16
17
18
19
20
  
  #include <linux/blk-mq.h>
  #include "blk.h"
  #include "blk-mq.h"
  #include "blk-mq-tag.h"
4bb659b15   Jens Axboe   blk-mq: implement...
21
22
23
24
25
  static bool bt_has_free_tags(struct blk_mq_bitmap_tags *bt)
  {
  	int i;
  
  	for (i = 0; i < bt->map_nr; i++) {
e93ecf602   Jens Axboe   blk-mq: move the ...
26
  		struct blk_align_bitmap *bm = &bt->map[i];
4bb659b15   Jens Axboe   blk-mq: implement...
27
28
29
30
31
32
33
34
  		int ret;
  
  		ret = find_first_zero_bit(&bm->word, bm->depth);
  		if (ret < bm->depth)
  			return true;
  	}
  
  	return false;
320ae51fe   Jens Axboe   blk-mq: new multi...
35
36
37
38
  }
  
  bool blk_mq_has_free_tags(struct blk_mq_tags *tags)
  {
4bb659b15   Jens Axboe   blk-mq: implement...
39
40
41
42
43
  	if (!tags)
  		return true;
  
  	return bt_has_free_tags(&tags->bitmap_tags);
  }
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
44
  static inline int bt_index_inc(int index)
0d2602ca3   Jens Axboe   blk-mq: improve s...
45
  {
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
46
47
48
49
50
51
52
53
  	return (index + 1) & (BT_WAIT_QUEUES - 1);
  }
  
  static inline void bt_index_atomic_inc(atomic_t *index)
  {
  	int old = atomic_read(index);
  	int new = bt_index_inc(old);
  	atomic_cmpxchg(index, old, new);
0d2602ca3   Jens Axboe   blk-mq: improve s...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  }
  
  /*
   * If a previously inactive queue goes active, bump the active user count.
   */
  bool __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
  {
  	if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) &&
  	    !test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
  		atomic_inc(&hctx->tags->active_queues);
  
  	return true;
  }
  
  /*
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
69
   * Wakeup all potentially sleeping on normal (non-reserved) tags
0d2602ca3   Jens Axboe   blk-mq: improve s...
70
   */
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
71
  static void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags)
0d2602ca3   Jens Axboe   blk-mq: improve s...
72
  {
0d2602ca3   Jens Axboe   blk-mq: improve s...
73
74
  	struct blk_mq_bitmap_tags *bt;
  	int i, wake_index;
0d2602ca3   Jens Axboe   blk-mq: improve s...
75
  	bt = &tags->bitmap_tags;
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
76
  	wake_index = atomic_read(&bt->wake_index);
0d2602ca3   Jens Axboe   blk-mq: improve s...
77
78
79
80
81
  	for (i = 0; i < BT_WAIT_QUEUES; i++) {
  		struct bt_wait_state *bs = &bt->bs[wake_index];
  
  		if (waitqueue_active(&bs->wait))
  			wake_up(&bs->wait);
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
82
  		wake_index = bt_index_inc(wake_index);
0d2602ca3   Jens Axboe   blk-mq: improve s...
83
84
85
86
  	}
  }
  
  /*
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
   * If a previously busy queue goes inactive, potential waiters could now
   * be allowed to queue. Wake them up and check.
   */
  void __blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx)
  {
  	struct blk_mq_tags *tags = hctx->tags;
  
  	if (!test_and_clear_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
  		return;
  
  	atomic_dec(&tags->active_queues);
  
  	blk_mq_tag_wakeup_all(tags);
  }
  
  /*
0d2602ca3   Jens Axboe   blk-mq: improve s...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
   * For shared tag users, we track the number of currently active users
   * and attempt to provide a fair share of the tag depth for each of them.
   */
  static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
  				  struct blk_mq_bitmap_tags *bt)
  {
  	unsigned int depth, users;
  
  	if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_SHARED))
  		return true;
  	if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
  		return true;
  
  	/*
  	 * Don't try dividing an ant
  	 */
  	if (bt->depth == 1)
  		return true;
  
  	users = atomic_read(&hctx->tags->active_queues);
  	if (!users)
  		return true;
  
  	/*
  	 * Allow at least some tags
  	 */
  	depth = max((bt->depth + users - 1) / users, 4U);
  	return atomic_read(&hctx->nr_active) < depth;
  }
e93ecf602   Jens Axboe   blk-mq: move the ...
132
  static int __bt_get_word(struct blk_align_bitmap *bm, unsigned int last_tag)
4bb659b15   Jens Axboe   blk-mq: implement...
133
134
  {
  	int tag, org_last_tag, end;
59d13bf5f   Jens Axboe   blk-mq: use spars...
135
  	org_last_tag = last_tag;
4bb659b15   Jens Axboe   blk-mq: implement...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  	end = bm->depth;
  	do {
  restart:
  		tag = find_next_zero_bit(&bm->word, end, last_tag);
  		if (unlikely(tag >= end)) {
  			/*
  			 * We started with an offset, start from 0 to
  			 * exhaust the map.
  			 */
  			if (org_last_tag && last_tag) {
  				end = last_tag;
  				last_tag = 0;
  				goto restart;
  			}
  			return -1;
  		}
  		last_tag = tag + 1;
  	} while (test_and_set_bit_lock(tag, &bm->word));
  
  	return tag;
  }
  
  /*
   * Straight forward bitmap tag implementation, where each bit is a tag
   * (cleared == free, and set == busy). The small twist is using per-cpu
   * last_tag caches, which blk-mq stores in the blk_mq_ctx software queue
   * contexts. This enables us to drastically limit the space searched,
   * without dirtying an extra shared cacheline like we would if we stored
   * the cache value inside the shared blk_mq_bitmap_tags structure. On top
   * of that, each word of tags is in a separate cacheline. This means that
   * multiple users will tend to stick to different cachelines, at least
   * until the map is exhausted.
   */
0d2602ca3   Jens Axboe   blk-mq: improve s...
169
170
  static int __bt_get(struct blk_mq_hw_ctx *hctx, struct blk_mq_bitmap_tags *bt,
  		    unsigned int *tag_cache)
4bb659b15   Jens Axboe   blk-mq: implement...
171
172
173
  {
  	unsigned int last_tag, org_last_tag;
  	int index, i, tag;
0d2602ca3   Jens Axboe   blk-mq: improve s...
174
175
  	if (!hctx_may_queue(hctx, bt))
  		return -1;
4bb659b15   Jens Axboe   blk-mq: implement...
176
  	last_tag = org_last_tag = *tag_cache;
59d13bf5f   Jens Axboe   blk-mq: use spars...
177
  	index = TAG_TO_INDEX(bt, last_tag);
4bb659b15   Jens Axboe   blk-mq: implement...
178
179
  
  	for (i = 0; i < bt->map_nr; i++) {
59d13bf5f   Jens Axboe   blk-mq: use spars...
180
  		tag = __bt_get_word(&bt->map[index], TAG_TO_BIT(bt, last_tag));
4bb659b15   Jens Axboe   blk-mq: implement...
181
  		if (tag != -1) {
59d13bf5f   Jens Axboe   blk-mq: use spars...
182
  			tag += (index << bt->bits_per_word);
4bb659b15   Jens Axboe   blk-mq: implement...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  			goto done;
  		}
  
  		last_tag = 0;
  		if (++index >= bt->map_nr)
  			index = 0;
  	}
  
  	*tag_cache = 0;
  	return -1;
  
  	/*
  	 * Only update the cache from the allocation path, if we ended
  	 * up using the specific cached tag.
  	 */
  done:
  	if (tag == org_last_tag) {
  		last_tag = tag + 1;
  		if (last_tag >= bt->depth - 1)
  			last_tag = 0;
  
  		*tag_cache = last_tag;
  	}
  
  	return tag;
  }
4bb659b15   Jens Axboe   blk-mq: implement...
209
210
211
212
  static struct bt_wait_state *bt_wait_ptr(struct blk_mq_bitmap_tags *bt,
  					 struct blk_mq_hw_ctx *hctx)
  {
  	struct bt_wait_state *bs;
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
213
  	int wait_index;
4bb659b15   Jens Axboe   blk-mq: implement...
214
215
216
  
  	if (!hctx)
  		return &bt->bs[0];
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
217
218
219
  	wait_index = atomic_read(&hctx->wait_index);
  	bs = &bt->bs[wait_index];
  	bt_index_atomic_inc(&hctx->wait_index);
4bb659b15   Jens Axboe   blk-mq: implement...
220
  	return bs;
320ae51fe   Jens Axboe   blk-mq: new multi...
221
  }
cb96a42cc   Ming Lei   blk-mq: fix sched...
222
223
224
225
  static int bt_get(struct blk_mq_alloc_data *data,
  		struct blk_mq_bitmap_tags *bt,
  		struct blk_mq_hw_ctx *hctx,
  		unsigned int *last_tag)
320ae51fe   Jens Axboe   blk-mq: new multi...
226
  {
4bb659b15   Jens Axboe   blk-mq: implement...
227
228
  	struct bt_wait_state *bs;
  	DEFINE_WAIT(wait);
320ae51fe   Jens Axboe   blk-mq: new multi...
229
  	int tag;
0d2602ca3   Jens Axboe   blk-mq: improve s...
230
  	tag = __bt_get(hctx, bt, last_tag);
4bb659b15   Jens Axboe   blk-mq: implement...
231
232
  	if (tag != -1)
  		return tag;
cb96a42cc   Ming Lei   blk-mq: fix sched...
233
  	if (!(data->gfp & __GFP_WAIT))
4bb659b15   Jens Axboe   blk-mq: implement...
234
235
236
237
  		return -1;
  
  	bs = bt_wait_ptr(bt, hctx);
  	do {
4bb659b15   Jens Axboe   blk-mq: implement...
238
  		prepare_to_wait(&bs->wait, &wait, TASK_UNINTERRUPTIBLE);
0d2602ca3   Jens Axboe   blk-mq: improve s...
239
  		tag = __bt_get(hctx, bt, last_tag);
4bb659b15   Jens Axboe   blk-mq: implement...
240
241
  		if (tag != -1)
  			break;
cb96a42cc   Ming Lei   blk-mq: fix sched...
242
  		blk_mq_put_ctx(data->ctx);
4bb659b15   Jens Axboe   blk-mq: implement...
243
  		io_schedule();
cb96a42cc   Ming Lei   blk-mq: fix sched...
244
245
246
247
248
249
250
251
252
253
254
255
256
  
  		data->ctx = blk_mq_get_ctx(data->q);
  		data->hctx = data->q->mq_ops->map_queue(data->q,
  				data->ctx->cpu);
  		if (data->reserved) {
  			bt = &data->hctx->tags->breserved_tags;
  		} else {
  			last_tag = &data->ctx->last_tag;
  			hctx = data->hctx;
  			bt = &hctx->tags->bitmap_tags;
  		}
  		finish_wait(&bs->wait, &wait);
  		bs = bt_wait_ptr(bt, hctx);
4bb659b15   Jens Axboe   blk-mq: implement...
257
258
259
260
261
  	} while (1);
  
  	finish_wait(&bs->wait, &wait);
  	return tag;
  }
cb96a42cc   Ming Lei   blk-mq: fix sched...
262
  static unsigned int __blk_mq_get_tag(struct blk_mq_alloc_data *data)
4bb659b15   Jens Axboe   blk-mq: implement...
263
264
  {
  	int tag;
cb96a42cc   Ming Lei   blk-mq: fix sched...
265
266
  	tag = bt_get(data, &data->hctx->tags->bitmap_tags, data->hctx,
  			&data->ctx->last_tag);
4bb659b15   Jens Axboe   blk-mq: implement...
267
  	if (tag >= 0)
cb96a42cc   Ming Lei   blk-mq: fix sched...
268
  		return tag + data->hctx->tags->nr_reserved_tags;
4bb659b15   Jens Axboe   blk-mq: implement...
269
270
  
  	return BLK_MQ_TAG_FAIL;
320ae51fe   Jens Axboe   blk-mq: new multi...
271
  }
cb96a42cc   Ming Lei   blk-mq: fix sched...
272
  static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_alloc_data *data)
320ae51fe   Jens Axboe   blk-mq: new multi...
273
  {
4bb659b15   Jens Axboe   blk-mq: implement...
274
  	int tag, zero = 0;
320ae51fe   Jens Axboe   blk-mq: new multi...
275

cb96a42cc   Ming Lei   blk-mq: fix sched...
276
  	if (unlikely(!data->hctx->tags->nr_reserved_tags)) {
320ae51fe   Jens Axboe   blk-mq: new multi...
277
278
279
  		WARN_ON_ONCE(1);
  		return BLK_MQ_TAG_FAIL;
  	}
cb96a42cc   Ming Lei   blk-mq: fix sched...
280
  	tag = bt_get(data, &data->hctx->tags->breserved_tags, NULL, &zero);
320ae51fe   Jens Axboe   blk-mq: new multi...
281
282
  	if (tag < 0)
  		return BLK_MQ_TAG_FAIL;
4bb659b15   Jens Axboe   blk-mq: implement...
283

320ae51fe   Jens Axboe   blk-mq: new multi...
284
285
  	return tag;
  }
cb96a42cc   Ming Lei   blk-mq: fix sched...
286
  unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data)
320ae51fe   Jens Axboe   blk-mq: new multi...
287
  {
cb96a42cc   Ming Lei   blk-mq: fix sched...
288
289
  	if (!data->reserved)
  		return __blk_mq_get_tag(data);
320ae51fe   Jens Axboe   blk-mq: new multi...
290

cb96a42cc   Ming Lei   blk-mq: fix sched...
291
  	return __blk_mq_get_reserved_tag(data);
320ae51fe   Jens Axboe   blk-mq: new multi...
292
  }
4bb659b15   Jens Axboe   blk-mq: implement...
293
294
295
  static struct bt_wait_state *bt_wake_ptr(struct blk_mq_bitmap_tags *bt)
  {
  	int i, wake_index;
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
296
  	wake_index = atomic_read(&bt->wake_index);
4bb659b15   Jens Axboe   blk-mq: implement...
297
298
299
300
  	for (i = 0; i < BT_WAIT_QUEUES; i++) {
  		struct bt_wait_state *bs = &bt->bs[wake_index];
  
  		if (waitqueue_active(&bs->wait)) {
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
301
302
303
  			int o = atomic_read(&bt->wake_index);
  			if (wake_index != o)
  				atomic_cmpxchg(&bt->wake_index, o, wake_index);
4bb659b15   Jens Axboe   blk-mq: implement...
304
305
306
  
  			return bs;
  		}
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
307
  		wake_index = bt_index_inc(wake_index);
4bb659b15   Jens Axboe   blk-mq: implement...
308
309
310
311
312
313
314
  	}
  
  	return NULL;
  }
  
  static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag)
  {
59d13bf5f   Jens Axboe   blk-mq: use spars...
315
  	const int index = TAG_TO_INDEX(bt, tag);
4bb659b15   Jens Axboe   blk-mq: implement...
316
  	struct bt_wait_state *bs;
2971c35f3   Alexander Gordeev   blk-mq: bitmap ta...
317
  	int wait_cnt;
4bb659b15   Jens Axboe   blk-mq: implement...
318

0289b2e11   Ming Lei   blk-mq: bitmap ta...
319
320
321
322
323
  	/*
  	 * The unlock memory barrier need to order access to req in free
  	 * path and clearing tag bit
  	 */
  	clear_bit_unlock(TAG_TO_BIT(bt, tag), &bt->map[index].word);
4bb659b15   Jens Axboe   blk-mq: implement...
324
325
  
  	bs = bt_wake_ptr(bt);
2971c35f3   Alexander Gordeev   blk-mq: bitmap ta...
326
327
328
329
330
331
332
  	if (!bs)
  		return;
  
  	wait_cnt = atomic_dec_return(&bs->wait_cnt);
  	if (wait_cnt == 0) {
  wake:
  		atomic_add(bt->wake_cnt, &bs->wait_cnt);
8537b1203   Alexander Gordeev   blk-mq: bitmap ta...
333
  		bt_index_atomic_inc(&bt->wake_index);
4bb659b15   Jens Axboe   blk-mq: implement...
334
  		wake_up(&bs->wait);
2971c35f3   Alexander Gordeev   blk-mq: bitmap ta...
335
336
337
338
  	} else if (wait_cnt < 0) {
  		wait_cnt = atomic_inc_return(&bs->wait_cnt);
  		if (!wait_cnt)
  			goto wake;
4bb659b15   Jens Axboe   blk-mq: implement...
339
340
  	}
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
341
342
343
  static void __blk_mq_put_tag(struct blk_mq_tags *tags, unsigned int tag)
  {
  	BUG_ON(tag >= tags->nr_tags);
4bb659b15   Jens Axboe   blk-mq: implement...
344
  	bt_clear_tag(&tags->bitmap_tags, tag);
320ae51fe   Jens Axboe   blk-mq: new multi...
345
346
347
348
349
350
  }
  
  static void __blk_mq_put_reserved_tag(struct blk_mq_tags *tags,
  				      unsigned int tag)
  {
  	BUG_ON(tag >= tags->nr_reserved_tags);
4bb659b15   Jens Axboe   blk-mq: implement...
351
  	bt_clear_tag(&tags->breserved_tags, tag);
320ae51fe   Jens Axboe   blk-mq: new multi...
352
  }
0d2602ca3   Jens Axboe   blk-mq: improve s...
353
  void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, unsigned int tag,
4bb659b15   Jens Axboe   blk-mq: implement...
354
  		    unsigned int *last_tag)
320ae51fe   Jens Axboe   blk-mq: new multi...
355
  {
0d2602ca3   Jens Axboe   blk-mq: improve s...
356
  	struct blk_mq_tags *tags = hctx->tags;
4bb659b15   Jens Axboe   blk-mq: implement...
357
358
359
360
361
362
  	if (tag >= tags->nr_reserved_tags) {
  		const int real_tag = tag - tags->nr_reserved_tags;
  
  		__blk_mq_put_tag(tags, real_tag);
  		*last_tag = real_tag;
  	} else
320ae51fe   Jens Axboe   blk-mq: new multi...
363
364
  		__blk_mq_put_reserved_tag(tags, tag);
  }
4bb659b15   Jens Axboe   blk-mq: implement...
365
366
  static void bt_for_each_free(struct blk_mq_bitmap_tags *bt,
  			     unsigned long *free_map, unsigned int off)
320ae51fe   Jens Axboe   blk-mq: new multi...
367
  {
4bb659b15   Jens Axboe   blk-mq: implement...
368
369
370
  	int i;
  
  	for (i = 0; i < bt->map_nr; i++) {
e93ecf602   Jens Axboe   blk-mq: move the ...
371
  		struct blk_align_bitmap *bm = &bt->map[i];
4bb659b15   Jens Axboe   blk-mq: implement...
372
373
374
375
376
377
378
379
380
381
  		int bit = 0;
  
  		do {
  			bit = find_next_zero_bit(&bm->word, bm->depth, bit);
  			if (bit >= bm->depth)
  				break;
  
  			__set_bit(bit + off, free_map);
  			bit++;
  		} while (1);
59d13bf5f   Jens Axboe   blk-mq: use spars...
382
  		off += (1 << bt->bits_per_word);
4bb659b15   Jens Axboe   blk-mq: implement...
383
  	}
320ae51fe   Jens Axboe   blk-mq: new multi...
384
385
386
387
388
389
390
391
392
393
394
395
  }
  
  void blk_mq_tag_busy_iter(struct blk_mq_tags *tags,
  			  void (*fn)(void *, unsigned long *), void *data)
  {
  	unsigned long *tag_map;
  	size_t map_size;
  
  	map_size = ALIGN(tags->nr_tags, BITS_PER_LONG) / BITS_PER_LONG;
  	tag_map = kzalloc(map_size * sizeof(unsigned long), GFP_ATOMIC);
  	if (!tag_map)
  		return;
4bb659b15   Jens Axboe   blk-mq: implement...
396
  	bt_for_each_free(&tags->bitmap_tags, tag_map, tags->nr_reserved_tags);
320ae51fe   Jens Axboe   blk-mq: new multi...
397
  	if (tags->nr_reserved_tags)
4bb659b15   Jens Axboe   blk-mq: implement...
398
  		bt_for_each_free(&tags->breserved_tags, tag_map, 0);
320ae51fe   Jens Axboe   blk-mq: new multi...
399
400
401
402
  
  	fn(data, tag_map);
  	kfree(tag_map);
  }
edf866b38   Sam Bradshaw   blk-mq: export bl...
403
  EXPORT_SYMBOL(blk_mq_tag_busy_iter);
320ae51fe   Jens Axboe   blk-mq: new multi...
404

4bb659b15   Jens Axboe   blk-mq: implement...
405
406
407
408
409
  static unsigned int bt_unused_tags(struct blk_mq_bitmap_tags *bt)
  {
  	unsigned int i, used;
  
  	for (i = 0, used = 0; i < bt->map_nr; i++) {
e93ecf602   Jens Axboe   blk-mq: move the ...
410
  		struct blk_align_bitmap *bm = &bt->map[i];
4bb659b15   Jens Axboe   blk-mq: implement...
411
412
413
414
415
416
  
  		used += bitmap_weight(&bm->word, bm->depth);
  	}
  
  	return bt->depth - used;
  }
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  static void bt_update_count(struct blk_mq_bitmap_tags *bt,
  			    unsigned int depth)
  {
  	unsigned int tags_per_word = 1U << bt->bits_per_word;
  	unsigned int map_depth = depth;
  
  	if (depth) {
  		int i;
  
  		for (i = 0; i < bt->map_nr; i++) {
  			bt->map[i].depth = min(map_depth, tags_per_word);
  			map_depth -= bt->map[i].depth;
  		}
  	}
  
  	bt->wake_cnt = BT_WAIT_BATCH;
  	if (bt->wake_cnt > depth / 4)
  		bt->wake_cnt = max(1U, depth / 4);
  
  	bt->depth = depth;
  }
4bb659b15   Jens Axboe   blk-mq: implement...
438
439
440
441
  static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth,
  			int node, bool reserved)
  {
  	int i;
59d13bf5f   Jens Axboe   blk-mq: use spars...
442
  	bt->bits_per_word = ilog2(BITS_PER_LONG);
4bb659b15   Jens Axboe   blk-mq: implement...
443
444
445
446
447
  	/*
  	 * Depth can be zero for reserved tags, that's not a failure
  	 * condition.
  	 */
  	if (depth) {
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
448
  		unsigned int nr, tags_per_word;
59d13bf5f   Jens Axboe   blk-mq: use spars...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  
  		tags_per_word = (1 << bt->bits_per_word);
  
  		/*
  		 * If the tag space is small, shrink the number of tags
  		 * per word so we spread over a few cachelines, at least.
  		 * If less than 4 tags, just forget about it, it's not
  		 * going to work optimally anyway.
  		 */
  		if (depth >= 4) {
  			while (tags_per_word * 4 > depth) {
  				bt->bits_per_word--;
  				tags_per_word = (1 << bt->bits_per_word);
  			}
  		}
4bb659b15   Jens Axboe   blk-mq: implement...
464

59d13bf5f   Jens Axboe   blk-mq: use spars...
465
  		nr = ALIGN(depth, tags_per_word) / tags_per_word;
e93ecf602   Jens Axboe   blk-mq: move the ...
466
  		bt->map = kzalloc_node(nr * sizeof(struct blk_align_bitmap),
4bb659b15   Jens Axboe   blk-mq: implement...
467
468
469
470
471
  						GFP_KERNEL, node);
  		if (!bt->map)
  			return -ENOMEM;
  
  		bt->map_nr = nr;
4bb659b15   Jens Axboe   blk-mq: implement...
472
473
474
475
476
477
478
  	}
  
  	bt->bs = kzalloc(BT_WAIT_QUEUES * sizeof(*bt->bs), GFP_KERNEL);
  	if (!bt->bs) {
  		kfree(bt->map);
  		return -ENOMEM;
  	}
86fb5c56c   Alexander Gordeev   blk-mq: bitmap ta...
479
480
481
  	bt_update_count(bt, depth);
  
  	for (i = 0; i < BT_WAIT_QUEUES; i++) {
4bb659b15   Jens Axboe   blk-mq: implement...
482
  		init_waitqueue_head(&bt->bs[i].wait);
86fb5c56c   Alexander Gordeev   blk-mq: bitmap ta...
483
484
  		atomic_set(&bt->bs[i].wait_cnt, bt->wake_cnt);
  	}
4bb659b15   Jens Axboe   blk-mq: implement...
485

4bb659b15   Jens Axboe   blk-mq: implement...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  	return 0;
  }
  
  static void bt_free(struct blk_mq_bitmap_tags *bt)
  {
  	kfree(bt->map);
  	kfree(bt->bs);
  }
  
  static struct blk_mq_tags *blk_mq_init_bitmap_tags(struct blk_mq_tags *tags,
  						   int node)
  {
  	unsigned int depth = tags->nr_tags - tags->nr_reserved_tags;
  
  	if (bt_alloc(&tags->bitmap_tags, depth, node, false))
  		goto enomem;
  	if (bt_alloc(&tags->breserved_tags, tags->nr_reserved_tags, node, true))
  		goto enomem;
  
  	return tags;
  enomem:
  	bt_free(&tags->bitmap_tags);
  	kfree(tags);
  	return NULL;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
511
512
513
  struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
  				     unsigned int reserved_tags, int node)
  {
320ae51fe   Jens Axboe   blk-mq: new multi...
514
  	struct blk_mq_tags *tags;
320ae51fe   Jens Axboe   blk-mq: new multi...
515
516
517
518
519
520
521
522
523
524
  
  	if (total_tags > BLK_MQ_TAG_MAX) {
  		pr_err("blk-mq: tag depth too large
  ");
  		return NULL;
  	}
  
  	tags = kzalloc_node(sizeof(*tags), GFP_KERNEL, node);
  	if (!tags)
  		return NULL;
320ae51fe   Jens Axboe   blk-mq: new multi...
525
526
  	tags->nr_tags = total_tags;
  	tags->nr_reserved_tags = reserved_tags;
320ae51fe   Jens Axboe   blk-mq: new multi...
527

4bb659b15   Jens Axboe   blk-mq: implement...
528
  	return blk_mq_init_bitmap_tags(tags, node);
320ae51fe   Jens Axboe   blk-mq: new multi...
529
530
531
532
  }
  
  void blk_mq_free_tags(struct blk_mq_tags *tags)
  {
4bb659b15   Jens Axboe   blk-mq: implement...
533
534
  	bt_free(&tags->bitmap_tags);
  	bt_free(&tags->breserved_tags);
320ae51fe   Jens Axboe   blk-mq: new multi...
535
536
  	kfree(tags);
  }
4bb659b15   Jens Axboe   blk-mq: implement...
537
538
539
  void blk_mq_tag_init_last_tag(struct blk_mq_tags *tags, unsigned int *tag)
  {
  	unsigned int depth = tags->nr_tags - tags->nr_reserved_tags;
9d3d21aeb   Ming Lei   blk-mq: bitmap ta...
540
  	*tag = prandom_u32() % depth;
4bb659b15   Jens Axboe   blk-mq: implement...
541
  }
e3a2b3f93   Jens Axboe   blk-mq: allow cha...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  int blk_mq_tag_update_depth(struct blk_mq_tags *tags, unsigned int tdepth)
  {
  	tdepth -= tags->nr_reserved_tags;
  	if (tdepth > tags->nr_tags)
  		return -EINVAL;
  
  	/*
  	 * Don't need (or can't) update reserved tags here, they remain
  	 * static and should never need resizing.
  	 */
  	bt_update_count(&tags->bitmap_tags, tdepth);
  	blk_mq_tag_wakeup_all(tags);
  	return 0;
  }
320ae51fe   Jens Axboe   blk-mq: new multi...
556
557
558
  ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
  {
  	char *orig_page = page;
4bb659b15   Jens Axboe   blk-mq: implement...
559
  	unsigned int free, res;
320ae51fe   Jens Axboe   blk-mq: new multi...
560
561
562
  
  	if (!tags)
  		return 0;
59d13bf5f   Jens Axboe   blk-mq: use spars...
563
564
565
566
567
  	page += sprintf(page, "nr_tags=%u, reserved_tags=%u, "
  			"bits_per_word=%u
  ",
  			tags->nr_tags, tags->nr_reserved_tags,
  			tags->bitmap_tags.bits_per_word);
320ae51fe   Jens Axboe   blk-mq: new multi...
568

4bb659b15   Jens Axboe   blk-mq: implement...
569
570
  	free = bt_unused_tags(&tags->bitmap_tags);
  	res = bt_unused_tags(&tags->breserved_tags);
320ae51fe   Jens Axboe   blk-mq: new multi...
571

4bb659b15   Jens Axboe   blk-mq: implement...
572
573
  	page += sprintf(page, "nr_free=%u, nr_reserved=%u
  ", free, res);
0d2602ca3   Jens Axboe   blk-mq: improve s...
574
575
  	page += sprintf(page, "active_queues=%u
  ", atomic_read(&tags->active_queues));
320ae51fe   Jens Axboe   blk-mq: new multi...
576
577
578
  
  	return page - orig_page;
  }