mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-21 12:41:26 +00:00
Web updates
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3660 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -93,156 +93,6 @@
|
||||
page cache, namely, locking issues related to it. They should be carefully
|
||||
investigated.</p>
|
||||
|
||||
<A NAME="DYN_FLOW"></A><h3>Dynamic I/O flow control</h3>
|
||||
|
||||
<p>At the moment, if an initiator or several initiators simultaneously send to
|
||||
target too many commands, especially in seek intensive workloads, target can get
|
||||
overloaded and not able to finish commands on time. In such cases you can see on
|
||||
the initiator(s) messages about aborting commands or resetting the target. See in SCST core
|
||||
README section "What if target's backstorage is too slow" for more details.
|
||||
To fix this problem it is necessary to implement a dynamic I/O flow control in
|
||||
SCST core.</p>
|
||||
|
||||
<p>The flow control, generally, is quite simple. Each SCST command has timeout value,
|
||||
which is set by the corresponding dev handler. SCST core should keep device's queue depth
|
||||
at the level that the worst command's execution time, i.e. time between scst_rx_cmd()
|
||||
and scst_finish_cmd(), would be between something like timeout/10 and timeout/5.
|
||||
So, commands execution time should be checked and:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>If it's > timeout/5, then the new queue depth should be set to max(1,
|
||||
cur_depth/2)</span></li>
|
||||
|
||||
<li><span>If it's < timeout/10, then new queue depth should be set to min(MAX_DEPTH,
|
||||
cur_depth+1). This shouldn't be done too often, once in a few minutes should be
|
||||
sufficient</span></li>
|
||||
</ul>
|
||||
|
||||
<p>The above is, of course, an oversimplification to let you see the idea.
|
||||
Implementation considering real life cases should be as the following:</p>
|
||||
|
||||
<p>1. There are several parameters:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>P - load watch period. During this period all the statistic is
|
||||
gathered and processed.</span></li>
|
||||
|
||||
<li><span>MN - underload ratio divisor, which sets the underload portion of
|
||||
timeout. If the longest execution time among all commands completed
|
||||
during period P is below timeout/MN, the corresponding device considered
|
||||
underloaded.</span></li>
|
||||
|
||||
<li><span>MX - overload ratio divisor, which sets the overload portion of
|
||||
timeout. If the longest execution time among all commands completed
|
||||
during period P is above timeout/MX, the corresponding device considered
|
||||
overloaded.</span></li>
|
||||
|
||||
<li><span>I - step on which device's queue size will be increased if device
|
||||
considered underloaded.</span></li>
|
||||
|
||||
<li><span>D - divisor on which device's queue size will be decreased if device
|
||||
considered overloaded.</span></li>
|
||||
|
||||
<li><span>QI - quick fall interval. See description of Q parameter.</span></li>
|
||||
|
||||
<li><span>Q - quick fall ratio divisor. If the longest execution time of a
|
||||
completed command is above timeout/Q and time from the previous quick
|
||||
fall is smaller than QI, the corresponding device considered heavily
|
||||
overloaded. The quick fall is needed to handle cases when load on device
|
||||
is instantly increased on the way, where it can't handle it properly.</span></li>
|
||||
|
||||
<li><span>QD - divisor on which device's queue size will be decreased if
|
||||
device considered heavily overloaded.</span></li>
|
||||
</ul>
|
||||
|
||||
<p>The default values should be something like: P=15 sec., MN=20, MX=10, Q=3,
|
||||
I=1, D=2, QI=5 sec., QD=10.</p>
|
||||
|
||||
<p>2. There are the following new variables in struct scst_device:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>queue_depth - current queue depth.</span></li>
|
||||
|
||||
<li><span>max_exec_ratio - maximum commands timeout/(execution time).</span></li>
|
||||
|
||||
<li><span>queue_was_full - flag, marking that the queue was at least once full
|
||||
during period P.</span></li>
|
||||
|
||||
<li><span>quick_fall_time - time of the last quick fall.</span></li>
|
||||
|
||||
<li><span>flow_lock - protects flow control related variables, where needed.</span></li>
|
||||
|
||||
<li><span>...</span></li>
|
||||
</ul>
|
||||
|
||||
<p>3. The commands processing path should be as the following:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>In scst_rx_cmd() the start time of the command is recorded (already done).</span></li>
|
||||
|
||||
<li><span>In __scst_init_cmd(), if dev->dev_cmd_count == dev->queue_depth,
|
||||
dev->queue_was_full set to true.</span></li>
|
||||
|
||||
<li><span>In scst_finish_cmd() dev->max_exec_ratio set to max(dev->max_exec_ratio,
|
||||
(cmd's exec_time)*100/cmd->timeout).</span></li>
|
||||
|
||||
<li><font color="#666666">If in scst_finish_cmd() cmd's exec time is above cmd->timeout/Q and
|
||||
time from the latest quick fall is above QI, then:</font>
|
||||
|
||||
<ul>
|
||||
<li><span>dev->queue_depth set to max(1, dev->queue_depth/QD).</span></li>
|
||||
|
||||
<li><span>Flow control period reset, i.e. started again, including setting
|
||||
dev->max_exec_ratio to 0 and dev->quick_fall_time to jiffies.</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>4. There should be a work, which once in a P seconds will check
|
||||
dev->max_exec_ratio, then:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>If device neither underloaded, nor overloaded. i.e. max_exec_ratio
|
||||
between defined by MN and MX, do nothing.</span></li>
|
||||
|
||||
<li><font color="#666666">If device was underloaded:</font>
|
||||
|
||||
<ul>
|
||||
<li><span>if dev->queue_was_full is false, then do nothing.</span></li>
|
||||
|
||||
<li><span>if dev->queue_was_full is true, then set dev->queue_depth to
|
||||
min(SCST_MAX_DEV_COMMANDS, dev->queue_depth + I).</span></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><span>If device was overloaded, then set dev->queue_depth to max(1,
|
||||
dev->queue_depth/D).</span></li>
|
||||
</ul>
|
||||
|
||||
<p>Then the flow control period is reset, i.e. started again, including
|
||||
setting dev->max_exec_ratio to 0 and dev->quick_fall_time to jiffies.</p>
|
||||
|
||||
<p>That's all. Then only support for initiators, like iSCSI,
|
||||
which don't handle QUEUE FULL to decrease amount of queued
|
||||
commands, should be added. Such initiators expect target to control size of
|
||||
the queue, via, e.g., through MAX_SN for iSCSI.</p>
|
||||
|
||||
<p>For it at the stage 2 of the dynamic flow control development
|
||||
the following should be done:</p>
|
||||
|
||||
<ul>
|
||||
<li><span>New callback on_queue_depth_adjustment() should be added to struct
|
||||
scst_tgt_template.</span></li>
|
||||
|
||||
<li><span>If target driver defined it, each time after dev->queue_depth changed
|
||||
on_queue_depth_adjustment() should be called. In this callback target
|
||||
driver should change internal queue_depth to, e.g. for iSCSI target, set
|
||||
max_sn in the replies correctly.</span></li>
|
||||
</ul>
|
||||
|
||||
<p>Then, at the latest stage of the development, logic to not schedule the
|
||||
flow control work on idle devices should be added.</p>
|
||||
|
||||
<A NAME="O_DIRECT"></A><h3>Support for O_DIRECT in scst_vdisk handler</h3>
|
||||
|
||||
<p>At the moment, scst_vdisk handler doesn't support O_DIRECT option and possibility to set it
|
||||
|
||||
Reference in New Issue
Block a user