壊れたファイルシステムの保存・復元作業

先日の騒動、無事btrfsの修復ができたが、損失の可能性がある。 そこで、バックアップを利用して損失があった場合に備える。

基本的な考え方としては、損失がある可能性のあるファイルを上書きせずにバックアップし、その上でrsyncによりバックアップの更新を行う。

完全なsnapshotを取るのではなく、データに差分があるものについて行うこととした。 つまり、全データについて、実際に読んで、比較することになる。

まずは待避先となるサブボリュームを用意する。

# btrfs subvolume create escaped_snap

次に、さらに別のサブボリュームを用意し、そこに全データをコピーする。今回はディスクに余裕があるので、不安定なデスクトップの稼働時間を抑えることを優先した。

# btrfs subvolume create dest2
# umount /WorldMirror
# mount -o gzip,noatime,space_cache,subvol=dest2 /dev/mapper/btrvolume01 /WorldMirror

最初はrecursiveにファイルを探索して、cmpで比較し、差分があるものについてコピーしようとした。

#!/usr/bin/zsh
# $1 = olddir
# $2 = newdir
# $3 = snapshot base dir

setopt extended_glob
cd "$1"


for i in **/*(#qD.)
do
  print ">>$i"
  if cmp "$i" "$2/$i"
  then
    print "OK"
  else
    sha256sum "$2/**/$i" > /tmp/rec-dir-cmpsnap-sum
    sum=$(sha256sum "$i" | cut -d " " -f 1)
    
    if ! fgrep -q "$sum" /tmp/rec-dir-cmpsnap-sum
    then
      tar cfv - "$i" | (cd "$3"; tar xf -)
    fi

  fi
done

rm /tmp/rec-dir-cmpsnap-sum

だが、うまくいかなかった。理由はよくわからなかったが。

そこで、再帰的なチェックサム差分のためにrsyncのdry-runを使う。

rsync -cvna /mnt/3/ /Worldmirror/ > rsyncdiff.result

/mnt/3には元々の、上書きされていないバックアップがある。

dry-runなので、これによってコピーされようとしているファイルが出力される。 -cオプションでチェックサム比較しているので、「バイナリ的に違いがある、または新しいコピーには存在しないもの」がリストアップされる。

これで転送に関する余分なメッセージを削除すればファイルリストができる。 今回はファイルリストにmvした300GBを越えるファイルがあるので、それについてはリストから削除しておく。

そしてそのリストに基づいてスナップショットへとコピー

while read
do
tar cvf - "$REPLY" | (cd /mnt/2; tar xf -)
done < ~/rsyncdiff.result2

長い道のりだった

フリーズ→btrfsファイルシステム崩壊

熱なのかPCがフリーズ、そしてBtrfsが壊れ、マウントできなくなった。

btrfs csum mismatch on free space cache

と言われてしまう。

これがまたどうしようもない。fsckしてみるが

# btrfsck /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765

エラーを大量に吐くだけ。

リカバリーマウントしようとしてみる。

# mount -t btrfs -o recovery,no_space_cache /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765

がやはりマウントできない。

諦めてリカバリー

# btrfs check --repair /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765

が、ここでもfsckなエラーが出てしまい結果は同じ、依然として状況は変わらず。

zero-log

# btrfs-zero-log /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765

エラーのあと完了を知らせるが、やはり状況は変わらず。

救出マウント

# mount -t btrfs -o recovery,nospace_cache,nospace_cache /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765 /mnt/1

マウントできた。scrub

# btrfs scrub start /dev/mapper/dmcw_ata-WDC_WD30EZRX-00D8PB0_WD-WCC4N0840765

時々statusを見ると、猛烈な勢いでエラーがたまっていく。システムがとても重い。

しばらく後、コンソールに出力

WARNING: errors detected during scrubbing, corrected.

statusしてみると

scrub status for 5764a2af-d7e7-4b45-955c-19e27de332ee
	scrub started at Wed Mar 25 13:52:45 2015 and finished after 10337 seconds
	total bytes scrubbed: 4.30TiB with 635846 errors
	error details: read=13 verify=630 csum=635203
	corrected errors: 635846, uncorrectable errors: 0, unverified errors: 0

635846 errors!! まぁ、それはすごい。 しかし、すべてcorrectedとなっているから大丈夫なのか。

一応、従来のバックアップとは別にバックアップをとり、その上で差分をとって、差分があるファイルは保存しておくようにしよう。

メインシステムをEncFS on BtrfsからBtrfs on dm-cryptに変更

概要

散々やるよといっていた構成変更だが、ついに実行した。

作業はかなり面倒で、1時間半ほどかかってしまった。

今までは次のようになっていた。

  • 4ディスクによるBtrfsを編成
  • Btrfsはサブボリュームを持つ
  • ひとつのサブボリュームを丸々EncFSとする
  • .zshrcでencfsコマンドを呼び、マウントする

この方法のメリットは次のようなものだ

  • 強力で柔軟な暗号化
  • ファイル単位でのバックアップが、暗号化したまま可能
  • 手軽
  • rootでもユーザーデータにアクセスできないので、かなり安全

一方デメリットは次のようなもの

  • rootでユーザーデータにアクセスできないとKVMが暗号化されたディスクにイメージを置けないなど結構不便
  • 特にバックアップで困る
  • ファイルアクセスは常にEncFSがトップ。どのプロセスがIO負荷になっているのかわからない

下準備

先日のrsoftmirrorとrsyncを使ってデータをすべてスレーブにバックアップ

dm-crypt

4kBのurandomデータをめちゃくちゃに暗号しまくって、その中から512Bを切り出す方法で鍵ファイルを作成。これを使う。

cryptsetup --hash=sha512 --key-size=512 --ciper="twofish-xts-plain" --offset=0 key-file=/etc/worldencmount/keyfile --type=plain open device name

単にopen。LUKSではluksFormatという専用のアクションがあるが、プレーンだとない。 ちなみに、twofish-xts-plain結構遅い

これをしただけだとBtrfsの存在はblkidでは残っているように見えてしまう。 そこでrebootするのだが、その前に/etc/fstabを編集してbtrfsをマウントしないようにしておかないと痛い目を見る。

