NFSで提供されたread-only rootにtmpfsをoverlayすることで,同一のrootfsを複数のserverで共有できる.
この環境を構築する際に生じた問題とその対策をまとめた.
環境
- OS: CentOS Linux release 8.1.1911 (Core)
- Kernel: 4.18.0-147.5.1.el8_1.x86_64
- overlayfsを使用
- lower = read-only root over NFS v4
- upper = tmpfs
lowerdirの内容を変更するとESTALEが生じる
そもそもoverlayfsではlowerへの変更は許容されないことがKernel-docに記載されている.
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt
Changes to the underlying filesystems while part of a mounted overlay filesystem are not allowed. If the underlying filesystem is changed, the behavior of the overlay is undefined, though it will not result in a crash or deadlock.
しかし,稼働中のrootfsへ変更を加えることができると便利なので,変更を許容してほしい.
patchworkにそのような要望を叶えるpatchが投稿されており,これを適用すればよい.
(上記パッチは微妙に壊れているので,書き直した)
diff -ru linux-4.18.0-147.5.1.el8.x86_64/fs/overlayfs/super.c linux-4.18.0-147.5.1.el8.x86_64.new/fs/overlayfs/super.c --- linux-4.18.0-147.5.1.el8.x86_64/fs/overlayfs/super.c 2020-01-14 23:54:17.000000000 +0900 +++ linux-4.18.0-147.5.1.el8.x86_64.new/fs/overlayfs/super.c 2020-03-02 04:29:36.855735623 +0900 @@ -127,16 +127,11 @@ if (d->d_flags & DCACHE_OP_REVALIDATE) { ret = d->d_op->d_revalidate(d, flags); - if (ret < 0) + if (ret <= 0) return ret; - if (!ret) { - if (!(flags & LOOKUP_RCU)) - d_invalidate(d); - return -ESTALE; - } } } - return 1; + return ret; } static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
NFS v4を用いるとサブディレクトリ以下への書き込みでEOPNOTSUPPが生じる
NFS v4ではACLをサポートしているが,この属性情報(xattr)を含むmetadataをlowerからupperへコピーする際,ACLの名前空間が異なるためコピーに失敗し,EOPNOTSUPPが生じる.
詳しい情報は以下のサイトに記載されている.
この問題へのいくつかの対策法を以下に示す
- export元のfsのACLを無効にする (NFSv4のACLが無効になる)
- NFS v3を使う
- overlayモジュールのload時,またはマウントオプションで"metacopy=off"を指定する (未検証)
- metadataのcopy時にEOPNOTSUPPを無視するパッチ(以下)を当てる
- カーネルを弄らなくても解決できるので,これ以外の解決方法 (上の三つ) を取るべきだと思う
diff -ru linux-4.18.0-147.5.1.el8.x86_64/fs/overlayfs/copy_up.c linux-4.18.0-147.5.1.el8.x86_64.new/fs/overlayfs/copy_up.c --- linux-4.18.0-147.5.1.el8.x86_64/fs/overlayfs/copy_up.c 2020-01-14 23:54:17.000000000 +0900 +++ linux-4.18.0-147.5.1.el8.x86_64.new/fs/overlayfs/copy_up.c 2020-03-02 04:21:37.701624976 +0900 @@ -110,6 +110,10 @@ continue; /* Discard */ } error = vfs_setxattr(new, name, value, size, 0); + if (error == -EOPNOTSUPP) { + error = 0; + continue; + } if (error) break; }