FreeBSD unionfsの改善提案および修正状況

後藤大地 (daichi@freebsd.org)
作成年月日 Mon Feb 13 12:08:39 2006
更新年月日 Tue Oct 23 13:32:15 2007

[English]

1 概要

FreeBSD 6.2-RELEASEまでに搭載されているunionfsにはいくつかの問題があった。問題は、大きく分けて2つの領域に分類することができる。unionfsにおける仕様が曖昧な部分に起因する問題と、FreeBSD unionfsのロックの実装に関する問題である。

FreeBSD unionfsの2つの問題:

この結果、CD9660ファイルシステムに対してunionfsをかぶせて使用するような場合にいくつかの問題が起こっていた。このためFreeSBIEのようなシステムではunionfsをそのまま採用できないでいた。本稿では、これら問題を説明すると同時に、これら問題を解決するためのパッチを提供する。すでに新しいunionfs実装の重要な部分の大半はシステムへマージされている。現在開発が進められている改善パッチは随時システムへのマージを実施している。

2 unionfsとは

unionfsは、2つのファイルシステムをアタッチしてひとつのファイルシステムとして扱うためのファイルシステムのことである。たとえばCD-ROMに対してメモリファイルシステムをアタッチして、CD-ROM上のファイルに対して書き込みができるかのように見せかけるといった用途に用いられる。

ベースとなるディレクトリ (下層) 以下に対して変更を加えることなく、上にかぶせたディレクトリ(上層)以下に対してのみ変更を与えることになるため、下層のディレクトリはそのままに、変更点だけ保持したいといった場合にも活用できる。

詳細な仕様はMarshall Kirk McKusick、George V. Neville-Neil著 "The Design and Implementation of the FreeBSD Operating System" の P.256 Section 6.7, The Union Filesystemからの2ページ強分などを参照のこと。

3 従来のFreeBSD unionfsが抱えていた問題

FreeBSD 6.2-RELEASEまでの古いFreeBSD unionfsが抱えいた問題は次のとおり。

  1. [実装上の問題] 従来のunionfsは、ロック機構として次のような方法を使っている。VOP_* 系の呼び出しに対し、必要に応じて上層/下層をロックしにいくというものである。この場合、unionfsのvnode を含め、1つのvnodeに対して最大で同時に3つのロックを行うことになる。つまり、カーネル側の仕組とは別のタイミングで複数のロック/アンロックを行うため、デッドロックが起りやすい状況にある。事実、従来のunionfsは不安定であり、高負荷状況になるとデッドロックが起りやすい。
  2. [実装上の問題] VOP_*系の呼び出しにおいて、一部はunionfsのvnodeを応答するのに対し、一部は上層/下層のvnodeを直接応答する。特にLOOKUPでこの現象が起きた場合、ユーザからは理解しがたい状況に陥る可能性がある。これまでに確認しているものは、pwdが上層/下層の絶対パスを応答してしまう現象である。
  3. [実装上の問題] readdirの実装が不十分で、上層の一覧のみを応答する。このため、下層にのみ存在するファイルなどをユーザが識別することが出来ない。
  4. [実装上の問題] 上層/下層に同一のファイル/ディレクトリが存在した場合、上層を削除後にホワイトアウトが作成されないため、ユーザからは削除されていないように見える。
  5. [実装上の問題] アクセス権の判定において、下層にのみファイル/ディレクトリがある場合、上層にshadow file/dirを作成後に与えられる権限を応答しない。このため、書き込めるはずのファイルに書き込めないなどの問題が発生する。
  6. [unionfsの仕様の曖昧さに起因する問題] unionfsの仕様には下層のshadow file/dirを作成する場合に、属性の引き継ぎに関する規定がない。このため、従来の実装では「0777をそのときのumaskで修正したもの」という方法のみが提供されてきたが、これが現在のFreeBSD unionfsでは好ましくない結果を生んでしまうことがある。たとえば、実行権限を与えるべきでないファイルへ実行権限が与えられてしまうなど。

