Documentation: block: ROW I/O scheduler

This patch updates the documentation of the ROW
I/O scheduler.

Change-Id: I6a996a3852fe39976381f99c07588558f1945034
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
This commit is contained in:
Tatyana Brokhman
2012-12-03 14:15:40 +02:00
parent a80e0226fa
commit 011f09a965
+82 -65
View File
@@ -8,16 +8,28 @@ which is the main requests dispatch policy of this algorithm.
The ROW IO scheduler was developed with the mobile devices needs in
mind. In mobile devices we favor user experience upon everything else,
thus we want to give READ IO requests as much priority as possible.
The main idea of the ROW scheduling policy is:
If there are READ requests in pipe - dispatch them but don't starve
the WRITE requests too much.
The main idea of the ROW scheduling policy is just that:
- If there are READ requests in pipe - dispatch them, while write
starvation is considered.
Software description
====================
The elevator defines a registering mechanism for different IO scheduler
to implement. This makes implementing a new algorithm quite straight
forward and requires almost no changes to block/elevator framework. A
new IO scheduler just has to implement a set of callback functions
defined by the elevator.
These callbacks cover all the required IO operations such as
adding/removing request to/from the scheduler, merging two requests,
dispatching a request etc.
Design
======
The requests are kept in queues according to their priority. The
dispatching of requests is done in a Round Robin manner with a
different slice for each queue. The dispatch quantum for a specific
queue is defined according to the queues priority. READ queues are
queue is set according to the queues priority. READ queues are
given bigger dispatch quantum than the WRITE queues, within a dispatch
cycle.
@@ -30,88 +42,93 @@ distributed to:
- Regular priority WRITE queue
- Low priority READ queue
The marking of request as high/low priority will be done by the
application adding the request and not the scheduler. See TODO section.
If the request is not marked in any way (high/low) the scheduler
assigns it to one of the regular priority queues:
read/write/sync write.
If in a certain dispatch cycle one of the queues was empty and didn't
use its quantum that queue will be marked as "un-served". If we're in a
middle of a dispatch cycle dispatching from queue Y and a request
use its quantum that queue will be marked as "un-served". If we're in
a middle of a dispatch cycle dispatching from queue Y and a request
arrives for queue X that was un-served in the previous cycle, if X's
priority is higher than Y's, queue X will be preempted in the favor of
queue Y. This won't mean that cycle is restarted. The "dispatched"
counter of queue X will remain unchanged. Once queue Y uses up it's quantum
(or there will be no more requests left on it) we'll switch back to queue X
and allow it to finish it's quantum.
queue Y.
For READ requests queues we allow idling in within a dispatch quantum in
order to give the application a chance to insert more requests. Idling
means adding some extra time for serving a certain queue even if the
queue is empty. The idling is enabled if we identify the application is
inserting requests in a high frequency.
For READ request queues ROW IO scheduler allows idling within a
dispatch quantum in order to give the application a chance to insert
more requests. Idling means adding some extra time for serving a
certain queue even if the queue is empty. The idling is enabled if
the ROW IO scheduler identifies the application is inserting requests
in a high frequency.
Not all queues can idle. ROW scheduler exposes an enablement struct
for idling.
For idling on READ queues, the ROW IO scheduler uses timer mechanism.
When the timer expires we schedule a delayed work that will signal the
device driver to fetch another request for dispatch.
For idling on READ queues we use timer mechanism. When the timer expires,
if there are requests in the scheduler we will signal the underlying driver
(for example the MMC driver) to fetch another request for dispatch.
The ROW algorithm takes the scheduling policy one step further, making
it a bit more "user-needs oriented", by allowing the application to
hint on the urgency of its requests. For example: even among the READ
requests several requests may be more urgent for completion then others.
The former will go to the High priority READ queue, that is given the
bigger dispatch quantum than any other queue.
ROW scheduler will support special services for block devices that
supports High Priority Requests. That is, the scheduler may inform the
device upon urgent requests using new callback make_urgent_request.
ROW scheduler will support additional services for block devices that
supports Urgent Requests. That is, the scheduler may inform the
device driver upon urgent requests using a newly defined callback.
In addition it will support rescheduling of requests that were
interrupted. For example, if the device issues a long write request and
a sudden high priority read interrupt pops in, the scheduler will
inform the device about the urgent request, so the device can stop the
current write request and serve the high priority read request. In such
a case the device may also send back to the scheduler the reminder of
the interrupted write request, such that the scheduler may continue
sending high priority requests without the need to interrupt the
ongoing write again and again. The write remainder will be sent later on
according to the scheduler policy.
Design
======
Existing algorithms (cfq, deadline) sort the io requests according LBA.
When deciding on the next request to dispatch they choose the closest
request to the current disk head position (from handling last
dispatched request). This is done in order to reduce the disk head
movement to a minimum.
We feel that this functionality isn't really needed in mobile devices.
Usually applications that write/read large chunks of data insert the
requests in already sorted LBA order. Thus dealing with sort trees adds
unnecessary complexity.
We're planing to try this enhancement in the future to check if the
performance is influenced by it.
interrupted. For example if the device driver issues a long write
request and a sudden urgent request is received by the scheduler.
The scheduler will inform the device driver about the urgent request,
so the device driver can stop the current write request and serve the
urgent request. In such a case the device driver may also insert back
to the scheduler the remainder of the interrupted write request, such
that the scheduler may continue sending urgent requests without the
need to interrupt the ongoing write again and again. The write
remainder will be sent later on according to the scheduler policy.
SMP/multi-core
==============
At the moment the code is acceded from 2 contexts:
At the moment the code is accessed from 2 contexts:
- Application context (from block/elevator layer): adding the requests.
- Underlying driver context (for example the mmc driver thread): dispatching
the requests and notifying on completion.
- device driver thread: dispatching the requests and notifying on
completion.
One lock is used to synchronize between the two. This lock is provided
by the underlying driver along with the dispatch queue.
by the block device driver along with the dispatch queue.
Config options
==============
1. hp_read_quantum: dispatch quantum for the high priority READ queue
2. rp_read_quantum: dispatch quantum for the regular priority READ queue
3. hp_swrite_quantum: dispatch quantum for the high priority Synchronous
WRITE queue
(default is 100 requests)
2. rp_read_quantum: dispatch quantum for the regular priority READ
queue (default is 100 requests)
3. hp_swrite_quantum: dispatch quantum for the high priority
Synchronous WRITE queue (default is 2 requests)
4. rp_swrite_quantum: dispatch quantum for the regular priority
Synchronous WRITE queue
Synchronous WRITE queue (default is 1 requests)
5. rp_write_quantum: dispatch quantum for the regular priority WRITE
queue
queue (default is 1 requests)
6. lp_read_quantum: dispatch quantum for the low priority READ queue
(default is 1 requests)
7. lp_swrite_quantum: dispatch quantum for the low priority Synchronous
WRITE queue
WRITE queue (default is 1 requests)
8. read_idle: how long to idle on read queue in Msec (in case idling
is enabled on that queue).
is enabled on that queue). (default is 5 Msec)
9. read_idle_freq: frequency of inserting READ requests that will
trigger idling. This is the time in Msec between inserting two READ
requests
requests. (default is 8 Msec)
Note: Dispatch quantum is number of requests that will be dispatched
from a certain queue in a dispatch cycle.
To do
=====
The ROW algorithm takes the scheduling policy one step further, making
it a bit more "user-needs oriented", by allowing the application to
hint on the urgency of its requests. For example: even among the READ
requests several requests may be more urgent for completion than other.
The former will go to the High priority READ queue, that is given the
bigger dispatch quantum than any other queue.
Still need to design the way applications will "hint" on the urgency of
their requests. May be done by ioctl(). We need to look into concrete
use-cases in order to determine the best solution for this.
This will be implemented as a second phase.
Design and implement additional services for block devices that
supports High Priority Requests.