52
ちょっと Overlayfs の実装、 読んでみました

ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Embed Size (px)

Citation preview

Page 1: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

ちょっと Overlayfs の実装、読んでみました

Page 2: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

自己紹介

名前: @akachochin

近況:お仕事は、組み込みソフト技術者です。

一時期カーネルを離れていましたが、 NetBSD/Linux カーネルの世界にまた戻ってきました。

趣味:趣味は名のとおり、赤提灯めぐり。場末の飲み屋、さいこーです。これだけで 20 分程度語れるけど、今は語りません( 笑 )

Page 3: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

いきさつ

前回の「コンテナ型仮想化の情報交換会@東京」懇親会で「ちょっと喋ってみようかなあ」と勢いで言ったのが運のつき。

しっかり覚えられてました ( 笑 )

Page 4: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

今日お話すること

腐ってもカーネルでご飯食べてる身。何か、カーネルのソース読むか。

じゃあ、 Overlayfs 読むか。 Union Filesystem の実装見たことないし。

Page 5: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

使用上の注意です。

● 読んだソースは、 linux_4.4.0-21.37 (Ubuntu16.04) です。

自宅で主に使っているのが Ubuntu16.04 で、 ftrace した結果と突き合わせるといろいろはかどるからです。

● プレゼンの時間的な制約などから、細かいことは説明しきれません。なので、厳密さよりもわかりやすさを優先したり、話を端折ったりしている箇所が結構あります。ご了承のほどを。

Page 6: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

Overlayfs って何?

Page 7: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

この章を書くにあたり、「 LXC で学ぶコンテナ入門 -軽量仮想化環境を実現する技術第 18 回  Linux カーネルのコンテナ機能 [7]overlayfs 」という記事を大いに参考としました。

記事を書かれた加藤さん、大変感謝です。

Page 8: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

Overlayfs は Union filesystem の一種です。

Union filesystem は複数のファイルシステムをひとつの場所でマウントし、仮想的にまとめてあたかもひとつのファイルシステムであるかのように見せる技術です。

Linux 3.18 のときに Linux カーネルにマージされました。

また、 Docker では 1.4.0 で overlayfs に対応しました。

Page 9: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

図にすると、こんな感じ。

※https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/ より図を引用

複数のファイルシステムのレイヤを重ねあわせてマージしたものを見せている雰囲気がつかめたでしょうか?

Page 10: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

とはいっても、イメージしづらいので、 Docker のコンテナを例に説明します。

・ Docker の Image Layers はReadOnly なファイルシステム層を参照しています。

・ Docker がコンテナを作るとき、 Image の上に Writeableな層 ( コンテナ層 ) が追加されます。

※https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/ より図を引用

Page 11: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

コンテナ層を使って、 Docker はひとつのイメージを共有しつつ、それぞれ異なる複数のコンテナを作れるのです。

※https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/ より図を引用

Page 12: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

Overlayfs に戻ります。 Overlayfs視点では、各レイヤなどの名称は以下のとおりとなります。

※https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/ より図を引用

Docker での呼び名 overlayfs での呼び名

下の Read Only な層 Image Layer lowerdir

上の writable な層 Container Layer upperdir

マージした結果 Container mount merged(Overlayfs から見たときに見えるもの )

Page 13: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

マージされたファイルシステムを Overlayfs経由で見ると・・・

● ファイルシステム間で重複しないものはそのまま見える

● ファイルが重複→より上位のファイルシステム内のファイルが見える

● ディレクトリが重複→内容がマージされたディレクトリが見える

lower

upper A

overlay

a

B b

C

C d

d

A a C dB b

upper と lower のディレクトリを

マージ

Page 14: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

lower から upperへコピーして・・・ (copy up)lower

upperA

overlay

B

A B

B

Write Write

upper側へ書き込み

overlayfs経由でファイルへの書き込みを行うと・・・

● upper側→ upper側のファイルが書き換わる

● lower側→ lower側からupper側にファイルがコピーされ、upper側が書き換わる

Page 15: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

overlayfs経由でファイルの削除を行うと・・・

● upper側→ upper側のファイルが削除される

● lower側→ upper側に「削除」を示すファイルを生成、lower側ファイルを「覆う」。

lower

upper A

overlay

B

A B

削除 削除

「削除」を示すファイルが作成され、 lower のファイルが「見えなくなる」。 (whiteout)

Page 16: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs って何?

ここまで見たことをまとめます

● overlayfs は、 lowerdir と upperdir をひとつのマウントポイントでマウントし、その中で仮想的にマージして見せます。

● 下に Read Only なファイルシステム層 (lowerdir) を積み重ねます。

● lowerdir の上に書き込み可能なファイルシステム層(upperdir) をひとつ置きます。

● ファイルシステムへの変更は upperdir で吸収します。