Btrfs

リブートしたら暗号化を行うのと同じ手順でデバイスをオープンする。 Btrfsはそのオープンしたデバイスに対して行う。

# mkfs.btrfs -m raid1 -d raid1 -l WorldBtrfs /dev/mapper/world_enc_*

ちなみに、ストライプで高速化するのではなく、ミラーで分散してもらうことにした。 ミラーするかどうかは悩んだのだが、やはり安全をとってミラー。つまり、2ミラー、1バックアップになる。

サブボリュームを作ることを忘れていて若干ハマった。

# mount /dev/mapper/world_enc_1 /mnt/1
# cd /mnt/1
# btrfs subvolume create shared-world

設定ファイルにblkidでdm-cryptのPARTUUIDを送り込んでおく。 また、btrfsのUUIDを/etc/fstabに送り込んでおく。

# blkid | grep -F /dev/mapper/world_enc_* | tail -n 1 >> /etc/fstab

そしてvim

# vim /etc/fstab

コピペしてUUIDを書き換え、ゴミを消去し、コメントアウトを外し、noautoオプションを追加する。

修正

そういえばこの方法はdiskのパーティションを暗号化している。 これは推奨される方法だが、やはりできればwhole diskの暗号化をしたい。 LUKSも含め3TB以上のwhole diskの暗号化には対応している。

だが、そうするとかなり重大な問題が生じる。 PARTUUIDやPARTLABELが使えなくなるのだ。

これは結構困ったことで、どうしたものかと思ったが、/dev/disk/by-idを使うことにした。 これはWWIDと呼ばれる、システムに依存しないデバイスに対して永続的なIDであるという。 若干手間だが、確実だ。

ちなみにこの修正、同期がかなり進んだ段階でリセットする形で行った。 この修正に30分くらいかかってしまった。

セットアップスクリプト

#!/usr/bin/zsh

#read config file.
. /etc/worldencmount/worldrc || exit 1

#decryption
for disk in "${disks[@]}"
do
  cryptsetup --hash=sha512 --key-size=512 --cipher="twofish-xts-plain" --offset=0 --key-file=${keyfile:-/etc/worldencmount/seedfile} --type=plain open "$disk" dmcw_${disk:t}
done

.zshrc

#Check shared zshrc file.

if [[ -e $HOME/share/.zshrc ]]
then
  # Enable shared zshrc
  . $HOME/share/.zshrc
else
  # Disabled shared zshrc.
  
  print ~/share/.zshrc "is not exist." >&2
  print "Probably encrypted filesystem don't mount yet." >&2
  print "Let's mount it!" >&2
  print >&2
  
  ## Decryption ##
  if sudo btrfs filesystem show | grep -F -q HydrangeaMasterBtr
  then
    print "Btrfs filesystem already active." >&2
  else
    if sudo /usr/local/sbin/worldencmount
    then
      print "Okay, succeed to decrypt." >&2
    else
      print "Oh, failed to decrypt disks." >&2
      print "Aborting..." >&2
      exit 2
    fi
  fi
  
  ## Mount ##
  if sudo mount ~/share
  then
    print "Okay, succeed to mount the filesystem." >&2
    print "You can use the World." >&2
    exit 0
  else
    print "Gosh! failed to mount. I don't know why." >&2
    print "Please fix it." >&2
    exit 3
  fi
fi

いままでよりだいぶ複雑になった。 結局、自動マウントではなく.zshrcで処理するようにした。 このほうが合理的だ。

slave側の自動マウント

逆にslave側は常にマウントされているべきなので、systemdユニットを書く。

[Unit]
Description=Mount World filesystem.
After=network.service

[Service]
ExecStart=/usr/local/sbin/worldmount

[Install]
WantedBy=multi-user.target

そして自動起動

# systemctl enable worldmount

ものすごく手抜きで、実はまだテストしていないが、動くはずだ。 ちなみにCentOS7である。

同期

rsyncで新たに作られた~/shareに同期する。 これは復旧作業なので通常とは逆方向のsyncとなる。 結果的には約14時間かかった。gzipのためか時間はかかったが、容量は2.02TiBと約2/3に抑えられた。

鍵のバックアップ

鍵ファイルがなくなると困るのでバックアップ。 しかしそれだけでは暗号化している意味がないので、鍵ファイルも暗号化した上でCD-Rに焼く。 暗号化はopensslのencを使うのが手っ取り早く、確実。 復号化用のスクリプトも同梱した。

総論

今回の作業はそれなりにしんどかったが、それでも同期を別とすれば1時間半ほどで終了した。 (ただしそれは最初にしたようにパーティションベースで行った場合のみの話)

元々EncFSにしたのは暫定的な措置だったし、スレーブサーバー設置に伴ってこういった作業をすることは想定していた。

ZFSが遅い

先日、ZFS+rsyncでやっていくことにした、と報告したが、挫折した。

最初の7時間で300GBの進捗。まぁ、これはいい。だが、いくらなんでもそのあと3時間で40GBの進捗はない。それはひどすぎる。

これでは実用にならないのでBtrfsに変更。結果としては出だしで18倍以上の差となり、15時間ほどで2TBの転送を完了した。

ちなみに、サーバーはProliant MicoroServerで、メモリは4GB。Swapは使われていなかった。

不安定なZFSの劣化コピーとみなされがちなBtrfsだが、こうしてみるとZFSを凌ぐ部分が結構みつかる。特に、ZFS on Linuxと比較するとかなりだ。

Btrfsは既にかなり安定しているし、また速度的なアドバンテージがある。また、自動でストライピングするが、ミラーの場合でも1台単位で追加でき、1+0でもリバランスできる。これはZFSにはない特徴だ。

そして新たに知ったこととして、BtrfsにもZFS同様のSend/Recieveがあるということだ。Btrfs、かなり良い。

ストレージワーク:btrfs+EncFS / dm-crypt+ZFSでのリモートミラー

