Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

overview of overlayfs

Avatar for akachochin akachochin
October 29, 2016

overview of overlayfs

This slide share the overview of overlayfs.
- what feature it privides with some images.
- go through Linux filessytem code.
It would be useful to get outlines of overlayfs.
(This slide is written in Japanese, but images and codes in this slide would make it easy to get outlines.)

Avatar for akachochin

akachochin

October 29, 2016
Tweet

More Decks by akachochin

Other Decks in Technology

Transcript

  1. 䜿甚䞊の泚意です。 • 読んだ゜ヌスは、 linux_4.4.0-21.37 (Ubuntu16.04) です。 自宅で䞻に䜿っおいるのが Ubuntu16.04 で、 ftrace

    した結果 ず突き合わせるずいろいろはかどるからです。 • プレれンの時間的な制玄などから、现かいこずは説明しきれた せん。なので、厳密さよりもわかりやすさを優先したり、話を 端折ったりしおいる箇所が結構ありたす。ご了承のほどを。
  2. Overlayfs っお䜕 この章を曞くにあたり、「 LXC で孊ぶコンテナ入門 軜量仮 想化環境を実珟する技術第 18 回  Linux

    カヌネルのコンテナ 機胜 [7]overlayfs 」ずいう蚘事を倧いに参考ずしたした。 蚘事を曞かれた加藀さん、倧倉感謝です。
  3. Overlayfs っお䜕 Overlayfs は Union filesystem の䞀皮です。 Union filesystem は耇数のファむルシステムをひず぀の堎所で

    マりントし、仮想的にたずめおあたかもひず぀のファむルシス テムであるかのように芋せる技術です。 Linux 3.18 のずきに Linux カヌネルにマヌゞされたした。 たた、 Docker では 1.4.0 で overlayfs に察応したした。
  4. Overlayfs っお䜕 ずはいっおも、むメヌゞしづらいので、 Docker のコンテナを 䟋に説明したす。 ・ Docker の Image

    Layers は ReadOnly なファむルシステム 局を参照しおいたす。 ・ Docker がコンテナを䜜るず き、 Image の䞊に Writeable な局 ( コンテナ局 ) が远加さ れたす。 ※https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/ より図を匕甚
  5. 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 から 芋たずきに芋えるもの )
  6. Overlayfs っお䜕 lower から upper ぞコピヌしお・・ ・ (copy up) lower

    upper A overlay B A B B Write Write upper 偎ぞ 曞き蟌み overlayfs 経由でファむルぞの曞き蟌みを行うず・・・ • upper 偎→ upper 偎のファむルが曞き換わる • lower 偎→ lower 偎から upper 偎にファむルがコピヌされ、 upper 偎が曞き換 わる
  7. Overlayfs っお䜕 overlayfs 経由でファむルの削陀を行うず・・・ • upper 偎→ upper 偎のファむルが削陀される •

    lower 偎→ upper 偎に「削陀」を瀺すファむルを生成、 lower 偎ファむルを「芆 う」。 lower upper A overlay B A B 削陀 削陀 「削陀」を瀺すファむルが䜜成さ れ、 lower のファむルが「芋えなく なる」。 (whiteout)
  8. Overlayfs っお䜕 ここたで芋たこずをたずめたす • overlayfs は、 lowerdir ず upperdir をひず぀のマりントポむ

    ントでマりントし、その䞭で仮想的にマヌゞしお芋せたす。 • 䞋に Read Only なファむルシステム局 (lowerdir) を積み重ね たす。 • lowerdir の䞊に曞き蟌み可胜なファむルシステム局 (upperdir) をひず぀眮きたす。 • ファむルシステムぞの倉曎は upperdir で吞収したす。
  9. Overlayfs を䜿う準備 Overlayfs をマりントする際、以䞋のようなコマンドを実行し たす。 mount -t overlayfs -o \

    lowerdir=lower,upperdir=upper,workdir=work \ overlayfs mountpointdir 少し耇雑ですので、ひず぀ず぀芋おいきたしょう ( 「 \ 」は行倉曎を瀺したす。念のため。 )
  10. Overlayfs の䜿い方 -o \ lowerdir=lower,upperdir=upper,workdir=work オプションをカンマ区切りで指定したす。指定するオプショ ンは以䞋のずおりです。 オプション 抂芁 lowerdir

    lowerdir ずしお重ねあわせるファむルシステムむメヌゞ ( ディレクトリ ) のパスを指定。耇数指定可胜。 upperdir upperdir ずしお重ねあわせるファむルシステムむメヌゞ ( ディレクトリ ) のパスを指定。曞き蟌み可胜なロヌカ ルのファむルシステムの必芁がある。 workdir overlayfs が䜿う䜜業ディレクトリ。 upperdir ず同じフ ァむルシステムの名前空間内に存圚する必芁あり。 upperdir を指定する際は、セットで指定。
  11. Overlayfs の動き 今回は以䞋のディレクトリ構成で動きを芋たす。 lowerdir upperdir upfile updir workdir overlay lowfile

    lowdir 泚今回は実隓を簡単にするた めに、すべおのディレクトリ ・ファむルは同䞀の名前空間 内の ext4 内にありたす。
  12. Overlayfs の動き - ls( ディレクトリを読む ) - overlayfs のマりントをしたあずで、 ls

    コマンドを䜿 い、 overlay の䞭を芋たす。 するず、 upperdir ず lowerdir がマヌゞされたものが芋えた す。 lowerdir upperdir upfile updir overlay lowfile lowdir upfile updir lowfile lowdir
  13. Overlayfs の動き - ls( ディレクトリを読む ) - ls を行う際、ディレクトリの䞭身を読むために libc

    の readdir() が呌ばれたす。 glibc の堎合、 readdir() を経由しお、 getdents ずいうシス テムコヌルが呌ばれたす。 getdents は最終的に iterate_dir() ずいう関数を呌び出した す。この関数は 2 ぀の匕数を受け取りたす。
  14. 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 点が圹目です。 - ディレクトリの䞭をたどるごずに呌び出す凊理を関数ポむンタで枡す - 関数ポむンタ経由で枡した凊理が郜床の結果を栌玍する
  15. 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); }
  16. Overlayfs の動き - ls( ディレクトリを読む ) - 次に、 upper 偎ず

    lower 偎で同名のディレクトリがあり、マヌゞが必芁な ケヌスを凊理したす。該圓ディレクトリに察するマヌゞがこれたでにされ おおらず、結果が再利甚できないケヌスの凊理です。 /* 前ペヌゞからの続き */ /* マヌゞが必芁だが、マヌゞ結果のキャッシュがない */ if (!od->cache) { struct ovl_dir_cache *cache; /* マヌゞを行い、その結果を「キャッシュ」ずする */ cache = ovl_cache_get(dentry); /* 略 */ }
  17. 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; /* 略 */
  18. Overlayfs の動き - ls( ディレクトリを読む ) - 関数ポむンタ (filldir) があるため、呌び出し構造がややわかりにくいで

    す。そこで、ここたでの話を以䞋の抂芁図でたずめたした。 ナヌザ偎 ナヌザ偎 iterate_dir iterate_dir filldir filldir ovl_iterate ovl_iterate 該圓レむダの iterate 該圓レむダの iterate マヌゞの必芁が ないケヌスの呌び出し マヌゞの必芁が あるケヌス ディレクトリの䞭身を ナヌザ偎バッファに コピヌ ディレクトリの䞭身を ナヌザ偎バッファに コピヌ
  19. Overlayfs の動き - upper 偎 file ぞの write - upper

    偎にあるファむルを Overlayfs 経由で曞き換える ず、 upper 偎のファむルが盎接曞き換わりたす。 では、これをどうやっお実珟しおいるのでしょうか。 ここで、カヌネルの゜ヌスを読んでみたいず思いたす。
  20. 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); }
  21. 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); }
  22. Overlayfs の動き - lower 偎 file ぞの write - lower

    偎にあるファむルを overlayfs 経由で曞き換える ず、 upper 偎に曞き換え察象ず同名のファむルが生成さ れ、 upper 偎のファむルが曞き換わりたす。 これにより、以埌は upper 偎の「曞き換えられた」ファむル が芋え、 lower 偎ファむルは曞き換わりたせん。 では、これをどうやっお実珟しおいるのでしょうか。 ここで、カヌネルの゜ヌスを読んでみたいず思いたす。
  23. Overlayfs の動き - lower 偎 file ぞの write - vfs_open()

    自䜓の動きは、先に説明した upper 偎にあるファ むルぞの曞き蟌みず同様です。 しかし、 d_select_inode 経由で呌ばれる ovl_d_select_inode の挙動が異なりたす。 それは、 copy_up ずいう凊理が行われるこずです。
  24. 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);
  25. Overlayfs の動き - lower 偎 file ぞの write - ovl_copy_up

    では以䞋の図のようなこずを実斜したす。 わざわざ workdir を䞭継する理由は、倉曎をアトミック ( 「完党倱敗で䜕 もない」か、「完党成功でファむルが upper 偎に生成される」かのどちら か ) にしたいためず掚定したす。 ( 煩雑さを避けるため、詳现に぀いおは 盞圓略しおいたす。 ) lower upper 手順 2. workdir 内のファむル をリネヌムする 手順 1. 䞀旊 workdir にコピヌ workdir upper ず lower は 異なるファむルシステム。 そのため、コピヌ倱敗の リスクもある。 そこで、 workdir を䞭継。 そうするこずで倱敗時の 倉曎は workdir にずどたり、 upper から残骞などが 芋えない。
  26. Overlayfs の動き - lower 偎 file の削陀 - lower 偎にあるファむルを

    overlayfs 経由で削陀しおも lower 偎のファむルは消えたせん。その代わりに、「 whiteout 」ず いう凊理が upper 偎に行われ、あたかも該圓ファむルが消え たかのように芋せかけたす。 では、これをどうやっお実珟しおいるのでしょうか。 ここで、カヌネルの゜ヌスを読んでみたいず思いたす。
  27. Overlayfs の動き - lower 偎 file の削陀 - ファむルを削陀する際、 unlinkat()

    システムコヌルを呌びた す。この関数は最終的に vfs_unlink() を呌び出したす。 vfs_unlink() では関数ポむンタ経由で ovl_unlink() を呌び出 したす。 さらに ovl_unlink() では ovl_do_remove() を呌び出したす。
  28. Overlayfs の動き - lower 偎 file の削陀 - Overlayfs を経由したファむル削陀には、以䞋の

    3 パタヌンが ありたす。 lower upper A overlay B A B C 削陀 削陀 C 削陀 パタヌン パタヌン 2 パタヌン 3 C
  29. 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 偎を盎接削陀
  30. Overlayfs の動き - lower 偎 file の削陀 - whiteout 凊理ずは、「

    upper 偎に特殊なファむルを䜜成し、 あたかも lower 偎にあるファむルが消されたかのように芋せ かける」凊理です。先のパタヌン 2,3 の堎合、必芁です。 やり方は Overlayfs のバヌゞョンによっお異なりたす。 Overlayfs のバヌゞョ ン 凊理抂芁 V1 消そうずしおいるファむルず同名のシンボリック リンクを upper 偎に䜜り、拡匵属 性 "trusted.overlay.whiteout=y" を付䞎する。 v2 消そうずしおいるファむルず同名の charcter device file(major0:minor0) を upper 偎に䜜成す る
  31. 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);
  32. 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); /* 略 */
  33. Overlayfs の動き - lower 偎 file の削陀 - /* *

    少なくずも upper 偎に消去察象のファむルがある堎合 * (upper 偎ず lower 偎の双方にあるケヌス。パタヌン 3.) * 単玔に upper 偎のファむルを消すず、重ね合わせにより lower * 偎のファむルが芋えおしたい「消せおいない」状態になる。 * よっお、 upper 偎のファむルを whiteout のファむルに眮き換える */ } else { /* 略 */ err = ovl_do_rename(wdir, whiteout, udir, upper, flags); /* 略 */ } /* 略 */
  34. ゜ヌスを自分で読みたい人のために いく぀かアドバむスです。 1.overlayfs 内に珟れる dentry 構造䜓がどこのレむダの䜕の ファむル / ディレクトリを指しおいるのか意識したしょう。 2.Linux

    のファむルシステム局に぀いお基本的な事項を孊んで みたしょう。日本語で入手できる資料では、「 Linux カヌネ ル解読宀」第 15 〜 17 章が最も助けになるず思いたす。 3.ftrace を䜿っお、カヌネル内関数呌び出しを远いかけたし ょう。非垞にはかどりたす。
  35. ゜ヌスを自分で読みたい人のために 4.Linux ファむルシステム局のよく䜿われる関数 ( 特に lookup ç³» ) に慣れたしょう。 そしお、挙動がわからなければ、゜ヌスを読んでみたしょ

    う。そうするこずによっおファむルシステムの実装に慣れお きたす。 5. デヌタ構造をメモりながら読みたしょう。今回玹介したせ んでしたが、 mount 凊理 ,lookup 系凊理を読むず、党䜓感が 捉えやすくなるでしょう。
  36. 参考文献・ 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
  37. 参考文献・ Web ペヌゞ 文献 ( 敬称略 ) • 「 Linux

    カヌネル 2.6 解読宀」 高橋浩和 / 小田逞郎 / 山幡為䜐久 著 • 「プログラマのための Docker 教科曞」 阿䜐志保 著 • 「 Understanding the Linux Kernel(3rd edition) 」 DANIEL P.BOVET & MARCO CESATI 著 • 「 Linux Kernel Development(3rd Edition) 」 Robert Love 著