Page 17: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs を使う準備

Page 18: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs を使う準備

Overlayfs をマウントする際、以下のようなコマンドを実行します。

mount -t overlayfs -o \ lowerdir=lower,upperdir=upper,workdir=work \overlayfs mountpointdir

少し複雑ですので、ひとつずつ見ていきましょう( 「 \」は行変更を示します。念のため。 )

Page 19: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs を使う準備

-t overlayfs

これは、マウントしたいファイルシステムが Overlayfs であることを指定しています。

Page 20: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の使い方

-o \lowerdir=lower,upperdir=upper,workdir=work

オプションをカンマ区切りで指定します。指定するオプションは以下のとおりです。オプション 概要

lowerdir lowerdir として重ねあわせるファイルシステムイメージ(ディレクトリ ) のパスを指定。複数指定可能。

upperdir upperdir として重ねあわせるファイルシステムイメージ(ディレクトリ ) のパスを指定。書き込み可能なローカルのファイルシステムの必要がある。

workdir overlayfs が使う作業ディレクトリ。 upperdir と同じファイルシステムの名前空間内に存在する必要あり。upperdir を指定する際は、セットで指定。

Page 21: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs を使う準備

overlayfs mountpointdir

マウントする際はストレージデバイスを指定することが多いのですが、 overlayfs を使用するときに指定する「デバイス」は仮想的な「デバイス」という意味合いで overlayfs を指定します。

最後に仮想的にファイルシステム群をマージした結果を見せるためのマウントポイントを指定します。

Page 22: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き

Page 23: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き

今回は以下のディレクトリ構成で動きを見ます。

lowerdir

upperdirupfile updir

workdir

overlay

lowfile lowdir

注:今回は実験を簡単にするために、すべてのディレクトリ・ファイルは同一の名前空間内の ext4内にあります。

Page 24: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

overlayfs のマウントをしたあとで、 ls コマンドを使い、 overlay の中を見ます。すると、 upperdir と lowerdir がマージされたものが見えます。

lowerdir

upperdirupfile updir

overlay

lowfile lowdir

upfile updir lowfile lowdir

Page 25: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

2つのファイルシステムが「重ね合わせられ」ひとつのファイルシステムに見えることがわかります。

では、これをどうやって実現しているのでしょうか。ここで、カーネルのソースを読んでみたいと思います。

Page 26: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

ls を行う際、ディレクトリの中身を読むために libc のreaddir() が呼ばれます。glibc の場合、 readdir() を経由して、 getdents というシステムコールが呼ばれます。

getdents は最終的に iterate_dir() という関数を呼び出します。この関数は 2 つの引数を受け取ります。

Page 27: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

int iterate_dir(struct file *file, struct dir_context *ctx){ /* パラメータチェックなどは割愛 */ /* ディレクトリ内の最後のエントリに到達するまで */ if (!IS_DEADDIR(inode)) { /* 前処理は割愛 */ res = file->f_op->iterate(file, ctx); /* 後処理も割愛 */ } return res;}

ここで、 dir_context 構造体 (ctx) は以下 2点が役目です。 - ディレクトリの中をたどるごとに呼び出す処理を関数ポインタで渡す - 関数ポインタ経由で渡した処理が都度の結果を格納する

Page 28: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