Btrfs上にEncFSを構成したマスターから、dm-crypt上にZFSを構築したスレーブへとミラーする、しかもそれらのホストはシャットダウンされる。これはかなり厳しい条件だった。

やはりシャットダウンされるためにHA(高可用)システムは使えない。シャットダウンする時点で障害発生とみなされるし、切り離された状態で単独でスタートアップして動けない。

さらに、EncFSはrootであってもアクセスを許さないため、非常にセキュアではあるが、GlusterFS GeoReplicationも使えないなど障害になった。

やはり無理な要求である、というのは

LinuxQuestionで聞いてみても
明らかになるだけだった。だが、ここでrsyncが大規模システムに耐えるということが分かったため、rsync(1)at(1)でいこうと決意を固めることができた。

rsync+sshはごくごく単純だ。

rsync -e ssh fromdir user@host:destdir

でいける。だが、まずはZeroconfでアクセスしたい。

Manjaroで/etc/nsswitch.confmdns_minimalを指定しても解決できない。これでホスト名を解決しようと思うと、nss-mdnsパッケージをインストールし、avahi-daemonを動かさなくてはいけない。

さらに、CentOS側が受け入れてくれない。これは、NICがひとつだとそのNICをpublicなゾーンのインターフェイスとみなすが、Avahiはhomeインターフェイスにしか許されていない。そのため、firewall-cmd --add-service=avahi --zone=public --permanentとしてAvahi-daemonへのアクセスを透過する。

これでZeroconfでのアクセスに成功、.localのホスト名でsshアクセスできる。ssh-keygenでパスフレーズなしのキーを作り、アクセスしようとする。ところが、ssh-copy-idしようとした段階でToo many authentication failures for ...となり、sshアクセスできない。これは、sshの管理下にある鍵が多すぎる場合に生じるようだ。その数はsshdが登録、管理している鍵とファイルとして~/.ssh以下にある鍵の総数。とりあえずの方法としては、鍵ファイルがあるものだけを鍵として扱うため、~/.ssh/config

IdentitiesOnly yes

と書くと改善される。ただし、ファイル自体が多くなるとこれでもダメだろう。

これで鍵によるアクセスまでできるようになった。

鍵による実際のアクセスの前に、atとrsyncについて確認する。rsyncについては前述の通りで大丈夫。atは

$ <kbd>at now + 1 minutes &lt;&lt;&lt; 'zsh -c "notify-send \"$(id)\""'</kbd>

すると自身のuidになっているので、atを実行したユーザーで実行されることが分かる。EncFSに対してアクセスするためにはこれは絶対条件だ。

そしてこのままrsyncするとうまくいく。だが、パスフレーズなしで自由にアクセスできる鍵というのは危険だ。

コマンドで制限すべきなのだが、rsyncのコマンドを受ける側がどうなっているのか、というのは非常にわかりにくい。rsync -vvv -au --delete-after -e ssh from destして、パスワードの前に表示されたconnectionの中からrsyncより前を削り、互いにvを削って設定する。

ただし、このままでは外部からファイルを消されるリスクがあるため、ホストも限定したほうがいいかもしれない。ただし、鍵がなければできないのだから、その時はバックアップ側は仕方がない、とも見れる。

今回の成果物も

GitHub
にて公開。

新しいストレージワーク(GlusterFS, AoE, lsyncd)

問題点

分かってはいたことだが、先日の件でbtrfs mirrorでは不十分だ。データの冗長化は次のようなことが考えられる。

  • ストレージの故障
  • ファイルシステムの故障
  • RAIDハードウェアの故障
  • 誤操作による喪失
  • コンピュータノードの故障
  • コンピュータノードの喪失(災害や盗難など)

基本的な対応は次の通り。

ストレージの故障
ミラーリングを行い、故障したストレージを置き換える
ファイルシステムの故障
異なるファイルシステム間でミラーするか、バックアップする。
RAIDハードウェアの故障
同一のRAIDハードウェアに再接続するか、バックアップによって復元する
誤操作
gitやpdumpfs、あるいはLogFSなどスナップショットの活用
ノードの故障
新規ノードにストレージを移設する。可用性が不要ならばデータの冗長化は不要
ノードの喪失
可用性の損失は避けられない。同一箇所に保管していると同時に損失する可能性は高いため、クラウドバックアップが有効

一般にノードの損失は稀なケースだと考えられる。だが、実際はそこそこ可能性はある。落雷によっても起こりうる。この場合のことを考えれば、データを諦められないのであればバックアップは必要だ。

これまでは、btrfsの2レッグミラーを採用していた。これはストレージの故障に対する冗長性・可用性を担保する。しかし、それ以外には対応できていない。特に怖いのは、未だexperimentalであるbtrfs自体の異常だ。ファイルシステムが壊れてしまえばミラーされていたものも含めてすべてのデータがアクセス不能になる。

少々複雑な話に聞こえるかもしれないが、btrfsは「壊れにくいファイルシステム」だ。日常的な読み書きで起こるビットエラーをbtrfsは発見し、ミラーリングを行っていれば訂正することすら可能だ。そのため、他のファイルシステムと比べ非常に壊れにくい。それは他のジャーナリングファイルシステムと比べてもだ。そのためた信頼性が高いと言われ、この点を買って私は採用している。一方で、btrfsはまだ完成度が低く、btrfs自体が壊れる挙動を示す可能性がある。そのため信頼性が低いとされている。

データが既に2TiBを超えている現状にあっては、バックアップやその復元も容易ではない。ちなみに、この次にハードルが上がるのは、ストレージ1台ではすまなくなる時だ。コストを度外視すれば、8TBということになる。

基本的にはバックアップというよりも、ミラーリングによって冗長性を持たせ、データが損失しないことを前提とする方向としている。今後も情報増加は進む予定だし、それに対応する構成としておかなくてはならないからだ。そして、データ量は一般的なシングルストレージで済む量に収まる見込みはない。ストレージ増加よりもデータ増加の方がはるかに速い。

