ZFS send/recvとnetcatを使ってネットワーク越しにZFSのデータを移行する

今回のサーバ更新では、ZFSからZFSへデータ移行をする必要があった。一般的にはrsyncやtarを使うんだろうけど、せっかくなのでZFSの機能を使って移行してみたら、かなり高速で快適だったのでメモ。
ZFSには、複製を作成するためのsend/recvという機能が用意されている。標準入出力を使ってデータをやりとりできるので、netcatを使ってネットワーク越しにつなぐことで、データを移行する。
まずは新サーバでの操作。netcatでネットワークからの入力を待ち受けて、標準出力へリダイレクトし、zfs recvで受信する。ポート番号は適当に選択する。受信するpoolはあらかじめ作成しておくこと。

# nc -l -p ポート番号 -w 120 | zfs recv -v pool/export@snapshot

次は、旧サーバでの操作。zfs sendはスナップショットしか送信できないので、スナップショットを作ってsendする。

# zfs snapshot pool/export@snapshot
# zfs send pool/export@snapshot | nc 宛先IPアドレス ポート番号

あとは待つだけ。rsyncやtarに比べて、ファイルシステムを直に扱うためオーバーヘッドが少ない、何も考えなくてもファイル作成時刻などのメタデータがそのままコピーできる、旧サーバのsnapshotも移行しようと思えば移行できる、などいいことだらけなので、今後もサーバ更新の際はzfs send/recvを使うようにしよう。

追記

netcatは転送するデータを暗号化せず平文で流すので、家庭内LANなどの覗き見されないネットワーク環境で使うこと。
覗き見の可能性があるなら、素直にsshを使うのがお手軽。

FreeBSD 9.1-RELEASEでSSDのTRIM命令を有効にする

新しい自宅サーバでは、起動ドライブにSSDを使ってみた。SSDはHDDといろいろと違うところがあるけど、そのうちの一つにTRIM命令がある。
SSDは、HDDと違っていわゆる上書きができないため、上書きする場合は、書き込まれているデータをいったん待避して、その領域をまっさらにしてから書き戻すことになる。ところで、一般的なファイルシステムでは、ファイルを削除した場合、管理データだけ削除してディスク上のデータはそのまま残しておく作りになっていることが多い。すると、削除したファイルが使っていた領域は、OSではすでに不要になっているのに、SSDとしては不要かどうか分からないので、上書きの際にいちいち待避することになる。
OSがファイルを削除した際に、SSDに対して「この領域はもう使いませんよ」と教えてあげることができたら、このような非効率は発生しない。そのための命令がTRIM命令というわけ。
FreeBSDでもしばらく前からTRIM命令をサポートしてる。ただし、デフォルトでは無効になっているので、必要なファイルシステムに対してtunefsの-tオプションを使って有効にしてやる必要がある。

     -t enable | disable
             Turn on/off the TRIM enable flag.  If enabled, and if the under‐
             lying device supports the BIO_DELETE command, the file system
             will send a delete request to the underlying device for each
             freed block.  The trim enable flag is typically set when the
             underlying device uses flash-memory as the device can use the
             delete command to pre-zero or at least avoid copying blocks that
             have been deleted.

実際にはこんな感じ。マウントされていると変更できないので、memstickとかLiveCDを使って起動して変更すべし。

# tunefs -t enable /dev/ada4p2

有効になっているかどうかは、dumpfsを使って確認できる。flagsにtrimが入っていれば有効。

# dumpfs /dev/ada4p2
省略
flags   soft-updates+journal trim 
省略

ついでに/etc/fstabでnoatimeを指定して、atimeを無効にしておいた。これで書き込みが少なくなって、SSDの寿命が延びるはず。

HP ProLiant MicroServerのFreeBSD 9.1-RELEASE dmesg