これら古いFreeBSD unionfsが抱える問題によってたとえば次のような影響がでていた。

4 問題への改善提案

提案してきたパッチにおける[実装上の問題]への改善内容は次のとおり。これら成果物はすでにFreeBSDシステムへマージされており、FreeBSD 8/FreeBSD 7.0/FreeBSD 6.3ではこれら問題は発生しない。

  1. [実装上の問題への対処] unionfsのvnodeが内部に持つロックオブジェクトを上層/下層のロックオブジェクトへのポインタに差し替え、なおかつロック/アンロックをunionfsで管理することでkernelをできるだけ修正せずに正常動作するようにする。また、kernelへの影響を無くすため、上層/下層のロックは常に同じ状態を維持できるように管理する。
  2. [実装上の問題への対処] http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/84107の修正 (修正完了)
  3. [実装上の問題への対処] http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/84498の修正 (修正完了)
  4. [実装上の問題への対処] http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/89755の修正 (修正完了)
  5. [実装上の問題への対処] http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/73094の修正 (修正完了)
  6. [実装上の問題への対処] これ以外で、前述したようにわかっている問題を対処。

[unionfsの仕様の曖昧さに起因する問題]に対する改善については、本来仕様に規定されていないことであるため、規定されていない振る舞いをどうするべきか、という議論を含むことになる。

FreeBSD 6.2-RELEASEまでの古いunionfsにおける実装では、この結果、アクセス権を判定し動作を決定するアプリケーションが、ユーザの期待どおりに動作しないという状況が発生している。

この振る舞いをどうするかであるが、これは場面に応じて要求される事柄であり、また、本来仕様に定められていないことであるために、対応が難しいところだと考えられる。今回はこの振る舞いに対し、オプションによって3つの振る舞いを持たせるということで対処することを提案した。パッチはこの3つの振る舞いをオプションで切り替える機能を含んでいる。

[unionfsの仕様の曖昧さに起因する問題]に対する改善:3つの動作パターン

本来仕様が策定されていない部分の振る舞いであるから、複数の振る舞いを用意し選択できるようにすることは、意義のある対応であると考える。たとえば、3-7において説明した[unionfsの仕様の曖昧さに起因する問題]は、[transparentモード]で対処できる。

この結果、次の問題も[transparentモード]で修正された。

5 インストール方法

パッチを適用してインストールする方法の作業例をプロンプト5.1に示す。

# cd /usr/src/
# patch -p3 < /anywhere/unionfs-p19-20070504.diff
# cp /usr/src/sys/fs/unionfs/union.h /usr/include/fs/unionfs/
# cd /usr/src/sbin/mount_unionfs/
# make obj depend && make && make install
# make clean
# cd /usr/src
# make buildkernel
# make installkernel
# shutdown -r now
プロンプト5.1 インストール作業の例

6 使用方法

マニュアルページmount_unionfs(8)を参照のこと。すべてマニュアルページにまとまっている。

7 ダウンロード

FreeBSD 8-current向けパッチ。パッチセット番号が大きいほど新しいパッチセット。

FreeBSD 7-stable向けパッチ。

FreeBSD 7-current向けパッチ。

FreeBSD 6-stable向けパッチセット:

7.1 unionfs-p19-20070504.diff / unionfs-p19-20070524.diffにおける変更点

7.2 unionfs-18.diffにおける変更点

7.3 unionfs-17.diffにおける変更点

7.4 unionfs-16.diffにおける変更点

7.5 unionfs-15.diffにおける変更点

7.6 unionfs-14.diffにおける変更点

7.7 unionfs-13.diffにおける変更点

7.8 unionfs-12.diffにおける変更点

7.9 unionfs-11.diffにおける変更点

7.10 unionfs-10.diffにおける変更点

7.11 unionfs-9.diffにおける変更点

7.12 unionfs-8.diffにおける変更点

2006/02/13 - 6.xにおいてビルドできない問題があったため、unionfs6-p8.diffを修正したunionfs6-p8-fix1.diffを追加。