現在の対応は次の通りだ。

  • btrfsによるジャーナリング、自動訂正によるビットエラー対策
  • btrfsミラーによる冗長化
  • btrfsによる柔軟なストレージ追加。1台単位でディスク容量を問わず追加し任意のボリュームを切り出せる
  • 必要な箇所をgitとすることで誤操作による損失の防止
  • 一部データのリモートgitへのclone

だが、先日はそのストレージを格納するコンピュータノードがダウンした。そのため、データ自体にアクセスできなくなった。現在でも最低限、4台のストレージを搭載しなければデータを使うことができない。Proliant Microserverは搭載ストレージ台数は4なので、システムドライブを含めるとそれを搭載することができない。

もちろん、データは損失していないのだからコンピュータノードを追加すれば良いのだが、その間仕事は完全に停止してしまう。やはりこの点も冗長性が必要だろう。

機能問題は別として、別のコンピュータがデータを触れれば良いのだ。コンピュータノード全体がダウンしても機能するようにすれば、1台のコンピュータが損失しても問題ない、ということになる。もっとも、実際に必要となるのは完全なクラウドバックアップだが、現在のところそれは月額で8万円程度が必要になるため、現実的でない。

GlusterFS

GlusterFSはペタバイト規模に対応するクラスタストレージ技術だ。ユーザースペースで動作するデーモンであり、大きなファイルの読み書きはネイティブなコードで行う。FUSEでマウントできるだけでなく、NFSやCIFSでもマウント可能。

分散ファイルシステムだがネイティブファイルシステムではなく、各コンピュータはマウントされた特定のディレクトリをGlusterFSデーモンによって公開する(blickと呼ぶ)。クライアントはblickを束ねてvolumeとしてマウントすることができる。中央サーバーがないのがGlusterFSの特徴だ。

CephやGFSと比べかなりお手軽に使えそうに見えるGlusterFSだが、実際には意外と厳しい。それは、blickの容量をみずにファイルベースで振り分けていくこと、GlusterFSのレプリケーションはblickを組みとして複製するものであることによる。このことから、実質的にはblickはすべて同一容量でなくてはならない。しかも、blickの追加はRAID化している数をunitとして行わなくてはいけない。例えばstriped replicated volumeだとしたら、4 blicksが追加単位となるのだ。ディスク単位のblickにしても4台のディスク、コンピュータ単位だと4台のコンピュータだ!

また、このような技術はノードの停止は「障害」であるため、HAの理屈に基づき稼働停止が許されなくなる。電気代で考えても厳しいし、デスクトップユースでの無停止はそもそも難しい。結構よく見えたのだが、GlusterFS適用はかなり難しいように見えた。

ただし、適用方法はある。それは、「そもそも2組のストレージにしてしまい、2 blicks GlusterFS volumeにする」という方法だ。例えばiSCSI+LVMなどで複数のコンピュータノードからなるひとつのファイルシステムを編成し、それをマウントし、それをblickにすれば良い。そうすればコンピュータを2組に分けることができ、片方の組のコンピュータが停止しても全体はダウンしない。ストレージ追加はLVMなどの単位で行えるためかなり柔軟だ。容量の問題は、単に合計容量が小さいほうの組を上限としてそれを越えないように運用する、という制約があるだけだ。

lsyncd

だが、やはりこのようなHA技術は少々重い。それであれば少なくともデスクトップは使う側にしてデスクトップにストレージをもたせるのはやめるべきだ。

任意に停止しゆるい同期を行えれば良い。つまり、「手動で同期サービスを開始・停止し、ファイル更新時に反映してくれれば良い」という考えだ。可用性については、短時間の停止なら十分許容できる。

原始的には定期的にrsyncを回す方法もあるが、せめてファイル更新を監視したい。別にそれをスクリプトにしてもいいのだが、ionotifyというLinuxの機能があるのだから、それを活かしたいもの。そこで「ファイル変更を監視して同期する」というものを探したところ(正確には「なんて名前だっけ」だった)、lsyncdが見つかった。

lsyncdはファイル同期デーモンだが、実際にはミラーリングを行う機能はなく、rsyncなどをバックエンドとして使う。つまり、lsysncdはionotifyによってファイル更新を受け取り、それをトリガーとしてrsyncなどを起動するデーモンだ。

デスクトップレベルではこれが順当なところではないだろうか。台数が増えるとオンオフも困難になるので普通にHAストレージでいいのかもしれないが。

台数が少ないうちは普通にイーサネットケーブルでつなぎ、それをまとめて2つのストレージを編成すればいいのだが、台数が増えてきた場合、それぞれキーになるノード(片方はデスクトップ)をシングルにつなぎ、それぞれがストレージ用ハブを持っておくと良いだろう。構成手順は次のとおり

  • デスクトップは現在btrfsミラー
  • キーサーバーAを接続し、ZFSでストレージを束ねる
  • キーサーバーAにrsyncで全データをバックアップ
  • デスクトップのbtrfsのミラーをやめて構成しなおす
  • キーサーバーAからrsyncでデスクトップにデータを戻す
  • デスクトップとキーサーバーAにGbEインターフェイスを追加する
  • 追加されたGbEインターフェイスをハブに接続する
  • ストレージサーバーノードをGbEでストレージ側ハブに接続する
  • ストレージサーバーノードのディスクをAoEを用いてそれぞれのキーノードのブロックデバイスとしてみえるようにする
  • 追加されたストレージサーバーノードのディスク(AoE)をbtrfs/ZFSノードに加える
  • btrfs/ZFSをリバランス

10GbEに置き換えるところまで考えればかなりの規模までこれでいけるように思う。ただし、グループノードのいずれかがダウンすると障害発生なので、「故障率」は当然あがる。これはグリッドシステムでは常に起こることだ。

現在のシステムについて

私のコンピュータシステムについて質問があったのでまとめておく。

とはいえ、Linuxのシステムは全て説明するのは困難なので、概要に留める。

ハードウェア

ASRock FM2+Killer Extreame, AMD A10 7700K, 32GB RAM, 128GB SSD, 3TB HDDx5というのが主な構成。

外付けマルチドライブ、Canon MP630とEPSON GT-S630がある。プリンタ、スキャナはWindowsからは使用していない。