参考に、HP ProLiant MicroServerをFreeBSD 9.1-RELEASEで動かしたときのdmesgを載せておく。
全てのデバイスは適切に認識されて、動作してる。NICはbgeで、options=c019bとだいたい対応してる。
SSDを接続したSATAポートは、光学ドライブ用のため150MB/sで動作してるけど、体感的に問題ないのでそのままにしてる。非公式BIOSを書き込めば、300MB/s動作させられるらしい。

Copyright (c) 1992-2012 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
	The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 9.1-RELEASE #0 r243825: Tue Dec  4 09:23:10 UTC 2012
    root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
CPU: AMD Turion(tm) II Neo N40L Dual-Core Processor (1497.55-MHz K8-class CPU)
  Origin = "AuthenticAMD"  Id = 0x100f63  Family = 10  Model = 6  Stepping = 3
  Features=0x178bfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,MMX,FXSR,SSE,SSE2,HTT>
  Features2=0x802009<SSE3,MON,CX16,POPCNT>
  AMD Features=0xee500800<SYSCALL,NX,MMX+,FFXSR,Page1GB,RDTSCP,LM,3DNow!+,3DNow!>
  AMD Features2=0x837ff<LAHF,CMP,SVM,ExtAPIC,CR8,ABM,SSE4A,MAS,Prefetch,OSVW,IBS,SKINIT,WDT,NodeId>
  TSC: P-state invariant
real memory  = 8589934592 (8192 MB)
avail memory = 8111689728 (7735 MB)
Event timer "LAPIC" quality 400
ACPI APIC Table: <HP     ProLiant>
FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs
FreeBSD/SMP: 1 package(s) x 2 core(s)
 cpu0 (BSP): APIC ID:  0
 cpu1 (AP): APIC ID:  1
