ハードディスクのDMA有効化とbdflushの調整
最近我が家のサーバーを新しいハードディスク(MK6021GAS 60GB)に入れ替えた。
しかし、ハードディスクへのアクセスがどうも遅いようだ。昔のハードディスクも遅く感じたが、古いので仕方ないくらいに思っていたが...。どうもおかしい。

結論は至って単純であった。
DMAモードではなく、PIOモードで動作していた。これでは遅くても仕方がない。
そんなわけで、今回はDMAモードの設定です。

ULTRA DMAを有効にする前のハードディスクのベンチマークを採ってみる。
結果はこんな感じだ。
[root /root]# hdparm -t /dev/hda

/dev/hda:
Timing buffered disk reads: 64 MB in 16.08 seconds = 3.98 MB/sec
次に、DMAを有効にする。
[root /root]# hdparm -c1 -d1 /dev/hda

/dev/hda:
setting 32-bit I/O support flag to 1
setting using_dma to 1 (on)
I/O support = 1 (32-bit)
using_dma = 1 (on)
再び、ベンチマーク。
なんと、5倍もの速度になっている。というより、この速度が普通だと思う。今までが遅すぎた。
[root /root]# hdparm -t /dev/hda

/dev/hda:
Timing buffered disk reads: 64 MB in 3.02 seconds = 21.19 MB/sec

以上で満足のいく結果が得られたが、今回の作業中に、ある事に気がついた。
ハードディスクへのアクセスが5〜6秒おきに行われているのである。(ハードディスクへのアクセスランプで確認)
 これはbdflushプロセスがハードディスクへアクセスを行っている為らしい。このプロセスはメモリの内容をハードディスクへflush(書き込む)する重要なプロセスではあるが、数秒おきにアクセスされるとハードディスクはスタンバイ状態になる事ができず、電気代がもったいない。
そこで、この数秒おきに発生するディスクアクセスを回避しようと思う。
※ちなみに、僕の環境ではノートPCのBIOSでHDDのスタンバイ時間を1分に指定している。もしBIOSで指定できない場合には、先ほどのhdparmでスタンバイ時間を指定する事が可能である。
"hdparm -S12 /dev/hda" -Sに続く数値がスタンバイまでの時間で5秒間隔である。この例では12を指定したので12*5=60秒を指定した事になる。

webで検索すると、inittabで指定される"ud::once:/sbin/update"を修正するとあると紹介されているが、私の環境ではその行がコメントになっている。色々調べた結果、設定する有効な方法は/proc/sys/vm/bdflushファイルを書き換える方法である。但し、/procファイルシステムがカーネル作成の際に有効になっている必要がある。
このファイルを参照すると幾つかの数字がある。
これの左から5番目の値を変更する事でflushする間隔を変更できる。
ただし、このファイルはカーネルのバージョンにより多少差があるらしい。また指定できるMAX値も異なっているようだ。ソースコードを参照して一度確かめてみる事を薦める。(カーネルソースコードディレクトリ/fs/buffer.c)

カーネル2.4.9の場合
以下の値はデフォルト値である。これの5番目が更新間隔である。(単位は10ミリ秒である。)
この値を大きくする事で更新の間隔を変更する事が可能である。最大値は60000(600秒)である。
この数値で足りない場合、bdflush_maxで指定されるMAX値を書き換えればより大きな値が指定できるようになると思われる。(確認してないので確かではないが。)
[root /root]# cat /proc/sys/vm/bdflush
30    64    64    256    100    600    60    0     0

カーネル2.4.18の場合
以下の値はデフォルト値である。こちらの場合も5番目が更新間隔である。
この値を大きくする事で更新の間隔を変更する事が可能である。最大値は1000000(10000秒)である。
僕の環境ではファイルの書き込みはめったに行われないので最大値でも良いと思う。
[root linux]# cat /proc/sys/vm/bdflush
50    500    0    0    100    600    60    20    0

更新する場合は、次のように行う。 以下の例では、更新間隔を60000(600秒)に設定している。5番目以外の項目はもとの値をそのまま指定しておこう。
[root linux]# echo "30 64 64 256 60000 600 60 0 0" > /proc/sys/vm/bdflush

最後に、今まで設定した内容をシステム起動時に有効にするように設定する。
DMAの場合も、bdflushの場合も再起動すると設定が失われる為毎回指定する必要がある。
起動用に次のようなスクリプトを作成する。 stopにてsyncを実行しているが、これは未書き込みデータを強制的にハードディスクへ書き込んでいる。
/etc/rc.d/init.d/hddctrl
#!/bin/sh

# Source function library.
. /etc/init.d/functions

case "$1" in
    start)
        echo -n "hdparm ... "
        hdparm -c1 -d1 /dev/hda  
<--DMAモードを有効にする。
        echo "50 500 0 0 1000000 600 60 20 0" > /proc/sys/vm/bdflush  
<--bdflushの設定を変更する
        ;;
    stop)
        echo -n "sync ... "
        sync  
<--メモリの内容を強制的に書き出し
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        exit 1
esac
exit 0
そして、ランレベル毎の設定を行う。
ランレベル3,5の時は上記スクリプトのstartを実行し0,6の時はstopを実行する。
[root init.d]# chmod +x hddctrl
[root init.d]# cd /etc/rc.d/rc3.d/
[
root rc3.d]# ln -s ../init.d/hddctrl S99hddctrl
[
root rc3.d]# cd ../rc5.d/
[
root rc5.d]# ln -s ../init.d/hddctrl S99hddctrl
[
root rc5.d]# cd ../rc0.d/
[
root rc0.d]# ln -s ../init.d/hddctrl K01hddctrl
[
root rc0.d]# cd ../rc6.d/
[
root rc6.d]# ln -s ../init.d/hddctrl K01hddctrl

以上で設定はお終いです。



お問い合わせはwebmaster@ryouto.jpまで。
Copyright (C)2003 ryouto.jp. All Rights Reserved.