AUDIO I/OはAUDIO 4 DJ(セレクター経由でBOSE)、TASCAM US-366+FOSTEX AP05+VAIO付属スピーカー、アナログ出力のlogicool。US-366はLinuxでは扱えない。通常はClassic Proのヘッドフォン、製作時やリスニングではULTRASONE HFI-580を使用。

キーボードはオウルテックのメカニカルキーボード(青軸)、マウスはサンワサプライのBLUE-TECH有線、マウスパッドはELECOMの滑マウスパッド(大)。ELECOMのゲルハンドリストを使用。

机がL字型の自作となっている。

モニターは21.5インチのFullHDデュアル

システム

ディスクは以下のようになっている。

disk0(SSD)
Linuxシステム(/boot, /, /swap)
disk1,2,3,5
Btrfsボリューム
disk4
Windowsシステム(NTFS/UEFI)

Btrfsボリュームは2レッグミラー(RAID1+0相当)で運用される。サブボリュームを用いた運用で、サブボリュームの直下がEncfsディレクトリとなっており、~/.share.encfsにマウントされる。これをencfsで~/shareにマウントして使用する。

そもそもホームディレクトリの主要なディレクトリやファイルはシンボリックリンクとなっており、これをマウントしないとシステムをまともに使用することができない。システム自体もLUKSで暗号化されており、オフライン攻撃に対する強度を確保する。

Manjaro/WindowsともにUEFIでブートされる。ディスクは全てGPTとなっている。

Linux

ディストリビューション
Manjaro Linux JPを使用。0.8.10からのローリングアップグレード。
カーネル周り

Manjaro kernel 3.17を使用。AMD Catalystドライバで、オーバースキャンの設定をしてある。

ただし、この状態ではデスクトップ環境を問わず、HDMIモニター(セカンダリー)のカーソルがやがてバグる。

デスクトップ環境

XFce, Awesome, KDE, Cinnamonを用意。通常はKDEを使用。

KDEについてはSuper+Leftでウィンドウを左に寄せる、などエッジリサイズオプションを設定してある。

Conkyを使用しているが、KDEではRSSがうまく領域を確保されないことが多いので、あまり使っていない。

日本語環境

fcitx+Mozc-UT。

fontsは、Archで用意されている日本語フォントはだいたい入っている。

インターネット

ウェブブラウザはFirefox latest(binから入れたもの。スクリプト起動)とMaxthon, opera developerを使用。

メールはMaildeliver(自作スクリプト)でチェック、振り分け、フィルタリング、通知などを行い、Claws Mailで読む/出す。通知はデフォルトの通り、SOXとNotify Sendを使用。

TwitterはMikutter(Git)を使用。2chはJD(AUR)を使用。

その他、Skype+Sype Call Recorderを使用。

マルチメディア

半自動でCDをflacとOgg Vorbisに取り込むようになっており、Amarokで音楽コレクションを再生。

PDAPにはスクリプトを用いてOgg Vorbisを転送。Ogg VorbisはV192kbps。

ビデオはVLC/SMPlayer。

音声についてはPulseAudio経由で、出力デバイスはアナログオーディオ、HDMI、そしてNI AUDIO4 DJがあるが、設定によりAUDIO 4DJから音楽のみ出すようにしている。これはPulseAudioで設定してある。現在、Audio 4 DJから鳴るのはAmarokとSMPlyer。

画像は通常はGwenviewだが、Thunar+ViwniorやRistrettoも使用。

画像は投稿時などの変換はImageMagick。その他、GIMPとInkscape。

開発

PDocはmedit、コードはKate、プレーンテキストはTeaを使用。

バージョン管理はGitで、サイトのテキストもGitで管理、大部分はリモートGitを使用している。

リモートGitはCodebreak;, GitHubが主。

開発言語はRubyとZsh

シェル
XFce4 TerminalとZshを使用。Zshはmomongaをベースに拡張したrcで使用している。EXTENDED_GLOBは常にON。

Windows

デスクトップ

外観はU-7imate Final Version for Windows7, MacType, tronnixカーソルテーマを使用。

ランチャーはLaunchy。Rain Meterも控えめに使用。フォントは源柔フォント, 源真フォント, Rounded M+, Noto Sans Japanese, Ricty。

ユーティリティ
  • GeekUninstall
  • PeaZip
ファイラ
  • As/R
  • Hina File Master
日本語入力環境
Google日本語入力
マルチメディア
XnView
音楽制作環境
  • SONAR X3 PRODUCER
  • FL STUDIO Signature Bundle
  • KOMPLETE 9 ULTIMATE
  • Cabuse 6 LE
インターネット
ウェブブラウザ
  • Cyberfox AMD64bit
  • Sleipnir
メール
Oepra Mail
エディタ
  • Uneditor
  • VXEditor
セキュリティ
  • ZoneAlarm Free Firewall
  • Avast! AntiVirus Free

音楽制作環境なので、基本的に余計なものは入れないようにしている。

Windowsでウェブブラウジングを楽しむようなことはない。メールもメインアカウントのIMAPアクセスだけだ。だが、ブラウザは調べ物したりSoundCloudにアクセスしたりで必要となる。

パフォーマンス

Linuxでの並列作業や、WindowsでのDTMで使われているこのコンピュータのパフォーマンスについて述べる。

Linuxにおいて10000プロセスをforkして行う作業は、ほぼ問題ない。が、GUIはフリーズしたり、ひどい遅延を起こす。どちらかというと、fork時が問題になるようだ。ちなみに、Nepomukでシステムが使えなくなるまでには26万プロセスがforkされていたと記憶している。

おおよそ並列作業のために見境なくforkしても問題にはなりにくい。ただし、gccなどでは、やはり多くても12スレッドがいいようだ。並列性は、残念ながらあまり高くない。やはりこの作業ではコア数が必要となるので、FX-8が欲しいな、と思う。

全体にはCPUがボトルネックになっている。システムはSSDからロードされているため、ストレージ性能はそれなりにある。ネットワークもGbEでそれなりの帯域がある。RAMはKDEでも2GBもあればロードできるため、実際は8GBを越えることは稀だ。

