最近の変更サイトマップ

Samba 4.6のファイルコピーがCPU 100%近く使い超絶遅い件

最初に結論

この状態に悩まされてる人は何よりも答えが欲しいだろうから、最初に結論を書いておくと、smb.confでcase sensitive = yesと設定すると多分直る。直下に大量のファイルを抱えたフォルダをコピーするとsmbdがCPUを100%近く消費し、コピー速度が極めて遅くなる現象ならほぼ間違いなく直る。

「”大量のファイル”ってどれくらい?」かというと、サーバマシンの性能にもよるがCore i系なら概ね1万ファイル、流行りのラズパイとかだと恐らくもっと少数、単純なクロック比で1/2、実性能はもっと劣るだろうから更に半分で2500ファイルくらい?。完全な当てずっぽうですけど。要はファイル名の比較のところがボトルネックになっているようなので、CPUのシングルスレッド性能に依存する。

次に御託

例によってNAS4Free 11.0.0.4 (4303)[FreeBSD 11.0-RELEASE-p10/Samba 4.6.4]でNASをでっち上げたのだが、知人曰く、今までのNASに較べてファイルコピーが遅い、と。マシンのスペック的にはXeon E5-2620v3, メモリ8GB, 1GbE×2のLAGで、ストレージも3.5インチHDD2本でRAID-1のペアを3ペアでRAID10なので問題が出るとは考えにくい。実際、シェルでのシーケンシャルライトでは500MB/sくらい出てる。

様々なサイズのテストファイルを試してみるも、至って正常な速度が出るし、むしろ他のNASよりも速いくらい。ところが、知人が遅いというファイル群で試してみると、たしかに遅い。小さなファイルが多いためワイヤーレートには程遠いが、それでも初速は10MB/s超えてるのに、あれよあれよと速度が落ちて仕舞には100kB/sを切ってしまう。そして何故かsmbdがCPUを100%近く持っていく尋常ならざる状態に。Pen!!!時代のGbEじゃあるまいし、たかがファイル転送でCPU 100%ってどんだけー。

問題のファイル群をシェルでcpすると30MB/s出てるので、やっぱりマシンに問題はなさげ。さらに、NAS4Free 9 [FreeBSD 9.3-RELEASE-p14/Samba 4.1.18]搭載の別マシン(Xeon E3-1225v2/16GB/3.5“ HDD 6台でRAID-Z2なので性能は必要十分)で試すと、安定して数MB/sは出るし、CPU負荷も常識的な範囲。となれば、問題なのはSambaっぽい…?

ここまで絞り込んでからが大変だった。

情報がないない。マシンの省電力設定を切ってみたり、Sambaが速くなる各種おまじないを試してみたり、SMBのプロトコルバージョンを変えたり、LAGを解除してみたり、etc…するも効果なし。ググりにググって、ようやくFreeNASのフォーラムでcase sensitiveが原因じゃねという投稿を見つけた次第。

早速case sensitive = yesにして試してみたら、効果てきめん。転送速度もCPU負荷も劇的に改善された(テストファイルが32kBなので速度がそんなに出てないのは仕方ない)。論より証拠ってなもんで、比較画像貼っておきますね。

 Samba 4.6.4のcase sensitive設定によるファイルコピー速度の比較

その後、Sambaのドキュメントのcase sensitive設定のところを見たら、思いっきり「As a special case for directories with large numbers of files, if the case options are set as follows, “case sensitive = yes”, (後略)」と書いてあったでござる(´・ω・`)。

大文字小文字の変換処理ごときで遅くなるなよ!と思わなくもないが、ファイルの新規作成時はディレクトリ内の既存ファイル名と被ってないか総当りでチェックしているようなので、何も考えずに実装すれば計算量はO(n2)、ファイル数が増えると爆発的に比較数が増えるんすなぁ…。にしてもですよ、デフォルト設定のcase sensitive = autoは以前のバージョンから変わってないわけで、いきなり遅くなるなんてチョーひどくなーい?

case sensitive設定を変えるとWindowsからのアクセスに支障がでないか心配なところだが(なんたってWindowsは表面上は大文字小文字区別しませんからね!)、そこはエクスプローラが上手いこと取り計らってくれる模様。本当かどうかは知らない。

参考サイト

FreeBSD 11.1-RELEASE キタ―――(゚∀゚)――――!!

予定通りFreeBSD 11.1-RELEASEがリリースされた。めでたいめでたい。特定条件下の11.0RでVirtualBoxが動かない問題が直ってるハズなので、早速更新することにした。

基本はいつも通りfreebsd-updateするだけなのだが、現在の環境がFreeBSD 11.1-RC2の人は要注意。リリースアナウンスによれば、RC2でVirtualBoxを使ってる人はシステム更新の前にvirtualbox-ose-additionsを再インストールしないとカーネルパニックを起こすようだ。

うちは見事に該当してるので、手順に従う。

# pkg install -f virtualbox-ose-additions

これもリリースアナウンスに書いてあるが、念には念を入れ、vboxguestサービスを無効化しておく。経験的にVirtualBoxのカーネルモジュールとサービスはシステム更新時のハマりの原因になるので、必ず無効化することをオススメする。今まで何度地雷を踏み抜いたことか…(ヽ´ω`)