7.13 unionfs-7.diffにおける変更点

7.14 unionfs-6.diffにおける変更点

7.15 unionfs-p5.diffにおける変更点

7.16 unionfs-p4.diffにおける変更点

7.17 unionfs-p3.diffにおける変更点

7.18 unionfs-p2.diffにおける変更点

7.19 unionfs-p1.diffにおける変更点

8 既知の問題

9 成果物のマージ1

unionfs-17.diffからsys/kern/vfs_lookup.cに対するパッチをはずした成果物が2006-12-02 19:35:56 UTCづけのFreeBSD 7-currentブランチにマージされた。

リスト9.1 unionfs-17.diffからsys/kern/vfs_lookup.cに対するパッチをはずした成果物を-currentへマージ
rodrigc     2006-12-02 19:35:56 UTC

  FreeBSD src repository

  Modified files:
    sys/fs/unionfs       union.h union_subr.c union_vfsops.c 
                         union_vnops.c 
    sbin/mount_unionfs   Makefile mount_unionfs.8 mount_unionfs.c 
  Log:
  Many, many thanks to Masanori OZAWA <ozawa@ongs.co.jp>
  and Daichi GOTO <daichi@FreeBSD.org> for submitting this
  major rewrite of unionfs.  This rewrite was done to
  try to solve many of the longstanding crashing and locking
  issues in the existing unionfs implementation.  This
  implementation also adds a 'MASQUERADE mode', which allows
  the user to set different user, group, and file permission
  modes in the upper layer.
  
  Submitted by:   daichi, Masanori OZAWA
  Reviewed by:    rodrigc (modified for minor style issues)
  
  Revision  Changes      Path
  1.13      +1 -1        src/sbin/mount_unionfs/Makefile
  1.21      +184 -23     src/sbin/mount_unionfs/mount_unionfs.8
  1.25      +107 -74     src/sbin/mount_unionfs/mount_unionfs.c
  1.33      +87 -92      src/sys/fs/unionfs/union.h
  1.87      +948 -1080   src/sys/fs/unionfs/union_subr.c
  1.79      +394 -332    src/sys/fs/unionfs/union_vfsops.c
  1.135     +1864 -1613  src/sys/fs/unionfs/union_vnops.c

2007-02-13 05:56:43 UTC、主要なコードの大半がFreeBSD 6-stableブランチにマージされた。

リスト9.2 FreeBSD 6-stableに成果物がマージされた
rodrigc     2007-02-13 05:56:43 UTC

  FreeBSD src repository

  Modified files:        (Branch: RELENG_6)
    sys/fs/unionfs       union.h union_subr.c union_vfsops.c 
                         union_vnops.c 
    sbin/mount_unionfs   Makefile mount_unionfs.8 mount_unionfs.c 
  Log:
  MFC: New unionfs implementation from Daichi GOTO and Masanori OZAWA,
       which fixes many locking and crashing problems in the previous
       implementation.  kib@ helped a lot by eliminating a source
       of deadlocks encountered with unionfs with these commits:
         rev. 1.50 of src/sys/fs/deadfs/dead_vnops.c
         rev. 1.97 of src/sys/kern/vfs_lookup.c
  Submitted by:   daichi, Masanori OZAWA <ozawa ongs co jp>
  
  Revision   Changes      Path
  1.12.8.1   +1 -1        src/sbin/mount_unionfs/Makefile
  1.20.2.1   +198 -25     src/sbin/mount_unionfs/mount_unionfs.8
  1.24.2.1   +108 -74     src/sbin/mount_unionfs/mount_unionfs.c
  1.31.2.1   +88 -94      src/sys/fs/unionfs/union.h
  1.86.2.1   +937 -1080   src/sys/fs/unionfs/union_subr.c
  1.76.2.2   +398 -334    src/sys/fs/unionfs/union_vfsops.c
  1.132.2.1  +1879 -1607  src/sys/fs/unionfs/union_vnops.c

10 成果物のマージ2