しかし、ソフトの起動時に待たされる、特にKDEの起動が遅いことについては、やはりCPUがひっかかっているようだ。これはGIMPやLibreOfficeの待ち時間についても同様。KDEでもひっかかりが生じることがあり、明確にどこでということは読めないのだが、どうもCPUらしい。KDEは明らかにXFceのようにはさくさく動かない。リソースに常に余裕があれば、体感的な速度にはそれほど差がでないはずなので、常にではないが動きが悪いと感じるということはKDEに対して余裕がないのだろう。

ちなみに、パイプでのXZなどCPU中心となるものに関しても結構遅いと感じられる。コンパイルも意外と待つ。「すごく速い!」という印象はない。

IOスピードは、まぁ、この程度だろう。RAMも十分なのだが、それでももう少しあると快適になるシーンというのはある。バッファで使いきってしまうことは結構あるので、その時にはもっとメモリーがあればIO待ちの時間が減る。また、tmpfsに置けるファイルも増えるだろう。とはいえ、64GB化はエクスペリエンスの向上は乏しいだろう。

WindowsのDTMにおいては、ストレージスピード、RAM共に完全に余裕である。ストレージスピードが足りないようならば、ネットワークストレージのRAID0でさらなる高速化を準備していたが、その必要はなかった。

RAMは、Windowsでは逼迫したことがない。WindowsはRAMの使い方が下手だ、ということもあるが。

16トラックのシンセに20本のプラグインエフェクトを入れてもRAMには十分な余裕があったが、問題はCPUだ。上限に張り付くようなことはないのだが、US-366でlowest latencyにしていると、3トラック目あたりからノイズが乗ってくる。DTM作業をストレスなく行うには、かなりパワーが足りない印象だ。

AMP A APUは、クロック周波数がブースト時のものになっているので、その最大周波数で動いてくれるわけではない、というのが結構痛い。見ていると、ひとつのコアが60%くらいになるとノイズが乗り始める。この場合、他のコアは40%程度の使用率となっている。

Highest latencyにしてもノイズが除去できないこともある。結局、モアCPUパワー!な状態だ。

音楽制作においては、比較的低レベルでの動作が多いためか、どうもハードウェア的にインテルのほうがいいことが多いように思う。性能は同じでも、うまく動いてくれる気がする。一方、LinuxではFX 8がとても気になる。

現状、DTMではコアよりパワー、一方Linuxではパワーよりコアである感じがするのだが、まぁこれだけCPUの話ばかりになってしまうほど、CPUが遅い!

ちなみに、CPUについでパワーが足りないのは、ゲームなどしていないにもかかわらず、グラフィックだったりする。Windowsではもたつくというほどではないが、それでもYouTubeなどでは「んっ」と思う時がある。デュアルディスプレイの負荷が厳しいのかもしれないが、安定性も足りなかったりする。Windowsでもだ。

一応、この構成でもFHDx2+4kが可能なようではあるが、相当もっさりしそうだ。

クリエイティブな環境のためには、もっとCPUとGPUが必要だ、という結論に達した。

なおストレージ容量だが、現在はだいたい1.3TB。一時2.7TBまで行っていた。ネットワークが50Mbps程度しか出ていない(しかも、down率が10%を越える)ので増加は抑えめだが、本来限界まで簡単に行くとは思う。btrfsでいくらでもふやせるのはいいのだが、バックアップが難しくなっていくのは難点である。

btrfs, その他Manjaroのセッティング

btrfs

先日のトラブルを乗り越えてbtrfsの作業を完了。

今回は開いている/dev/sdb1をまずaddし、そして/dev/sdd2をdelete、/dev/sddをblastして/dev/sdd1をadd、というように繰り返していき、これまで/dev/sdd2, /dev/sde2, /dev/sdf2という構成だったところを、/dev/sdb1, /dev/sdd1, /dev/sde1, /dev/sdf1という構成に変更した。これにより、2TBx3だった3TB RAID1ボリュームは、3TBx4の6TB RAID1ボリュームへと倍増した。この増強により、データ格納もだいぶ安心できる状態になったと言っていいだろう。なお、このあとさらにbtrfs filesystem balance /homeしたあと、念の為btrfs scrub start /homeしておいた。

balanceをwatch -n 15 btrfs filesystem show /homeしているとかなりおもしろいことがわかる。バラバラにバランスをとるように移動していくのだが、100GBあたりでsdbとsdd、sdeとsdfの容量が同じになり、sdbとsddが同時に減少、sdeとsdfが同時に増加する。つまり、奇数の不均一な容量のディスクが使われている状況では、どこにどうデータがはいっているかというのは入り乱れているのだが、4台でバランスすると、sdbとsdd、sdeとsdfをそれぞれミラーした構成にしたことになる。btrfsはそのようにする必要はないが、可能ならそうしようとする、ということだろう。

LVMの場合、リバランスはできないし、ZFSでも容量が一定でない奇数のディスクをミラーする、ということ自体ができない。このミラーリングの器用さはbtrfsの大きな魅力だ。対障害性も結構高い。ただ、機能面で安定しない部分があるようだ。普通に使う分には十分安定していると思うが、何かの操作で障害が起きる場合がある。現状、まだバックアップはしておいたほうがよさそうだ。クラウドストレージのほうがいいかもしれないが、TB単位のデータをバックアップすると転送に時間がかかりすぎるだろう。ちなみに、当家のFTTH回線の速度は、下りで300kbps、上りは50kbps程度である。ナロードバンドというやつだ。しかも、何時間も接続できなかったりする。

Claws mail or Sylpheed

Sylpheedから派生したClaws Mailだが、見た目かなり似ている。何が違うのかよくわからなかったりする。

もともとはClaws Mailは外部MDAについて新規フォルダを検索すれば自動でサマリを更新してくれたのだが、設定をいじってもフォルダはみつけるがメッセージをみつけない(設定をいじらないとフォルダもみつけない)だが、再構築すると時間がかかるし、しかもClaws Mailは再構築するとフォルダを最後にもっていってしまい、ローカルフォルダが他にもあるとデフォルトのsentやdraftフォルダは最初にあるものが使われてしまう。