/etc/rc.conf
#vboxnet_enable="YES"
#vboxguest_enable="YES"
#vboxservice_enable="YES"

準備が出来たらいよいよfreebsd-updateだ。といっても、ここからはいつもの通り。

新しいシステムを取ってきて、

# freebsd-update -r 11.1-RELEASE upgrade
Looking up update.FreeBSD.org mirrors... 4 mirrors found.
Fetching metadata signature for 11.1-RC2 from update4.freebsd.org... done.
Fetching metadata index... done.
...

カーネルをインスコして、

# freebsd-update install
Installing updates...
Kernel updates have been installed.  Please reboot and run
"/usr/sbin/freebsd-update install" again to finish installing updates.

再起動して、

# reboot

ユーザーランドをインスコして、

# freebsd-update install
Installing updates... done.

再起動して、

# reboot

無事、FreeBSD 11.1-RELEASEの環境へ。

$ freebsd-version -ku
11.1-RELEASE
11.1-RELEASE

FreeBSD 11からfreebsd-bootパーティションが64KBじゃ足りなくなった件

タイトルの通りでござる(ヽ´ω`)

FreeBSD 11が入っているSSDの入れ替え作業でパーティションを切り直していた際、例によってブートコードを書き込もうとしたら空き容量がないと怒られた。

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada15
gpart: /dev/ada15p1: not enough space

パーティション構成は前のSSDからの丸コピーであるからして、FreeBSD 10から11に更新した時にブートコードの更新をしていなかった、ないし今回のようにエラーが出ていたもののスルーしてたって事になる。FreeBSD 11にしてから5ヶ月経つというのに今まで気付かなかった……。古いブートコードでよく起動できてたなっていう。

念のため調べてみた所、やはりFreeBSD 11.0-RELEASEで/boot/gptzfsbootの容量が87KiBに増え、64KBのパーティションでは物理的に収まらなくなったようだ。エラッタにも、次のような記載がしっかりとなされていた(ヽ´ω`)

[2016-10-21] The size of the GPT enabled ZFS boot blocks (/boot/gptzfsboot) has increased past 64K. Systems upgraded from older releases may experience a problem where the size of the existing “freebsd-boot” partition is too small to hold the new gptzfsboot. FreeBSD 11.0-RELEASE Errata

さて、これはどうしたもんかね…。まぁどうしたもこうしたもパーティションを拡大するしかないわけだが、ブートパーティションはディスクの先頭にあり、その直後にシステム&データパーティションが続いているので拡大の余地はないのだよ。このようなパーティション構成は極めて一般的だと思うし、とりわけFreeBSD 8/9時代にRootOnZFS環境を作って乗り継いできた人の殆どにとって頭の痛い問題なんじゃなかろうか。

ディスクの後方に空きがあるなら、そっちにfreebsd-bootパーティションに新設するってのが一番手っ取り早いかも?これはこれで凄い気持ち悪いのと、ブートローダの容量の壁(ディスクの先頭○GB以内に配置しないといけない系のやつ)にハマりそうな気がしなくもないが、2017年にもなって流石にもうないか?gpartのドキュメントによると、freebsd-bootパーティションは他のFreeBSD系パーティションの直前か直後に配置する必要があるそうなので、環境によっては完全に詰む可能性あり。

どうせ作り直すんだったらパーティションを超でっかくしたくなるが、最大545KBまでという制限もあるので要注意。起動時にfreebsd-bootパーティション全体がメモリに読み込まれるそうで、古のコンベンショナルメモリとの絡みから来る容量制限なのかしら?ゆとりの僕にはわかんないんです(・ω<)

これを機にUEFIブートに乗り換えるってのもありかなー。こっちはこっちでESPを確保しなければならないので、全く同じ問題を抱えてるわけですがね!

ZFSと雖も不意の電源断でデータが破損する事がある

