Skip to content

Commit 488991e

Browse files
Alan D. BrunelleJens Axboe
authored andcommitted
block: Added in stricter no merge semantics for block I/O
Updated 'nomerges' tunable to accept a value of '2' - indicating that _no_ merges at all are to be attempted (not even the simple one-hit cache). The following table illustrates the additional benefit - 5 minute runs of a random I/O load were applied to a dozen devices on a 16-way x86_64 system. nomerges Throughput %System Improvement (tput / %sys) -------- ------------ ----------- ------------------------- 0 12.45 MB/sec 0.669365609 1 12.50 MB/sec 0.641519199 0.40% / 2.71% 2 12.52 MB/sec 0.639849750 0.56% / 2.96% Signed-off-by: Alan D. Brunelle <alan.brunelle@hp.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
1 parent 47483e2 commit 488991e

File tree

5 files changed

+39
-10
lines changed

5 files changed

+39
-10
lines changed

Documentation/ABI/testing/sysfs-block

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,17 @@ Description:
128128
preferred request size for workloads where sustained
129129
throughput is desired. If no optimal I/O size is
130130
reported this file contains 0.
131+
132+
What: /sys/block/<disk>/queue/nomerges
133+
Date: January 2010
134+
Contact:
135+
Description:
136+
Standard I/O elevator operations include attempts to
137+
merge contiguous I/Os. For known random I/O loads these
138+
attempts will always fail and result in extra cycles
139+
being spent in the kernel. This allows one to turn off
140+
this behavior on one of two ways: When set to 1, complex
141+
merge checks are disabled, but the simple one-shot merges
142+
with the previous I/O request are enabled. When set to 2,
143+
all merge tries are disabled. The default value is 0 -
144+
which enables all types of merge tries.

Documentation/block/queue-sysfs.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ size allowed by the hardware.
2525

2626
nomerges (RW)
2727
-------------
28-
This enables the user to disable the lookup logic involved with IO merging
29-
requests in the block layer. Merging may still occur through a direct
30-
1-hit cache, since that comes for (almost) free. The IO scheduler will not
31-
waste cycles doing tree/hash lookups for merges if nomerges is 1. Defaults
32-
to 0, enabling all merges.
28+
This enables the user to disable the lookup logic involved with IO
29+
merging requests in the block layer. By default (0) all merges are
30+
enabled. When set to 1 only simple one-hit merges will be tried. When
31+
set to 2 no merge algorithms will be tried (including one-hit or more
32+
complex tree/hash lookups).
3333

3434
nr_requests (RW)
3535
----------------

block/blk-sysfs.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ static ssize_t queue_nonrot_store(struct request_queue *q, const char *page,
189189

190190
static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
191191
{
192-
return queue_var_show(blk_queue_nomerges(q), page);
192+
return queue_var_show((blk_queue_nomerges(q) << 1) |
193+
blk_queue_noxmerges(q), page);
193194
}
194195

195196
static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
@@ -199,10 +200,12 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
199200
ssize_t ret = queue_var_store(&nm, page, count);
200201

201202
spin_lock_irq(q->queue_lock);
202-
if (nm)
203+
queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
204+
queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
205+
if (nm == 2)
203206
queue_flag_set(QUEUE_FLAG_NOMERGES, q);
204-
else
205-
queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
207+
else if (nm)
208+
queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
206209
spin_unlock_irq(q->queue_lock);
207210

208211
return ret;

block/elevator.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,15 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
473473
struct request *__rq;
474474
int ret;
475475

476+
/*
477+
* Levels of merges:
478+
* nomerges: No merges at all attempted
479+
* noxmerges: Only simple one-hit cache try
480+
* merges: All merge tries attempted
481+
*/
482+
if (blk_queue_nomerges(q))
483+
return ELEVATOR_NO_MERGE;
484+
476485
/*
477486
* First try one-hit cache.
478487
*/
@@ -484,7 +493,7 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
484493
}
485494
}
486495

487-
if (blk_queue_nomerges(q))
496+
if (blk_queue_noxmerges(q))
488497
return ELEVATOR_NO_MERGE;
489498

490499
/*

include/linux/blkdev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ struct request_queue
463463
#define QUEUE_FLAG_IO_STAT 15 /* do IO stats */
464464
#define QUEUE_FLAG_CQ 16 /* hardware does queuing */
465465
#define QUEUE_FLAG_DISCARD 17 /* supports DISCARD */
466+
#define QUEUE_FLAG_NOXMERGES 18 /* No extended merges */
466467

467468
#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \
468469
(1 << QUEUE_FLAG_CLUSTER) | \
@@ -589,6 +590,8 @@ enum {
589590
#define blk_queue_queuing(q) test_bit(QUEUE_FLAG_CQ, &(q)->queue_flags)
590591
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
591592
#define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
593+
#define blk_queue_noxmerges(q) \
594+
test_bit(QUEUE_FLAG_NOXMERGES, &(q)->queue_flags)
592595
#define blk_queue_nonrot(q) test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags)
593596
#define blk_queue_io_stat(q) test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags)
594597
#define blk_queue_flushing(q) ((q)->ordseq)

0 commit comments

Comments
 (0)