Skip to content

Commit 7c3fb70

Browse files
committed
block: rearrange a few request fields for better cache layout
Move completion related items (like the call single data) near the end of the struct, instead of mixing them in with the initial queueing related fields. Move queuelist below the bio structures. Then we have all queueing related bits in the first cache line. This yields a 1.5-2% increase in IOPS for a null_blk test, both for sync and for high thread count access. Sync test goes form 975K to 992K, 32-thread case from 20.8M to 21.2M IOPS. Reviewed-by: Bart Van Assche <[email protected]> Reviewed-by: Omar Sandoval <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent e14575b commit 7c3fb70

File tree

2 files changed

+24
-22
lines changed

2 files changed

+24
-22
lines changed

block/blk-mq.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,6 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
270270
struct blk_mq_tags *tags = blk_mq_tags_from_data(data);
271271
struct request *rq = tags->static_rqs[tag];
272272

273-
rq->rq_flags = 0;
274-
275273
if (data->flags & BLK_MQ_REQ_INTERNAL) {
276274
rq->tag = -1;
277275
rq->internal_tag = tag;
@@ -285,26 +283,22 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
285283
data->hctx->tags->rqs[rq->tag] = rq;
286284
}
287285

288-
INIT_LIST_HEAD(&rq->queuelist);
289286
/* csd/requeue_work/fifo_time is initialized before use */
290287
rq->q = data->q;
291288
rq->mq_ctx = data->ctx;
289+
rq->rq_flags = 0;
290+
rq->cpu = -1;
292291
rq->cmd_flags = op;
293292
if (data->flags & BLK_MQ_REQ_PREEMPT)
294293
rq->rq_flags |= RQF_PREEMPT;
295294
if (blk_queue_io_stat(data->q))
296295
rq->rq_flags |= RQF_IO_STAT;
297-
rq->cpu = -1;
296+
INIT_LIST_HEAD(&rq->queuelist);
298297
INIT_HLIST_NODE(&rq->hash);
299298
RB_CLEAR_NODE(&rq->rb_node);
300299
rq->rq_disk = NULL;
301300
rq->part = NULL;
302301
rq->start_time = jiffies;
303-
#ifdef CONFIG_BLK_CGROUP
304-
rq->rl = NULL;
305-
set_start_time_ns(rq);
306-
rq->io_start_time_ns = 0;
307-
#endif
308302
rq->nr_phys_segments = 0;
309303
#if defined(CONFIG_BLK_DEV_INTEGRITY)
310304
rq->nr_integrity_segments = 0;
@@ -321,6 +315,12 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
321315
rq->end_io_data = NULL;
322316
rq->next_rq = NULL;
323317

318+
#ifdef CONFIG_BLK_CGROUP
319+
rq->rl = NULL;
320+
set_start_time_ns(rq);
321+
rq->io_start_time_ns = 0;
322+
#endif
323+
324324
data->ctx->rq_dispatched[op_is_sync(op)]++;
325325
return rq;
326326
}

include/linux/blkdev.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,6 @@ typedef __u32 __bitwise req_flags_t;
141141
* especially blk_mq_rq_ctx_init() to take care of the added fields.
142142
*/
143143
struct request {
144-
struct list_head queuelist;
145-
union {
146-
call_single_data_t csd;
147-
u64 fifo_time;
148-
};
149-
150144
struct request_queue *q;
151145
struct blk_mq_ctx *mq_ctx;
152146

@@ -164,6 +158,8 @@ struct request {
164158
struct bio *bio;
165159
struct bio *biotail;
166160

161+
struct list_head queuelist;
162+
167163
/*
168164
* The hash is used inside the scheduler, and killed once the
169165
* request reaches the dispatch list. The ipi_list is only used
@@ -211,19 +207,16 @@ struct request {
211207
struct hd_struct *part;
212208
unsigned long start_time;
213209
struct blk_issue_stat issue_stat;
214-
#ifdef CONFIG_BLK_CGROUP
215-
struct request_list *rl; /* rl this rq is alloced from */
216-
unsigned long long start_time_ns;
217-
unsigned long long io_start_time_ns; /* when passed to hardware */
218-
#endif
219210
/* Number of scatter-gather DMA addr+len pairs after
220211
* physical address coalescing is performed.
221212
*/
222213
unsigned short nr_phys_segments;
214+
223215
#if defined(CONFIG_BLK_DEV_INTEGRITY)
224216
unsigned short nr_integrity_segments;
225217
#endif
226218

219+
unsigned short write_hint;
227220
unsigned short ioprio;
228221

229222
unsigned int timeout;
@@ -232,8 +225,6 @@ struct request {
232225

233226
unsigned int extra_len; /* length of alignment and padding */
234227

235-
unsigned short write_hint;
236-
237228
/*
238229
* On blk-mq, the lower bits of ->gstate (generation number and
239230
* state) carry the MQ_RQ_* state value and the upper bits the
@@ -260,6 +251,11 @@ struct request {
260251

261252
struct list_head timeout_list;
262253

254+
union {
255+
call_single_data_t csd;
256+
u64 fifo_time;
257+
};
258+
263259
/*
264260
* completion callback.
265261
*/
@@ -268,6 +264,12 @@ struct request {
268264

269265
/* for bidi */
270266
struct request *next_rq;
267+
268+
#ifdef CONFIG_BLK_CGROUP
269+
struct request_list *rl; /* rl this rq is alloced from */
270+
unsigned long long start_time_ns;
271+
unsigned long long io_start_time_ns; /* when passed to hardware */
272+
#endif
271273
};
272274

273275
static inline bool blk_rq_is_scsi(struct request *rq)

0 commit comments

Comments
 (0)