Skip to content

Commit ee1b6f7

Browse files
shligitaxboe
authored andcommitted
block: support different tag allocation policy
The libata tag allocation is using a round-robin policy. Next patch will make libata use block generic tag allocation, so let's add a policy to tag allocation. Currently two policies: FIFO (default) and round-robin. Cc: Jens Axboe <axboe@fb.com> Cc: Tejun Heo <tj@kernel.org> Cc: Christoph Hellwig <hch@infradead.org> Signed-off-by: Shaohua Li <shli@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent bb5c3cd commit ee1b6f7

File tree

6 files changed

+39
-13
lines changed

6 files changed

+39
-13
lines changed

block/blk-tag.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ init_tag_map(struct request_queue *q, struct blk_queue_tag *tags, int depth)
119119
}
120120

121121
static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
122-
int depth)
122+
int depth, int alloc_policy)
123123
{
124124
struct blk_queue_tag *tags;
125125

@@ -131,6 +131,8 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
131131
goto fail;
132132

133133
atomic_set(&tags->refcnt, 1);
134+
tags->alloc_policy = alloc_policy;
135+
tags->next_tag = 0;
134136
return tags;
135137
fail:
136138
kfree(tags);
@@ -140,10 +142,11 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q,
140142
/**
141143
* blk_init_tags - initialize the tag info for an external tag map
142144
* @depth: the maximum queue depth supported
145+
* @alloc_policy: tag allocation policy
143146
**/
144-
struct blk_queue_tag *blk_init_tags(int depth)
147+
struct blk_queue_tag *blk_init_tags(int depth, int alloc_policy)
145148
{
146-
return __blk_queue_init_tags(NULL, depth);
149+
return __blk_queue_init_tags(NULL, depth, alloc_policy);
147150
}
148151
EXPORT_SYMBOL(blk_init_tags);
149152

@@ -152,19 +155,20 @@ EXPORT_SYMBOL(blk_init_tags);
152155
* @q: the request queue for the device
153156
* @depth: the maximum queue depth supported
154157
* @tags: the tag to use
158+
* @alloc_policy: tag allocation policy
155159
*
156160
* Queue lock must be held here if the function is called to resize an
157161
* existing map.
158162
**/
159163
int blk_queue_init_tags(struct request_queue *q, int depth,
160-
struct blk_queue_tag *tags)
164+
struct blk_queue_tag *tags, int alloc_policy)
161165
{
162166
int rc;
163167

164168
BUG_ON(tags && q->queue_tags && tags != q->queue_tags);
165169

166170
if (!tags && !q->queue_tags) {
167-
tags = __blk_queue_init_tags(q, depth);
171+
tags = __blk_queue_init_tags(q, depth, alloc_policy);
168172

169173
if (!tags)
170174
return -ENOMEM;
@@ -344,16 +348,29 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
344348
}
345349

346350
do {
347-
tag = find_first_zero_bit(bqt->tag_map, max_depth);
348-
if (tag >= max_depth)
349-
return 1;
351+
if (bqt->alloc_policy == BLK_TAG_ALLOC_FIFO) {
352+
tag = find_first_zero_bit(bqt->tag_map, max_depth);
353+
if (tag >= max_depth)
354+
return 1;
355+
} else {
356+
int start = bqt->next_tag;
357+
int size = min_t(int, bqt->max_depth, max_depth + start);
358+
tag = find_next_zero_bit(bqt->tag_map, size, start);
359+
if (tag >= size && start + size > bqt->max_depth) {
360+
size = start + size - bqt->max_depth;
361+
tag = find_first_zero_bit(bqt->tag_map, size);
362+
}
363+
if (tag >= size)
364+
return 1;
365+
}
350366

351367
} while (test_and_set_bit_lock(tag, bqt->tag_map));
352368
/*
353369
* We need lock ordering semantics given by test_and_set_bit_lock.
354370
* See blk_queue_end_tag for details.
355371
*/
356372

373+
bqt->next_tag = (tag + 1) % bqt->max_depth;
357374
rq->cmd_flags |= REQ_QUEUED;
358375
rq->tag = tag;
359376
bqt->tag_index[tag] = rq;

drivers/block/osdblk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ static int osdblk_init_disk(struct osdblk_device *osdev)
423423
}
424424

425425
/* switch queue to TCQ mode; allocate tag map */
426-
rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL);
426+
rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL, BLK_TAG_ALLOC_FIFO);
427427
if (rc) {
428428
blk_cleanup_queue(q);
429429
put_disk(disk);

drivers/scsi/scsi_scan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
290290
if (!shost_use_blk_mq(sdev->host) &&
291291
(shost->bqt || shost->hostt->use_blk_tags)) {
292292
blk_queue_init_tags(sdev->request_queue,
293-
sdev->host->cmd_per_lun, shost->bqt);
293+
sdev->host->cmd_per_lun, shost->bqt,
294+
shost->hostt->tag_alloc_policy);
294295
}
295296
scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
296297

include/linux/blkdev.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,11 @@ struct blk_queue_tag {
272272
int max_depth; /* what we will send to device */
273273
int real_max_depth; /* what the array can hold */
274274
atomic_t refcnt; /* map can be shared */
275+
int alloc_policy; /* tag allocation policy */
276+
int next_tag; /* next tag */
275277
};
278+
#define BLK_TAG_ALLOC_FIFO 0 /* allocate starting from 0 */
279+
#define BLK_TAG_ALLOC_RR 1 /* allocate starting from last allocated tag */
276280

277281
#define BLK_SCSI_MAX_CMDS (256)
278282
#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
@@ -1139,11 +1143,11 @@ static inline bool blk_needs_flush_plug(struct task_struct *tsk)
11391143
extern int blk_queue_start_tag(struct request_queue *, struct request *);
11401144
extern struct request *blk_queue_find_tag(struct request_queue *, int);
11411145
extern void blk_queue_end_tag(struct request_queue *, struct request *);
1142-
extern int blk_queue_init_tags(struct request_queue *, int, struct blk_queue_tag *);
1146+
extern int blk_queue_init_tags(struct request_queue *, int, struct blk_queue_tag *, int);
11431147
extern void blk_queue_free_tags(struct request_queue *);
11441148
extern int blk_queue_resize_tags(struct request_queue *, int);
11451149
extern void blk_queue_invalidate_tags(struct request_queue *);
1146-
extern struct blk_queue_tag *blk_init_tags(int);
1150+
extern struct blk_queue_tag *blk_init_tags(int, int);
11471151
extern void blk_free_tags(struct blk_queue_tag *);
11481152

11491153
static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,

include/scsi/scsi_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ struct scsi_host_template {
402402
*/
403403
unsigned char present;
404404

405+
/* If use block layer to manage tags, this is tag allocation policy */
406+
int tag_alloc_policy;
407+
405408
/*
406409
* Let the block layer assigns tags to all commands.
407410
*/

include/scsi/scsi_tcq.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
6666
* devices on the shared host (for libata)
6767
*/
6868
if (!shost->bqt) {
69-
shost->bqt = blk_init_tags(depth);
69+
shost->bqt = blk_init_tags(depth,
70+
shost->hostt->tag_alloc_policy);
7071
if (!shost->bqt)
7172
return -ENOMEM;
7273
}

0 commit comments

Comments
 (0)