そこでSylpheedを使ってみたのだが、「次へ」でうまく拾ってくれなかったり、フォルダを移動する時の確認を消せない、そもそも新規フォルダを探すことができない、など結構不便。

機能の違いは、設定メニューがまるで違うことから感じるところもある。細かなところだが、色々違う。好みによるだろうが、Claws MailのほうがSylpheedよりも用意されている可能性が高いので、Claws Mailを使っているほうが移行性が高いのかな、という気はする。

MIDI on Manjaro/Arch Linux

結局一番簡単なのは、Timidity++とTimidity++ Freepatsをインストールする。そして/etc/timidity++/timidity.cfg

dir /usr/share/timidity/freepats
source /etc/timidity++/freepats/freepats.cfg

あとはtimidity -iAするか、systemctl start timidity.serviceして、aplaymidi --port 128:0 fileするなり、もしくはtimidity -in fileするなり、あるいはtimidity -igするなりで演奏できる。

Fluidsynth+FluidR3も試したが、かなりノイズが乗る上に、音源の質もあまりよくない。Freepatsはそれなりに聞ける。これはほぼArch Linux wikiのままだ。

FluidR3の音はひどいが、AURにはTitaniumとUnisonも存在。どちらかというと、Unisonのほうが音が良いが、相性は楽曲によるので一概には言えない。TitaniumまたはUnisonならば、曲によってはFreepatsよりもよさそうだ。

XFce4 on Manjaro Linux

カーソルが正常に表示されるようになったことについてだが、おそらくはXFce Theme Managerを使うとXFce起動時にXFceのX設定を読み込むため、一度画面がリセットされる。これによってカーソルが正常に表示されるようになったのだろあ。

ちなみに、カーソルテーマはLCD-Toxicにしている。3次元的である上に透過色で、しかも3D的に滑らかなアニメーションを見せる、こんなことできたんだというようなカーソルテーマだ。

Conky

Conkyを導入しセットアップ。ネットからとってきた.conkyrcをベースにカスタムしてみた。

フォントはMgen+ 2cp, Garnet, Dejevu Sans Mono, Promenadeを要求するので注意されたい。

## General
background yes
disable_auto_reload true
update_interval 5.0
#update_interval_on_battery 10.0
total_run_times 0
double_buffer yes
text_buffer_size 8192

## Window
## Window
own_window yes
#own_window_type desktop
#own_window_colour black
#own_window_argb_visual true
#own_window_argb_value 100
own_window_type override
own_window_transparent yes
gap_x 1550
gap_y 20
minimum_size 350 5
maximum_width 350

## Behavior
alignment top_right
use_spacer none
format_human_readable yes
short_units no
show_graph_range no
show_graph_scale no
draw_graph_borders no
cpu_avg_samples 2
net_avg_samples 2
diskio_avg_samples 2
top_cpu_separate false
top_name_width 25
no_buffers no

## Text/Font Settings
override_utf8_locale yes
use_xft yes
xftfont Garnet:size=8
xftalpha 1.0
uppercase no

## Border/Shade/Outline
draw_borders no
#border_width 1
#stippled_borders 8
draw_shades no
default_shade_color black
draw_outline yes
default_outline_color 40b0ff

## Color
default_color white
# Title
color1 0f3074
# Bar
color2 2d56ab
# Top Title
color3 0f3074
# Top 1
color4 fbff8a
#color5
#color6
#color7
#color8
#color9

## Template
# CPU Graph
template0 ${cpugraph cpu\1 \2,\3 40b0ff 2d56ab 100 -t}${offset -\3} CPU\1: ${cpu cpu\1}%
# CPU Top <indent1> <indent2> <indent3> <indent4>
template1 ${top name \1}${goto \2}${top pid \1}${goto \3}${top cpu \1}${goto \4}${top mem \1}${goto \5}${top io_perc \1}
# Memory Top <indent1> <indent2> <indent3> <indent4>
template2 ${top_mem name \1}${goto \2}${top_mem pid \1}${goto \3}${top_mem mem_vsize \1}${goto \4}${top_mem mem_res \1}${goto \5}${top_mem mem \1}
# Disk I/O Graph
template3 ${diskiograph_\2 \1 \3,\4 40b0ff 2d56ab 10000 -t}${offset -\4} /dev/\1 \2: ${diskio_\2 \1}
# Disk I/O Top <indent1> <indent2> <indent3> <indent4>
template4 ${top_io name \1}${goto \2}${top_io pid \1}${goto \3}${top_io io_read \1}${goto \4}${top_io io_write \1}${goto \5}${top_io io_perc \1}
# Network Graph <ethN>
template5 ${\2speedgraph \1 \3,\4 40b0ff 2d56ab 1000 -t}${offset -\4} \1 \2: ${\2speed \1}
# Disk Bar template6 \1 ${goto 55} ${fs_used \2}/${fs_size \2} ${goto 150} ${color2} ${fs_bar 6 \2}
# Load Average Graph
template7 ${loadgraph \1,\2 40b0ff 2d56ab 4 -t}${offset -\2} Load Average: ${loadavg}${alignr}Processes: ${running_processes}/${processes}
# Top 5 <template num> <indent1> <indent2> <indent3> <indent4>
template8 ${color4} ${template\1 1 \2 \3 \4 \5}\n${color} ${template\1 2 \2 \3 \4 \5}\n${color} ${template\1 3 \2 \3 \4 \5}\n${color} ${template\1 4 \2 \3 \4 \5}\n${color} ${template\1 5 \2 \3 \4 \5}