unionfs-p19-20070524.diffは2007年10月14日(日本時間)、FreeBSD 8-currentブランチにマージされた。次いで2007年10月22日(日本時間)にRELENG_7へ、翌2007年10月23日(日本時間)にデフォルトモードの変更パッチだけを除外したものがRELENG_6へマージされた。

11 Appendix

11.1 FAQ

Q: 従来のunionfsの修正という形ではなく、フルスクラッチから作り替える必要はあったのか?

A: 従来の実装は本質的にロックの実装でデッドロックが発生しやすいものになっていた。これを修正するのは難しく、ほとんどが作り替えになる。このため、従来のソースに対する修正という形ではなく、フルスクラッチから作成することにした。

Q: 互換性はどうなっているのか?

A: 現在のパッチでは、従来の使い方をする限り従来の動作と互換性がある。しかもhttp://www.freebsd.org/cgi/query-pr.cgi?pr=kern/84107http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/84498http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/89755http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/86596http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/73094やほかのunionfsに関する多くの問題も修正されている。

将来的には、-c transparentの動作をデフォルトにするべきだと考える。従来の動作で問題となる動作のほとんどは、-c transparentにすることで修正されると考えるからである。

Q: パッチの実装はunionfsの本来の動作に沿っているのか

A: 沿っていると考える。unionfsの仕様についてはMarshall Kirk McKusick、George V. Neville-Neil著 "The Design and Implementation of the FreeBSD Operating System" の P.256 Section 6.7, The Union Filesystemからの2ページ強分にまとまっているので、そちらを参照のこと。

Q: 読み込みを行っただけで shadow file が生成されるのはなぜか?

A: 下層のファイルに対してアクセス日時を更新することは出来ないため、shadow fileを作成して日時を更新するからである。この動作をやめるには、-o noatime オプションを指定すればよい。詳細はmount(8)を参照のこと。

Q: viで書き込むと次のメッセージを表示することがある。他のプロセスで、何も変更を加えていないが問題ないか?

'filename: file modified more recently than this copy; use ! to override.'

A: 上層へ 'copied-up file'を作成した場合にも表示される。これは、ファイルのinodeが変更されたことをviが検出するため。正常な動作であり問題はない。

11.2 連絡先

日本語から英語への翻訳に興味がある方は、翻訳したテキストをdaichi AT-MARK freebsd.orgかdaichi MT-MARK jp.freebsd.orgへ寄贈プリーズ。日本語テキストだとSPAMフィルタで弾かれる可能性があるのでjp.freebsd.orgの方がいいかも。バグ報告も同アドレスへ。

11.3 謝辞

太田さんと小野寛生さん、田丸博晴さんのご尽力によって、本サイトに英語版ページが作成されました。マニュアルページは佐藤広生さんによって編集されました。高品質なマニュアルが実現されたのは佐藤さんの手によるものです。感謝! 日本語サイトは随時更新されますので、英語版サイトを読んで日本語が混じっているところは、随時だれか英語に翻訳して〜

ディスクレス環境でのunionfsの動作試験を行ってくれているDanny Branissさん、FreeSBIEの主要開発者であり、最新のFreeSBIEで現在のunionfsの成果物を統合して積極的に開発を展開してくれているDario Freniさん、src committerにしてはじめてマージにむけて興味を持ってくれたAlexander Leidingerさん、daichiのsrc mentorを担当しマージへ向けて忍耐よく作業をしてくれたsrc committerのCraig Rodriguesさん。特にCraig Rodriguesさんのご尽力によってFreeBSD 7-currentへのマージが実現したといっても過言ではない。

whiteoutモード機能を提供してくれたEd Schouten氏。Coverityで報告されたNULLチェック関連の修正を示唆してくれたStanislav Sedov氏。いつも誰よりもはやくデッドロックやパニックの報告をしてくれるKris Kennaway氏。大量のunionfsパッチをレビューしてくれたJeff Roberson氏とKen Smith氏。

そして、自分のおかしな英語翻訳を修正してくれたFabian Keilさん、みなさんに感謝っ