FreeBSD 10.1-RELEASEな自宅ファイルサーバからMacにファイルをコピーすると「予期しないエラーが起きたため、操作を完了できません(エラーコード -50)。」が発生してコピーに失敗する現象に長らく苦しめられていた。経験的にファイルサイズが大きいほど発生確率が高く、数百MBくらいまでのファイルなら問題ないが、2GBを超えるとまずアウトっていう。鯖→Macの場合AFP(Netatalk 3.1.7)でもCIFS(Samba 4.2.5)でも発生し、鯖→Windowsの場合は言うまでもなくCIFSしか使えないが、所々詰まりながらも一応成功するといった具合。
失敗時はNetatalkのログに「Cannot allocate memory」が必ず記録されている。発生場所は大体{fork.c:913} (error:AFPDaemon): afp_read
か{dsi_stream.c:424} (error:DSI): dsi_stream_read_file
のどっちか。メモリたんねーと言われましても、32GB積んでるtop
で見ても余裕のよっちゃんイカで数GBレベルで残ってますし…。もう全くわけがわからないよ!本格的に原因を探ろうとsshで各種情報をモニタリングしながらコピーしたら、今度はsshdまでCannot allocate memory吐いて接続切れるし……。
ドライバの不具合?NIC/L2SW由来の不具合??もしかしてケーブルが腐ってる???などなど、疑心暗鬼ロードを爆走していたが、ようやく、ついに!遂に!!原因がわかったッ!!!!
犯人はヤス何とVirtualBox。 VirtualBox実行中はnetgraph関連のメモリが不足しやすく?なるっぽい。ここやここで同症状が報告されており、/boot/loader.conf
にnet.graph.maxdata=65536
を追加すればおkと書いてあった。
このカーネルパラメータはnetgraphのデータキューの最大確保数を表すものらしい。同様に非データ用のnet.graph.maxalloc
なんてのもある。それぞれ/usr/src/sys/netgraph/ng_base.c
で定義されていて、コメントが若干怖いことが書いてあった。
static int maxalloc = 4096;/* limit the damage of a leak */ static int maxdata = 512; /* limit the damage of a DoS */
下手に大きくすると問題発生時に被害が拡大しそうな雰囲気。ま、外部公開してなきゃそんなに気にしなくてもいいだろうけど。
ついでにdmesg
にLimiting open port RST response from 208 to 200 packets/sec.
なるログも出ていたので、/etc/sysctl.conf
に以下を追加。
net.inet.icmp.icmplim=2000
肝心のloader.conf
も一応。
net.graph.maxdata=65536 net.graph.maxalloc=65536
上記設定で1~6GBほどのファイルを100GB分くらいコピーしてみたら、何の問題もなく完了した。普通に動くって素晴らしい。