256バイト以上のファイル名を持つZFSをFreeBSDにインポートしてみる
以前、FreeBSDではlongnameフィーチャーは使えないという話をした。
FreeBSDで255バイト超のファイル名でファイルは作れないとして、Linuxで作った256バイト以上のファイル名を持つZFSをFreeBSDにインポートした場合、どうなるのだろうか。インポートできなかったり、クラッシュしたり、データセットが壊れるなんてことは流石にないと思うが、分からんってのが正直なところ。サクッと試してみよう。
まずはLinux側でlongnameフィーチャーが有効なデータセットと、長いファイル名を持つファイルを作る。
環境はこんな感じ。Linuxと言いつつProxmox VEです。
# pveversion
pve-manager/9.1.4/5ac30304265fbd8e (running kernel: 6.17.4-2-pve)
# zpool version
zfs-2.3.4-pve1
zfs-kmod-2.3.4-pve1
# zpool status zlongname
pool: zlongname
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
zlongname ONLINE 0 0 0
zvol/zvm/vm-100-disk-0 ONLINE 0 0 0
errors: No known data errors
データセットの文字コードはUTF-8にした。
# zfs create -o utf8only=on zlongname/longname
UTF-8の場合、日本語1文字はおおむね3~4バイトでエンコードされるので、255バイト=全角85文字となる。255バイトと256バイトのファイル名でファイルを作ってみる。
# touch '123456789~1~123456789~2~1234 56789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345' # touch '123456789~1~123456789~2~1234 56789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a' touch: cannot touch '123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a': File name too long
256バイトの方はファイル名長すぎィと怒られた。longnameフィーチャーを有効にして再度試してみる。
# zfs set longname=on zlongname/longname # touch '123456789~1~123456789~2~1234 56789~3~123456789~4~123456789~5~123456789~6~123456 789~7~123456789~8~12345a' # ls 123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345 123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a
今度は当然ながら問題なく作成できた。このプールをFreeBSDに持っていく。
FreeBSD側は以下のような感じ。ashiftの警告が出てるけど本質じゃないのでスルーで。
$ freebsd-version -uk
14.3-RELEASE-p2
14.3-RELEASE-p2
$ zpool status zlongname
pool: zlongname
state: ONLINE
status: One or more devices are configured to use a non-native block size.
Expect reduced performance.
action: Replace affected devices with devices that support the
configured block size, or migrate data to a properly configured
pool.
config:
NAME STATE READ WRITE CKSUM
zlongname ONLINE 0 0 0
gptid/737d89da-f0e3-6c4d-a86d-426d41479aa8 ONLINE 0 0 0 block size: 512B configured, 4096B native
lsでは普通に255バイト超のファイル名も表示された。ちょっと意外。
$ ls /zlongname/longname/ 123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345 123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a
開こうとするとファイル名長すぎィと怒られた。
$ cat '/zlongname/longname/123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a' cat: /zlongname/longname/123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345a: File name too long
256バイトのファイル名でファイルを作ろうとしても、やっぱり長すぎィと怒られた。
$ touch '/zlongname/longname/123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345b' touch: /zlongname/longname/123456789~1~123456789~2~123456789~3~123456789~4~123456789~5~123456789~6~123456789~7~123456789~8~12345b: File name too long
というわけで、ZFSのlongnameフィーチャーを有効にし256バイト以上のファイル名があるデータセットをFreeBSDに持っていくと、ファイルの存在は確認できるが、ファイル操作は不可というのが現状のようだ。
FreeBSD 14.3ではZFSのlongnameフィーチャーは事実上非対応っぽい?
OpenZFS 2.3.0で、個人的に待望のlongnameフィーチャーがリリースされた。
ZFSにおけるファイル名・ディレクトリ名(以後、まとめてファイル名と表記する)の最大長は、UNIX系の習わし(?)に沿って255 bytesとなっているが、longnameフィーチャーを有効にすると、その制約を打ち破って1023 bytesまで使えるようになる。単純に上限が固定的に引き上げられるといったものではなく、255 bytes超の名前があると機能がアクティブとなり、無くなれば非アクティブになるといった、動的な挙動となっているようだ。
この255バイトという伝統的な値はNAME_MAXマクロに由来し、FreeBSDの場合は/usr/src/sus/sys/syslimits.hで定義されている。厳密にいうと、ZFSでの制約は自身が定義している定数由来なのだが、NAME_MAXを意識した値であろうと思われる。なお、ここで注意が必要なのは、ファイルパスの最大長はPATH_MAXと別に定義されており、FreeBSDの場合は1023バイトとなっている。本記事で取り扱うのは、あくまでファイル名の最大長の方である。
現代的なUNIX系のファイルシステムでは、必ずしもこの制限に縛られることはないようだが、有名どころのFSは大抵255バイトが上限となっている。
255バイトもあって何が不満かと言われれば、ファイル名の文字エンコーディングにUTF-8を採用すると、最大文字数がだいぶ心許ないってこと。UTF-8の場合、日本語の文字は大半が3バイト、場合によっては4バイトで表現されるため、いわゆる全角換算で85~63文字に目減りしちゃうんですな。この問題はとりわけWindowsとファイル共有した時に顕在化しやすい。というのも、Windowsの主要FSの最大長はUTF-16で255文字1)なので、つい長い名前つけちゃって、FreeBSD+Sambaな共有フォルダにコピーしようとして失敗、なんてことが年に数回起きる。これが1023バイトならUTF-8でも341~255文字となり、大変都合がいいわけですよ。
そんなわけで、longnameフィーチャーには大変期待していたのだが、どうもFreeBSD 14.3-RELEASE時点では事実上使えないようだ。
ZFS自体の255バイト制限はなくなったものの、FreeBSDのVFSレイヤーに255バイト制限が残っていて、この影響を受ける模様。実際、PortsからOpenZFS 2.3.0入れて試してみたが255バイト制限は突破できなかった…。SambaはNAME_MAX等の直接的な制限は受けないようだし、Linux+Sambaでは問題なく機能しているようだし、やはりFreeBSD側の制限の可能性が大。
VFSの根っこの部分っぽいし、改善されるのかなー?
正直、longnameは今すぐにも使いたい。というか、256バイト以上のファイル名を含むデータセットをFreeBSDに持ってきた時に変なことにならないんだろうか…?ついにLinuxに鞍替えするときが来たのか!?
RAID-Z Expansionがマージされてた&ファイル名の最大長拡張PRが出来てた
もはや旧聞に属する話だが、2023年11月9日のRAID-Z Expansionのプルリクがついにmasterにマージされていた。コンセプトが発表されてから足掛け7年、実に長かった。なかなかインパクトのある機能だし仕方ないか。関係者の皆様お疲れ様でございました。
とはいったものの、実際にリリースされて使えるようになるのは、まだ先と思われる。リリース時期に関する最新情報は見つけられなかったのだけど、2021年時点のロードマップではOpenZFS 3.0で対応予定となっている。どんなに早くても2.3かなー?と思いつつ、どちらのバージョンのブランチもまだ存在しないのが現状。
加えてFreeBSDで使うには、ベースシステムに取り込まれるのを待たなきゃならんわけで、1年以上先なんじゃね?という気がしなくもない(まぁportsから入れればいいんだけども)。首を長くして待ちましょー
ついでにプルリク一覧を眺めていたら、ファイル名/ディレクトリ名の最大長を1023バイトに拡張する新しい機能フラグの実装があった⇒Longname: files/directories name upto 1023 bytes by tuxoko · Pull Request #15921 · openzfs/zfs
ZFSのファイル名/ディレクトリ名の最大長は255バイトとされているが、これはNAME_MAXだかPATH_MAX定数由来の制約らしい。これはUNIX系のファイルシステムにおける典型的な最大長で、通常はほとんど困らないサイズである。
ところが、ファイル名の文字コードとしてUTF-8を使うと話が変わってくる。UTF-8では1文字あたりのバイト数が1~4バイトと可変なので、ワーストケースで63文字しか格納できない。日本語の文字種はおおむね3バイトになるため、85文字で打ち止めとなる。
これでもFreeBSD、Linux単体で使う分にはさほど問題にならないと思うが、Windowsとファイル共有するとだいぶ困ったことになる。 というのもWindows (NTFS)の最大長はUTF-16で255文字2)なので、ZFSの255バイトでは全然足りんのです。 まぁ、日常的に85文字を超えるファイル名を使うことは、少なくとも自分は無いけれど、それでも1年に2~3回くらいは困る場面があるんだよね…
上記PRとは別に(?)最大長拡張の議論もなされており、開発のコアメンバーも認識はしている模様。互換性はどうなるんだとか、最大255文字で決め打ちしてるアプリで扱おうとした時にどうなるんだとか、色々気になる点はあるが、是非とも実現されてほしいところ。
参考サイト
今度こそRAIDZ Expansionが来る?
RAIDZ ExpansionのPR作成の報を打ってから早2年、今度こそRAID-Z Expansionが来そうな雰囲気?である。
当時のPRは閉じられており、6月末にどういう訳か新しいPRに移行して作業が行われている。見てないけどOpenZFSリーダー会議で移行議論の概要が見られるようだ。
今回は着々とレビューとコミットが積み上げられている。RAIDZ Expansion自体は問題なく動いているようで、既に自前ビルドで使っている勇者もいるっぽい。今度こそマージされてほしい。
RAIDZプールに追加したスペシャルvdevは削除できない
OpenZFS 2.1.4時点で、冗長性レベルを問わずRAID-Zプールに追加したスペシャルvdevを削除することは出来ないようだ。恐らく、トップレベルvdev削除の制限に起因する仕様と思われる。
次のようなRAID-Z1とスペシャルvdevから成るプールがあるとする。
# zpool status ztank
pool: ztank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
zdata ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
da1 ONLINE 0 0 0
da2 ONLINE 0 0 0
da3 ONLINE 0 0 0
special
mirror-1 ONLINE 0 0 0
da4 ONLINE 0 0 0
da5 ONLINE 0 0 0
errors: No known data errors
ここで、スペシャルvdevを削除しようとzpool removeすると、次のようにエラーとなる。
# zpool remove ztank mirror-1 cannot remove mirror-1: invalid config; all top-level vdevs must have the same sector size and not be raidz.
トップレベルvdevのmirror-1を一気に削除するのがマズいのかと思い、次のように構成メンバを個別に削除してってもダメ。
# zpool detach ztank da5 # zpool remove ztank da4 cannot remove .....
なお、RAIDZ以外の構成なら特に制限なく削除可能で、同じトップレベルvdevであるslogやL2ARCの場合は、RAIDZでも(以前から)削除可能である。
家鯖でスペシャルvdevを本格運用すべく色々準備してたけど、削除できないのはちょっと厳しいなぁ…VMであらかじめ実験しといて良かったぜ……slog/L2ARCは削除できるんだから、将来的にできるようになるのかなぁ………スペシャルvdevの場合、明示的に本体プールの方にデータを書き戻す必要があって難しいのかなぁ…………
当面はpL2ARCを使うとするかー。