ここで、 file->f_op->iterate()経由で ovl_iterate() が呼ばれます。これは Overlayfs依存の関数です。最初に、マージの必要がないケースを処理します。static int ovl_iterate(struct file *file, struct dir_context *ctx){ /* 略 */ /* * 該当ディレクトリは重ねあわせたファイルシステム間で * 重複していなくて、マージの必要がないディレクトリである * この場合、そのディレクトリの実体をそのまま読みだす。 */ if (od->is_real) { /* 略 */ return iterate_dir(od->realfile, ctx); }

Page 29: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

次に、 upper側と lower側で同名のディレクトリがあり、マージが必要なケースを処理します。該当ディレクトリに対するマージがこれまでにされておらず、結果が再利用できないケースの処理です。

/* 前ページからの続き */ /* マージが必要だが、マージ結果のキャッシュがない */ if (!od->cache) { struct ovl_dir_cache *cache; /* マージを行い、その結果を「キャッシュ」とする */ cache = ovl_cache_get(dentry); /* 略 */ }

Page 30: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

最後に、得られた結果 (キャッシュ ) をたどり、ユーザから渡されたバッファにコピーします。コピー自体は ctx の関数ポインタで渡されたfilldir で実施します。

/* 前ページの続き */ /* 辿れるだけディレクトリの中身をたどる */ while (od->cursor != &od->cache->entries) { p = list_entry(od->cursor, struct ovl_cache_entry, l_node); /* 「消された」ことになっていない場合、 */ if (!p->is_whiteout) /* 呼び出し元から渡された ctx の中の関数ポインタを呼ぶ */ if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) break; /* 略 */

Page 31: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - ls( ディレクトリを読む ) -

関数ポインタ (filldir) があるため、呼び出し構造がややわかりにくいです。そこで、ここまでの話を以下の概要図でまとめました。

ユーザ側ユーザ側 iterate_diriterate_dir filldirfilldir ovl_iterateovl_iterate 該当レイヤのiterate

該当レイヤのiterate

マージの必要がないケースの呼び出し

マージの必要があるケース

ディレクトリの中身をユーザ側バッファに

コピー

ディレクトリの中身をユーザ側バッファに

コピー

Page 32: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - upper 側 file への write -

upper側にあるファイルを Overlayfs経由で書き換えると、 upper側のファイルが直接書き換わります。

では、これをどうやって実現しているのでしょうか。ここで、カーネルのソースを読んでみたいと思います。

Page 33: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - upper 側 file への write -

upper側にあるファイルを書き込み可能で open() します。open() からシステムコールを経由して、 vfs_open() が呼び出され、関数ポインタ経由で ovl_d_select_inode() が呼ばれます。

int vfs_open(const struct path *path, struct file *file, const struct cred *cred){

/* 略 */ if (dentry->d_flags & DCACHE_OP_SELECT_INODE) { inode = dentry->d_op->d_select_inode(dentry, file->f_flags); if (IS_ERR(inode)) return PTR_ERR(inode); }

Page 34: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - upper 側 file への write -

ovl_d_select_inode() の中で ovl_path_real() を呼び出します。これにより、実体 ( ここでは upper側のファイル ) のパス情報 (struct path) を取得します。

struct inode *ovl_d_select_inode(...引数省略 ...){

/* 略 */ type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(...引数省略 ...)) {

/* 後述 */ }

/* 略 *//* upper側の inode を返すことで、呼び出し元で upper側のファイル

を open() する。これで以後のアクセスは upper側に行われる */ return d_backing_inode(realpath.dentry);}

Page 35: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file への write -

lower側にあるファイルを overlayfs経由で書き換えると、 upper側に書き換え対象と同名のファイルが生成され、 upper側のファイルが書き換わります。

これにより、以後は upper側の「書き換えられた」ファイルが見え、 lower側ファイルは書き換わりません。

では、これをどうやって実現しているのでしょうか。ここで、カーネルのソースを読んでみたいと思います。

Page 36: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file への write -

vfs_open() 自体の動きは、先に説明した upper側にあるファイルへの書き込みと同様です。

しかし、 d_select_inode経由で呼ばれる ovl_d_select_inodeの挙動が異なります。それは、 copy_upという処理が行われることです。

Page 37: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file への write -

struct inode *ovl_d_select_inode(...引数略 ...){ /* 略 */ type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(...引数略 ...)) { /* 略 */

/* ここで lower側にあるファイルを upper側にコピーします */ err = ovl_copy_up(dentry); /* 略 */ /* * ファイルを upper側にコピーした後でパス情報を返し、 * 書き込み処理が upper側ファイルに行われるようにする */ ovl_path_upper(dentry, &realpath);

Page 38: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file への write -

ovl_copy_upでは以下の図のようなことを実施します。わざわざ workdir を中継する理由は、変更をアトミック ( 「完全失敗で何もない」か、「完全成功でファイルが upper側に生成される」かのどちらか ) にしたいためと推定します。 (煩雑さを避けるため、詳細については相当略しています。 )

lower

upper

手順 2.workdir内のファイルをリネームする

手順 1.一旦 workdirにコピー

workdir

upper と lower は異なるファイルシステム。そのため、コピー失敗の

リスクもある。そこで、 workdir を中継。そうすることで失敗時の

変更は workdir にとどまり、upper から残骸などが

見えない。

Page 39: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

lower側にあるファイルを overlayfs経由で削除しても lower側のファイルは消えません。その代わりに、「 whiteout 」という処理が upper側に行われ、あたかも該当ファイルが消えたかのように見せかけます。

では、これをどうやって実現しているのでしょうか。ここで、カーネルのソースを読んでみたいと思います。

Page 40: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

ファイルを削除する際、 unlinkat() システムコールを呼びます。この関数は最終的に vfs_unlink() を呼び出します。

vfs_unlink() では関数ポインタ経由で ovl_unlink() を呼び出します。

さらに ovl_unlink() では ovl_do_remove() を呼び出します。

Page 41: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

Overlayfs を経由したファイル削除には、以下の 3パターンがあります。

lower

upper A

overlay

B

A B

C

削除 削除

C

削除

パターン1 パターン 2 パターン 3

C

Page 42: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

static int ovl_do_remove(struct dentry *dentry, bool is_dir){ /* 略 ( 大切な処理も含むが、煩雑さを避けるため略 */ type = ovl_path_type(dentry); /* upper側にだけあるファイルは、 upper側ファイルを直接消す */ if (OVL_TYPE_PURE_UPPER(type)) { err = ovl_remove_upper(dentry, is_dir); /* lower側にも該当ファイルがある場合、 whiteout処理を実行 */ } else { /* 略 */ err = ovl_remove_and_whiteout(dentry, is_dir); /* 略 */ }

パターン 1.upper 側を直接削除

Page 43: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

whiteout処理とは、「 upper側に特殊なファイルを作成し、あたかも lower側にあるファイルが消されたかのように見せかける」処理です。先のパターン 2,3 の場合、必要です。やり方は Overlayfs のバージョンによって異なります。

Overlayfs のバージョン

処理概要

V1 消そうとしているファイルと同名のシンボリックリンクを upper側に作り、拡張属性 "trusted.overlay.whiteout=y"を付与する。

v2 消そうとしているファイルと同名の charcter device file(major0:minor0) を upper側に作成する

Page 44: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir){ /* 略 */ if (is_dir) { /* ディレクトリを消す場合の処理。今回は略 */ }

/* 略 */ /* ここで whiteout処理を実施 */ whiteout = ovl_whiteout(workdir, dentry); /* 略 */

upper = ovl_dentry_upper(dentry);

Page 45: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

/* lower側にのみ消去対象のファイルがある場合 (パターン 2) */ if (!upper) { /* * upper側にディレクトリエントリを作成する。 * "lookup"なのだが、名前とディレクトリで検索して見つ *からない場合、 inode が空のディレクトリエントリが返る。 * ( ここでは新規に whiteout のためのファイルを生成したと * 考えれば良い ) */ upper = lookup_one_len(dentry->d_name.name, upperdir, dentry->d_name.len); /* 略 */ err = ovl_do_rename(wdir, whiteout, udir, upper, 0); /* 略 */

Page 46: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

Overlayfs の動き - lower 側 file の削除 -

/* * 少なくとも upper側に消去対象のファイルがある場合 * (upper側と lower側の双方にあるケース。パターン 3.) * 単純に upper側のファイルを消すと、重ね合わせにより lower * 側のファイルが見えてしまい「消せていない」状態になる。 * よって、 upper側のファイルを whiteout のファイルに置き換える */ } else { /* 略 */ err = ovl_do_rename(wdir, whiteout, udir, upper, flags); /* 略 */ } /* 略 */

Page 47: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

おわりに

ここまで駆け足で Overlayfs の概要と実装の概要をみてきました。しかし、細かいところについては時間の関係で説明できていません。ソースを読んだ箇所については、細かい話を近いうちに Qiita(http://qiita.com/akachochin) にまとめたいと思います。

Page 48: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

ソースを自分で読みたい人のために

いくつかアドバイスです。

1.overlayfs内に現れる dentry 構造体がどこのレイヤの何のファイル /ディレクトリを指しているのか意識しましょう。

2.Linux のファイルシステム層について基本的な事項を学んでみましょう。日本語で入手できる資料では、「 Linux カーネル解読室」第 15 〜 17 章が最も助けになると思います。

3.ftrace を使って、カーネル内関数呼び出しを追いかけましょう。非常にはかどります。

Page 49: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

ソースを自分で読みたい人のために

4.Linux ファイルシステム層のよく使われる関数 (特にlookup 系 ) に慣れましょう。そして、挙動がわからなければ、ソースを読んでみましょう。そうすることによってファイルシステムの実装に慣れてきます。

5. データ構造をメモりながら読みましょう。今回紹介しませんでしたが、 mount処理 ,lookup 系処理を読むと、全体感が捉えやすくなるでしょう。

Page 50: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

参考文献・ Web ページ

Webページ

● 「 LXC で学ぶコンテナ入門 -軽量仮想化環境を実現する技術第 18 回  Linux カーネルのコンテナ機能 [7]overlayfs 」http://gihyo.jp/admin/serial/01/linux_containers/0018

● 「 Understand images, containers, and storage drivers 」https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/

● そのファイル、安全に更新できていますか?(アトミックなファイル操作:前編)https://heartbeats.jp/hbblog/2013/10/atomic01.html

Page 51: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

参考文献・ Web ページ

文献 (敬称略 )

● 「 Linux カーネル 2.6解読室」高橋浩和 /小田逸郎 /山幡為佐久 著

● 「プログラマのための Docker 教科書」阿佐志保 著

● 「 Understanding the Linux Kernel(3rd edition) 」DANIEL P.BOVET & MARCO CESATI 著

● 「 Linux Kernel Development(3rd Edition) 」Robert Love 著

Page 52: ちょっとOverlayfsの実装、読んでみました(A brief report of overlayfs source code reading)

ご静聴ありがとうございました。