start

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に鞍替えするときが来たのか!?


1)
UNCは話がややこしくなるので考慮しない

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文字で決め打ちしてるアプリで扱おうとした時にどうなるんだとか、色々気になる点はあるが、是非とも実現されてほしいところ。


2)
260文字という話もある。さらに近年は32768文字に拡張された

今度こそ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を使うとするかー。

Special vdevが消失したプールとzpool -Fオプション

プールのメタデータを丸っと引き受けるというZFSのSpecial vdevの特性から、対応する物理デバイスの故障などでSpecial vdevが死ぬと、プールそのものが使えなくなりそうってのは容易に想像ができる。

実際どうなるか仮想マシンベースで確認してみると、やはり使えなくなった。それもzpool listの結果にプール自体が出てこなくなるという、割と重篤な扱い。プール名を指定 or プール探索でインポートしようとすると、以下のようになってインポートできない。

# zpool import -a -N
cannot import 'ztest': I/O error
        Destroy and re-create the pool from
        a backup source.

存在しないプールのインポートではcannot import 'znotexists': no such pool availableって感じなので、明らかに扱いが違う。

Special vdevが消失したプールの復旧は基本的に無理っぽい感じ。

一応man zpool-importを見てみると、(いつの間にか)プール回復に関するオプション-F, -X, -Tが追加されていた。それぞれの効果を抄訳してみた。

-F インポート不可能なプールのための回復モード。最後のわずかなトランザクションを破棄することで、プールがインポート可能状態への復帰を試みます。このオプションを使うことで、損傷を受けたすべてのプールが回復するとは限りません。成功した場合、破棄されたトランザクションに関連するデータは、回復不能なほどに失われます。プールがインポート可能またはインポート済みの場合、このオプションは無視されます。
-n 回復オプション(-F)と共に使用します。インポート不可能なプールが再びインポート可能になるかどうかを判定しますが、実際にプール回復は行いません。プール回復モードの詳細は、上記の-Fオプションをご覧ください。
-X 回復オプション(-F)と共に使用します。有効なtxgを見つけるための非常手段を取るか否かを指定します。これは、もはや一貫性が保証されていないtxgへ、プールがロールバックされることを許可します。矛盾したtxgでインポートされたプールは修復不能なチェックサムエラーを含むかもしれません。プール回復モードの詳細は、上記の-Fオプションをご覧ください。警告:このオプションはプールの健全性に対し極めて危険な可能性があり、最終手段として用いるべきです。
-T ロールバックに使用するtxgを指定します。暗黙的に-FXオプションを含みます。プール回復モードの詳細は、上記の-Xオプションをご覧ください。警告:このオプションはプールの健全性に対し極めて危険な可能性があり、最終手段として用いるべきです。

-F < -X < -Tの順で強力(危険)になる雰囲気。で、それぞれを指定して、先のSpecial vdevが無くなったプールのインポートを試みたのが以下。

# zpool import -F ztest
cannot import 'ztest': I/O error
        Destroy and re-create the pool from
        a backup source.

# zpool import -FX ztest
cannot import 'ztest': one or more devices is currently unavailable

# zpool import -T ztest
invalid txg value
usage:
        import [-d dir] [-D]
        import [-o mntopts] [-o property=value] ...
            [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] [-R root] [-F [-n]] -a
        import [-o mntopts] [-o property=value] ...
            [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] [-R root] [-F [-n]]
            [--rewind-to-checkpoint] <pool | id> [newpool]

-Tはtxgを指定してやらないとダメな予感。usageにもmanにもそれらしいことは書いてないんだけど…実際にどんな値を指定したらいいのか皆目見当もつかない。

その後、Special vdev用の仮想ディスクを戻してみると、問題なくプールのインポートができた。ただし自動インポートはされず、手動で行う必要があるようだ。(上記の-Fとかでプールを操作したためかもしれないが未確認。)scrubで健全性に問題がないことも確認。

そんなわけでSpecial vdevの冗長性には十分気を付ける必要がありそうだ。

  • start.txt
  • 最終更新: 2022-07-27 15:26
  • by Decomo