ちょっと前に家鯖が絶不調で、3.5インチHDD×4台のzpoolにアクセスするとフリーズする現象に見舞われていた。そのフリーズたるや生半可なものではなく、電源ボタン長押しすら受け付けず、コンセントぶっこ抜いた上に暫く放置してからじゃないと電源すら入らないというレベル。

すわ、電源ユニットが死んだか!?と思い早速手配し交換すべくサーバを開腹したところ、電源ファン前のフィルタが埃で目詰まりしていた。不調だったのは単に埃のせいで廃熱がままならず、サーマルプロテクションが動いてただけなんじゃないか疑惑。ま、もう電源買っちゃったし交換しときましたがね…。

こんな感じで、HDD×4台のRAID-Zは比較的短期間のうちに5〜6度に渡る不意の電源断にさらされたわけだが、いくら堅牢なZFSとはいえ流石に耐えられなかったようで。回復不能なエラーが発生し、ファイルが1つお亡くなりになってしまった。

$ sudo zpool status -v
パスワード:
  pool: zdata
 state: ONLINE
status: One or more devices has experienced an error resulting in data
    corruption.  Applications may be affected.
action: Restore the file in question if possible.  Otherwise restore the
    entire pool from backup.
   see: http://illumos.org/msg/ZFS-8000-8A
  scan: scrub repaired 0 in 64h6m with 2 errors on Sun Mar  5 06:42:20 2017
config:

    NAME         STATE     READ WRITE CKSUM
    zdata        ONLINE       0     0     2
      raidz1-0   ONLINE       0     0     4
        ada5p1   ONLINE       0     0     0
        ada4p1   ONLINE       0     0     0
        ada3p1   ONLINE       0     0     0
        ada2p1   ONLINE       0     0     0
    logs
      mirror-1   ONLINE       0     0     0
        ada15p4  ONLINE       0     0     0
        ada11p4  ONLINE       0     0     0
    cache
      ada11p5    ONLINE       0     0     0

errors: Permanent errors have been detected in the following files:

        /zdata/path/to/broken_file.wmv

scrub中にも電源断が起こったため、このような残念な結果になってしまったのだろう。初回scrubが出来ていれば、恐らくデータが壊れることはなかったと思う(個人的な経験に基づく推測)。

幸いにして死んだファイルはあ〜ん♡な動画だったため大した影響はなかったが、バックアップの重要性を考えさせられる良い機会となった。……とは言ったものの、個人でTBレベルの現実的なバックアップって難しいんだよなぁ。HDDにせよLTOにせよ、その都度引っ張り出してくるようでは面倒になってその内バックアップしなくなるのは目に見えてるし、かといって繋ぎっぱなしじゃバックアップの意味が薄れるし。流行のクラウドは容量も然る事ながら、自分の管理外の場所にデータを置くってのが信用できないし。

あ〜ん♡データの維持もなかなか大変である。

portmasterでPHP 5.5をモジュール含め一括でPHP 7.1に更新する

家鯖のPHPを5.5から7.1に更新した。

バージョン毎にportsが分かれているソフトを更新するときは、portmasterの-oオプションを使ってportmaster -o 置き換えるports(新バージョン) 置き換えられるports(旧バージョン)とする。そうしないと「php55-5.5.38 conflits with php71-7.1.1 (installs files into same place)」という具合に怒られる。

# sudo portmaster -o lang/php71 php56

PHPの場合、付随するモジュールも更新する必要があり、基本的には同じ方法で行う。しかし、1つずつportmaster -oしなきゃならなくて地味に面倒なんすよね(´・ω・`)。いい方法がないものかとネットを彷徨っていたら(この時間で手作業で更新できた説)、Stack Overflowに素敵な回答を発見。元のスクリプトだとdistfile削除プロンプトの入力待ちが正しく処理できなかったため、ちょっと改造させて貰った。

$ awk -vPATTERN="55" -vREPLACEMENT="71" \
'BEGIN { while (("pkg query -x %o \"/(mod_)?php" PATTERN "(-|$)\"" \
| getline name) > 0) { oldname = name; sub(PATTERN, REPLACEMENT, name); print "ALWAYS_SCRUB_DISTFILES=dopt portmaster --no-confirm -o " name " " oldname } }' \
| sudo sh

統廃合などで必ずしもモジュールが1対1で対応しなかったり、php-extensionパッケージは上手く扱えなかったりで、エラーなしで一発更新という訳にはいかないのが玉に瑕。でもこのスクリプトで更新作業はかなり楽になるハズ。PATTERNREPLACEMENTはお使いの環境に応じて書き換えてね(ゝω・)v

参考サイト

start.txt · 最終更新: 2016-05-07 17:46 by decomo
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0