ioapic0 <Version 2.1> irqs 0-23 on motherboard
kbd1 at kbdmux0
acpi0: <HP ProLiant> on motherboard
acpi0: Power Button (fixed)
acpi0: reservation of fee00000, 1000 (3) failed
acpi0: reservation of ffb80000, 80000 (3) failed
acpi0: reservation of fec10000, 20 (3) failed
acpi0: reservation of fed80000, 1000 (3) failed
acpi0: reservation of 0, a0000 (3) failed
acpi0: reservation of 100000, d7f00000 (3) failed
cpu0: <ACPI CPU> on acpi0
cpu1: <ACPI CPU> on acpi0
attimer0: <AT timer> port 0x40-0x43 irq 0 on acpi0
Timecounter "i8254" frequency 1193182 Hz quality 0
Event timer "i8254" frequency 1193182 Hz quality 100
atrtc0: <AT realtime clock> port 0x70-0x71 irq 8 on acpi0
Event timer "RTC" frequency 32768 Hz quality 0
hpet0: <High Precision Event Timer> iomem 0xfed00000-0xfed003ff on acpi0
Timecounter "HPET" frequency 14318180 Hz quality 950
Event timer "HPET" frequency 14318180 Hz quality 550
Event timer "HPET1" frequency 14318180 Hz quality 450
Timecounter "ACPI-safe" frequency 3579545 Hz quality 850
acpi_timer0: <32-bit timer at 3.579545MHz> port 0x808-0x80b on acpi0
pcib0: <ACPI Host-PCI bridge> port 0xcf8-0xcff on acpi0
pci0: <ACPI PCI bus> on pcib0
pcib1: <ACPI PCI-PCI bridge> at device 1.0 on pci0
pci1: <ACPI PCI bus> on pcib1
vgapci0: <VGA-compatible display> port 0xe000-0xe0ff mem 0xf0000000-0xf7ffffff,0xfe8f0000-0xfe8fffff,0xfe700000-0xfe7fffff irq 18 at device 5.0 on pci1
pcib2: <ACPI PCI-PCI bridge> irq 18 at device 6.0 on pci0
pci2: <ACPI PCI bus> on pcib2
bge0: <HP NC107i PCIe Gigabit Server Adapter, ASIC rev. 0x5784100> mem 0xfe9f0000-0xfe9fffff irq 18 at device 0.0 on pci2
bge0: CHIP ID 0x05784100; ASIC REV 0x5784; CHIP REV 0x57841; PCI-E
miibus0: <MII bus> on bge0
brgphy0: <BCM5784 10/100/1000baseT PHY> PHY 1 on miibus0
brgphy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseT, 1000baseT-master, 1000baseT-FDX, 1000baseT-FDX-master, auto, auto-flow
bge0: Ethernet address: XX:XX:XX:XX:XX:XX
ahci0: <ATI IXP700 AHCI SATA controller> port 0xd000-0xd007,0xc000-0xc003,0xb000-0xb007,0xa000-0xa003,0x9000-0x900f mem 0xfe6ffc00-0xfe6fffff irq 19 at device 17.0 on pci0
ahci0: AHCI v1.20 with 4 3Gbps ports, Port Multiplier supported
ahcich0: <AHCI channel> at channel 0 on ahci0
ahcich1: <AHCI channel> at channel 1 on ahci0
ahcich2: <AHCI channel> at channel 2 on ahci0
ahcich3: <AHCI channel> at channel 3 on ahci0
ohci0: <AMD SB7x0/SB8x0/SB9x0 USB controller> mem 0xfe6fe000-0xfe6fefff irq 18 at device 18.0 on pci0
usbus0 on ohci0
ehci0: <AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller> mem 0xfe6ff800-0xfe6ff8ff irq 17 at device 18.2 on pci0
usbus1: EHCI version 1.0
usbus1 on ehci0
ohci1: <AMD SB7x0/SB8x0/SB9x0 USB controller> mem 0xfe6fd000-0xfe6fdfff irq 18 at device 19.0 on pci0
usbus2 on ohci1
ehci1: <AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller> mem 0xfe6ff400-0xfe6ff4ff irq 17 at device 19.2 on pci0
usbus3: EHCI version 1.0
usbus3 on ehci1
pci0: <serial bus, SMBus> at device 20.0 (no driver attached)
atapci0: <ATI IXP700/800 UDMA133 controller> port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0xff00-0xff0f at device 20.1 on pci0
ata0: <ATA channel> at channel 0 on atapci0
ata1: <ATA channel> at channel 1 on atapci0
isab0: <PCI-ISA bridge> at device 20.3 on pci0
isa0: <ISA bus> on isab0
pcib3: <ACPI PCI-PCI bridge> at device 20.4 on pci0
pci3: <ACPI PCI bus> on pcib3
ohci2: <AMD SB7x0/SB8x0/SB9x0 USB controller> mem 0xfe6fc000-0xfe6fcfff irq 18 at device 22.0 on pci0
usbus4 on ohci2
ehci2: <AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller> mem 0xfe6ff000-0xfe6ff0ff irq 17 at device 22.2 on pci0
usbus5: EHCI version 1.0
usbus5 on ehci2
acpi_button0: <Power Button> on acpi0
sc0: <System console> at flags 0x100 on isa0
sc0: VGA <16 virtual consoles, flags=0x300>
vga0: <Generic ISA VGA> at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
ppc0: cannot reserve I/O port range
ctl: CAM Target Layer loaded
acpi_throttle0: <ACPI CPU Throttling> on cpu0
hwpstate0: <Cool`n'Quiet 2.0> on cpu0
Timecounters tick every 1.000 msec
usbus0: 12Mbps Full Speed USB v1.0
usbus1: 480Mbps High Speed USB v2.0
usbus2: 12Mbps Full Speed USB v1.0
usbus3: 480Mbps High Speed USB v2.0
usbus4: 12Mbps Full Speed USB v1.0
usbus5: 480Mbps High Speed USB v2.0
ugen0.1: <ATI> at usbus0
uhub0: <ATI OHCI root HUB, class 9/0, rev 1.00/1.00, addr 1> on usbus0
ugen1.1: <ATI> at usbus1
uhub1: <ATI EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus1
ugen2.1: <ATI> at usbus2
uhub2: <ATI OHCI root HUB, class 9/0, rev 1.00/1.00, addr 1> on usbus2
ugen3.1: <ATI> at usbus3
uhub3: <ATI EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus3
ugen4.1: <ATI> at usbus4
uhub4: <ATI OHCI root HUB, class 9/0, rev 1.00/1.00, addr 1> on usbus4
ugen5.1: <ATI> at usbus5
uhub5: <ATI EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus5
uhub4: 4 ports with 4 removable, self powered
uhub0: 5 ports with 5 removable, self powered
uhub2: 5 ports with 5 removable, self powered
uhub5: 4 ports with 4 removable, self powered
uhub1: 5 ports with 5 removable, self powered
uhub3: 5 ports with 5 removable, self powered
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <WDC WD30EZRX-00DC0B0 80.00A80> ATA-9 SATA 3.x device
ada0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada0: Previously was known as ad4
ada1 at ahcich1 bus 0 scbus1 target 0 lun 0
ada1: <WDC WD30EZRX-00DC0B0 80.00A80> ATA-9 SATA 3.x device
ada1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada1: Command Queueing enabled
ada1: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada1: Previously was known as ad6
ada2 at ahcich2 bus 0 scbus2 target 0 lun 0
ada2: <WDC WD30EZRX-00DC0B0 80.00A80> ATA-9 SATA 3.x device
ada2: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada2: Command Queueing enabled
ada2: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada2: Previously was known as ad8
ada3 at ahcich3 bus 0 scbus3 target 0 lun 0
ada3: <WDC WD30EZRX-00DC0B0 80.00A80> ATA-9 SATA 3.x device
ada3: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada3: Command Queueing enabled
ada3: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada3: Previously was known as ad10
ada4 at ata0 bus 0 scbus4 target 1 lun 0
ada4: <INTEL SSDSC2CT120A3 300i> ATA-9 SATA 2.x device
ada4: 150.000MB/s transfers (SATA, UDMA6, PIO 8192bytes)
ada4: 114473MB (234441648 512 byte sectors: 16H 63S/T 16383C)
ada4: Previously was known as ad1
SMP: AP CPU #1 Launched!
Timecounter "TSC-low" frequency 11699577 Hz quality 800
Trying to mount root from ufs:/dev/ad1p2 [rw,noatime]...
ZFS filesystem version 5
ZFS storage pool version 28

freebsd-updateを使ってFreeBSD 9.0-RELEASEからFreeBSD 9.1-RELEASEにアップグレード

FreeBSD 9.0-RELEASEで始めた自宅サーバだけど、ほどなくFreeBSD 9.1-RELEASEがリリースされたのでアップグレードした。FreeBSD.orgのサーバが侵入されちゃった事件の影響か、少しリリースが遅れたけど、無事にリリースされてよかったよ。
アップグレードは、いつもどおりfreebsd-updateを使ってバイナリアップデート。しばらく前から、ソースツリーは展開してなかったりする。うーん、軟弱になったもんだ。
手順はいつも通りで特に変わったところは無し。
まずは元リリースの最新に更新する。これは、FreeBSD-EN-12:01.freebsd-updateを修正しておかないと、freebsd-updateがうまく動かないから。

# freebsd-update fetch
# freebsd-update install

次に9.1-RELEASEへの更新差分をゲットする。しばらく時間がかかるので注意。

# freebsd-update upgrade -r 9.1-RELEASE

ゲットしたら、インストール。この段階では、kernelだけが新しくなるので、再起動して新しいkernelで動作させる。

# freebsd-update install
# shutdown -r now

次に残りの更新をインストールして再起動する。

# freebsd-update install
# shutdown -r now

8.2-RELEASE以前からのアップグレードだと、portsの作り直しが必要だけど、今回は9.0-RELEASEからなので、これでおしまい。ZFSは同じバージョンなので、zpool、ZFSのupgradeも不要。

自宅サーバを富士通 PRIMERGY MX130 S2からHP ProLiant MicroServerに更新

某所でHP ProLiant MicroServerがいいらしい、と聞いたので、調査してみた。本当によさそうだったので、富士通 PRIMERGY MX130 S2から乗り換えた。
MicroServerのスペックはこんな感じ。

PRIMERGY MX130 S2と比較すると、よい点は

  • HDDが専用ベイできれいに4台搭載可能、取り付け・取り外しも簡単(ただしホットプラグは未対応)
  • HDDを4台搭載しても、光学ドライブを搭載可能(MX130は4台目を5inchベイに搭載する必要があった)
  • eSATAポート搭載、外付けHDD箱による拡張もできる

いまいちな点は

  • メモリスロットが2スロット(MX130 S2は4スロット)
  • 筐体が立方体に近く、設置場所の変更が必要(これは人によると思う)
  • メモリや拡張カードの増設が面倒(マザーボードから各種コネクタを外して引っ張り出す必要がある)

今の利用状況から判断すると、メモリは8GBあれば足りそうだったのと、HDD 4台搭載して5inchベイが空くこと、低消費電力でいけそうなところに魅力を感じて乗り換えることにした。
N40LのHDD 250GBモデルがAmazonで17,800円だったので、これをベースにメモリとHDDを別調達した。ZFS Rootは面倒だったので、起動用にSSDをチョイス。最終的に追加したパーツはこんな感じ。

  • メモリ:PC3 DDR10600 DDR3 4GB x2(non ECC)
  • HDD:WD30EZRX 3TB x4
  • SSD:Intel 330(120GB)

OSは9.1-Rリリース前だったので9.0-Rをインストール。ZFSは、以前は容量の都合でRAIDZだったけど、今回は3TBに増量して余裕があったので、3TBのミラーx2で行くことにした。旧サーバからデータを移行して、無事稼働開始。HDDが前面から簡単に取り外しできるので、HDD故障したときの交換が楽になりそう。壊れないのが一番だけど。

HP ProLiant MicroServer TurionII NEO N40L 1.5GHz
by カエレバ
WD Green 3.5inch IntelliPower 3.0TB 64MBキャッシュ SATA3.0 WD30EZRX-1TBP/N 【フラストレーションフリーパッケージ(FFP)】
by カエレバ
Intel SSD 330 Series Maple Crest 120GB MLC 2.5inch 9.5mm Reseller Box SSDSC2CT120A3K5
by カエレバ

あけましておめでとうございます

この日記も1年以上放置してたけど、今年は少しずつ更新していきたい所存。

  • FreeBSDに関する技術ネタ、小ネタ、試行錯誤の記録
  • MacOSXに関する小ネタあれこれ

この辺のネタを題材に、週1回くらいは何か書いていきたい。

perlでEvernoteのAPIを使うときに'Missing version identifier'で怒られた

とある目的でperlからEvernoteAPIを使う必要にかられて挑戦してみたところ、'Missing version identifier'でUserStore->checkVersionが異常終了して困ってた。環境を変えて調べてみると、Mac OS X上にperlbrewで作ったperl 5.14.2環境ではうまくいかなくて、FreeBSD環境だとうまくいく。
例外の内容はこんなかんじ。

$VAR1 = bless( {
                 'code' => 0,
                 'message' => 'Missing version identifier'
               }, 'Thrift::TException' );

よくよく考えると、Evernote APIはThrift::HttpClient経由でlibwwwを使うんだけど、アクセス先がhttpsだった。Mac OS X上では、libwwwをhttps対応させてなかったのが原因だ。というわけで、Crypt::SSLeayとLWP::Protocol::httpsを追加でインストールして解決した。
FreeBSD portsだとMakefileの以下の記述により、OPTIONS SSLを有効にしていればSSL対応になるので、最初は気づかなかったよ。

.if defined(WITH_SSL)
RUN_DEPENDS+=   p5-Crypt-SSLeay>=0:${PORTSDIR}/security/p5-Crypt-SSLeay \
                p5-LWP-Protocol-https>=0:${PORTSDIR}/www/p5-LWP-Protocol-https
.endif