TEXT
${color1}${font Promenade:style=Regular:size=9}System ${font}${hr}
${color } ${nodename} - ${sysname} ${kernel} on ${machine}
${color } Uptime: ${uptime}
${color1}${font Promenade:style=Regular:size=9}${voffset 3}Processor ${font}${hr}
#${color } CPU ${freq_g 0}GHz: ${color2}${cpubar cpu0}
${color } CPU ${freq_g 1}GHz: ${color2}${cpubar cpu1}
${color } CPU ${freq_g 2}GHz: ${color2}${cpubar cpu2}
${color } CPU ${freq_g 3}GHz: ${color2}${cpubar cpu3}
${color } CPU ${freq_g 4}GHz: ${color2}${cpubar cpu4}
${color }${template0 0 20 325}${voffset -5}
${color }${template7 20 325}${voffset -5}
${color3} Command${goto 150}PID${goto 200}%CPU${goto 250}%MEM${goto 300}%I/O
${color }${template8 1 150 200 250 300}
${color1}${font Promenade:style=Regular:size=9}${voffset 3}Memory ${font}${hr}
${color } RAM: ${mem}/${memmax} - ${memperc}%${goto 190}${color2}${membar}
${color } Swap: ${swap}/${swapmax} - ${swapperc}%${goto 190}${color2}${swapbar}
${color } B/C: ${buffers}/${cached}
${color3} Command${goto 150}PID${goto 200}VIRT${goto 250}RES${goto 300}%MEM
${color }${template8 2 150 200 250 300}
${color1}${font Promenade:style=Regular:size=9}${voffset 3}Disk${font}${hr}
${color }${goto 10}${template3 sda Read 20 166}${goto 175}${template3 sda Write 20 166}${voffset -20}
${color }${goto 10}${template3 sdb Read 20 166}${goto 175}${template3 sdb Write 20 166}${voffset -10}
${color3} Command${goto 150}PID${goto 200}Read${goto 250}Write${goto 300}%I/O
${color }${template8 4 150 200 250 300}
${color }
${color } ${template6 / /}
${color } ${template6 /tmp /tmp}
${color1}${font Promenade:style=Regular:size=9}${voffset 3}Network ${font}${hr}
${if_up enp4s0}${color }${template5 enp4s0 Down 20 166}${goto 175}${template5 enp4s0 Up 20 166}${voffset -20}${endif}${if_up wlp0s16f0u1}
${color }${template5 wlp0s16f0u1 Down 20 166}${goto 175}${template5 wlp0s16f0u1 Up 20 166}${voffset -5}${endif}
${color1}${font Promenade:style=Regular:size=9}${voffset -5}Calendar ${font}${hr}
${color }${font DejaVu Sans Mono:style=Bold:size=7}${execi 1800 LANG=C cal -3}${font}
${color1}${font Promenade:style=Regular:size=9}${voffset -5}Yahoo News ${hr}${font}
${font Mgen+ 2cp:style=Medium:size=7}${rss http://headlines.yahoo.co.jp/rss/all-dom.xml 1 item_titles 10 }${font}

btrfsとの格闘

btrfs replace /dev/sdd2 /dev/sdb1 /homeしたら、システムが停止し、I/Oも停止。やむなく再起動したところ、案の定マウントできない。ちなみに、10.3%で、writeerrが1776あった。

理屈から言えばbtrfsはこのような場合でもデータを失ってはいないはずだ。なぜなら、btrfs replaceは新規デバイスにデータをコピーし、成功した場合にリファレンスを付け替える構造だからだ。

だが、現実はこのbtrfsファイルシステムにアクセスできない。1TB近いデータの損失は、バックアップをとってから結構重要なデータも増えており、致命的な状態だ。RAIDでカバーすることを基本としているだけに、ファイルシステム破損のダメージは大きい。

とりあえず、btrfsckしてみる。1200万ものエラーが発見された。だが、これによってマウントはマウント時にかなり待たされるものの、可能になった。ただし、失敗することもある。

それで再起動してみたが、やはりマウントできずコンソールに落ちる。btrfs device replace status /homeした上で、btrfs scrub start /homeしてみる。すぐにプロンプトは戻るが、btrfs scrub status /homeすると0secでabortされていることがわかる。明らかに異常な状態だ。

ファイルシステムをマウントすることができ(いつの間にかマウントを失っていることもあるが)、またファイルシステムにアクセスできるのだから、今のうちにデータをバックアップしておくべきだ。そう思い立ち、今までWindowsが入っていた(どのみちリカバリーのために消さなくてはいけない)ディスクをnukeし、XFSで再フォーマットした上でデータをコピーする。

構造として、/home/home/aki/shareにサブボリュームがマウントされているので、なかなかややこしい状態になっている。多分、btrfsのサブボリュームは、単にマスターボリューム以下にあるあるディレクトリをファイルシステムルートにみせかけているだけだと思うので、純粋にbtrfsのマスターボリュームをコピーすればいいのではないか、という気がするのだが、それでうまくいかなくかった時が怖いので、素直にサブボリュームをマウントした上でそれをコピーする。

最初のほうはかなりひっかかっていたが、やがてスムーズに動くようになった。もしかしてアクセスしながら自動的にbtrfsが修復していったということだろうか?(私のbtrfsは、2レッグミラーになっている)

そして完了後に別のサブボリュームをマウント、すぐに反応してくれる。異常な印象は受けない。ためしにscrubしてみると、なんと正常にスタートした!/homeも一応バックアップを取った上で、再起動してみると、正常にブートした。しかもそれだけではない。かねてから正常に動いていなかった「display1で正常にポインターカーソルが表示されない」「SEが出ない」も解消されている!一体なぜだろう。

とりあえずscrubした上で途中になっていたファイルシステムのメンテナンスを行い、そしてバックアップからの差分が膨らまないうちにと、今度はbtrfs device add /dev/sdb1; btrfs device del /dev/sdd2作戦。addは一瞬で終わる。一方、delは時間がかかる。これは正しい。addは本来ファイルシステムを作るだけだし、btrfsはマークをつけておくだけだったように思う。一方、delはデータを他のデバイスにコピーしてからリファレンスを消すので、そのデバイスのデータ分時間がかかる。まだ途中だが、今のところ支障はない。

ちなみに、そもそもなんでデバイス移行しようとしているかというと、LVM用に確保してあった領域を削除し、全域をbtrfsに割り当てるためである。

btrfsの不完全さのせいで生じたトラブルだが、btrfsの冗長性、可用性に救われた形になる。どういう反応をすれば良いのやら…