Linuxカーネル4.1のメモリレイアウト(ドラフト)

はじめに

前回のLinuxカーネル4.1のSLUBアローケータ(ドラフト) - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモと同じくドラフト版公開です。

カーネルのバージョンは4.1系です。

文書自体も完成版ではないし、markdownから手作業ではてなblogにコピペして修正してるので章立てとか変になってるところとかあるかもしれませんが気にしないでください。 一部は文書修正してます。

ユーザプロセス空間とカーネル空間

Linux x86_64では48bit(256TiB)のアドレス空間を使用できます。この256TiBの範囲のうち、128TiBをユーザープロセスが使用し、残りの128TiBをカーネルが使用します。32bitのカーネルではユーザプロセスに3GiB、カーネルに1GiBの割当でしたので、64bit環境では使用可能なメモリを使用量が大幅に増えました。 Linuxではこの256TiBのアドレス空間をプロセスとカーネルが使用しますが、0〜0xffff800000000000までのユーザプロセス空間はプロセスごとに割り当てられ、後半のカーネル空間に関しては常に1つとなり、「図_ユーザプロセス空間とカーネル空間」のようになります。

f:id:masami256:20190510203636p:plain

図_ユーザプロセス空間とカーネル空間

この256TiBのメモリはアドレスの範囲によって使用目的が決まっています。その内訳を「表_メモリマップ」に示します。

x86_64のメモリレイアウト
開始アドレス 終了アドレス サイズ 内容
0x0000000000000000 0x00007fffffffffff 128TiB ユーザプロセス空間
0xffff800000000000 0xffff87ffffffffff 8TiB ハイパーバイザー向けに予約
0xffff880000000000 0xffffc7ffffffffff 64TiB ダイレクトマップ領域
0xffffc80000000000 0xffffc8ffffffffff 1TiB 未使用
0xffffc90000000000 0xffffe8ffffffffff 32TiB vmalloc/ioremapが使用
0xffffe90000000000 0xffffe9ffffffffff 1TiB 未使用
0xffffea0000000000 0xffffeaffffffffff 1TiB 仮想メモリマップ
0xffffeb0000000000 0xffffebffffffffff 1023GiB 未使用
0xffffec0000000000 0xfffffc0000000000 16TiB kasan shadow memory
0xfffffc0000000000 0xfffffeffffffffff 3072GiB 未使用
0xffffff0000000000 0xffffff7fffffffff 512GiB スタック領域
0xffffff8000000000 0xffffffff7fffffff 509GiB 未使用
0xffffffff80000000 0xffffffffa0000000 512MiB カーネルテキストマッピング領域。物理メモリ0~512MiB
0xffffffffa0000000 0xffffffffff5fffff 1525MiB カーネルモジュールマッピング領域
0xffffffffff600000 0xffffffffffdfffff 8MiB vsyscallsで使用
0xffffffffffe00000 0xffffffffffffffff 2MiB 未使用

表_メモリマップ

この内訳はDocumentation/x86/x86_64/mm.txtにて確認することができます。 ユーザープロセス空間は128TiBをフルに使用しますが、カーネル空間の場合、ある特定の範囲を使用目的毎に分けています。128TiB全てが使用されているわけではなく、現在は未使用の領域として空いているところもあります。

また、EFIを使用するシステムでは図_メモリマップのように0xffffffef00000000から0xffffffff00000000の範囲をEFIのランタイムサービスにマッピングします。

f:id:masami256:20190510203723p:plain

図_メモリマップ

ダイレクトマップ(ストレートマップ)領域

カーネルは全ての物理メモリをこの領域にマッピングします。x86_32アーキテクチャではアーキテクチャの制限として、物理アドレスを直接マッピングできるのは896MiBまでで、それ以上のアドレスを使用するためにHIGHMEM領域を使用していましたが、x86_64アーキテクチャではHIGHMEM領域が不要になり、ダイレクトマップ領域だけを使用します。

ダイレクトマップ領域の開始アドレスはPAGE_OFFSETとして定義されていています。

arch/x86/include/asm/page_types.h
#define PAGE_OFFSET             ((unsigned long)__PAGE_OFFSET)

arch/x86/include/asm/page_64_types.h
#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)

図_PAGE_OFFSETの定義

物理アドレスからリニアアドレスへの変換は__vaマクロを使用します。この場合は物理アドレスに対してPAGE_OFFSETを足すことでリニアアドレスを得ることができます。

#define __va(x)                 ((void *)((unsigned long)(x)+PAGE_OFFSET))

リニアアドレスから物理アドレスへの変換は__pa関数マクロです。このマクロの実体は__phys_addr_nodebug関数です。x86_32ではアドレスからPAGE_OFFSETを引くだけでアドレスを計算できたのですが、x86_64ではカーネルテキストマッピング領域の開始アドレス 0xffffffff80000000(__START_KERNEL_map)を基準としてアドレスの計算を行います。この関数で使用するphys_baseは通常0となっています。アドレスの変換は、「図_リニアアドレスから物理アドレスへの変換」のように行います

f:id:masami256:20190510203830p:plain

図_リニアアドレスから物理アドレスへの変換

vmalloc/ioremap領域

vmalloc関数やioremap関数などでメモリを確保する場合、アドレスをこの領域から割り当てます。vmalloc関数については別記事

Linuxカーネル4.1のvmalloc()(ドラフト) - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ

にて説明します。この領域で使用するページフレームは物理的に連続していませんが、論理的に連続します。

仮想メモリマップ

この領域は主にページフレーム番号とpage構造体の相互変換に使用します。ページフレーム番号からページ構造体を取得するには__pfn_to_pageマクロ、page構造体からページフレーム番号の取得には__page_to_pfnマクロを使用します。

/* memmap is virtually contiguous.  */
#define __pfn_to_page(pfn)      (vmemmap + (pfn))
#define __page_to_pfn(page)     (unsigned long)((page) - vmemmap)

図_ページフレーム番号とpage構造体の変換インターフェース

これらの変換操作にはグローバル変数のvmemmapに設定されている仮想メモリマップ領域の開始アドレスを基準として、このアドレスに対してページフレーム番号を足すことで、該当のpage構造体を取得、また、page構造体のアドレスからvmemmapを減算することで、ページフレーム番号の取得を行います。

%esp fixup stack

このスタックはPAGE_SIZEが4096の場合、各CPUに対して64個のスタックを読み込み専用として作成します。このスタックはministacksと呼ばれます。 ministacksはStack-Segment Fault(SS)からiret命令により、カーネルからユーザランドへ制御が戻る時に、iretで使用していたスタックフレームをLDTにコピーしてからユーザランドへ戻ります。 この後、General Faultなどが発生した場合はInterrupt Stack Tableから専用のスタックを使用します。 このような読み込み用のスタックを使用するのはセキュリティ上の理由です(注1)。iret命令は16bitのセグメントを元に戻しますが、%espの16〜31bitはカーネルのスタックを指しているため、カーネルの情報が漏れてしまいます。この状況に対応するため、専用のスタックを用意してiret命令から戻るようになっています。

カーネルテキスト領域

物理メモリのアドレス0〜512MiBをこの範囲にマッピングします。この領域の開始アドレスは__START_KERNEL_mapとして定義されています。この領域にはカーネルマッピングするため、このアドレス範囲に対して操作を行うことはありませんが、先に見たように__paマクロによる物理アドレスの取得など、アドレスを扱う場合に__START_KERNEL_mapを利用することがあります。

モジュールマッピング領域

カーネルモジュールをロードする領域です。この領域はカーネルテキストマッピング領域の直後に位置します。

#define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
#define MODULES_END      _AC(0xffffffffff000000, UL)
#define MODULES_LEN   (MODULES_END - MODULES_VADDR)

図_モジュールマッピング領域の定義

カーネルモジュールをロードする時にmodule_alloc関数が__vmalloc_node_range関数を用いて、モジュールのために確保するメモリ領域をMODULES_VADDRからのMODULES_ENDまでの範囲を指定します。

vsyscall

vsyscallのために割り当てられた領域で、開始アドレスはVSYSCALL_ADDRとして以下のように定義されています。値は0xffffffffff600000となります。

10 #define VSYSCALL_ADDR (-10UL << 20)

vsyscall領域は/proc/pid/mapsファイルにて、1ページ分がマッピングされていることを確認できます。

$ cat /proc/self/maps
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
固定マップ領域

機能によって、特定のアドレスにメモリを割り当てて使用したいという要求があり、これを実現するのが固定マップ領域です。固定マップ領域は0xffffffffff7ff000からの領域でアドレスの低位に向かって使用します。 固定マップ領域で使用する機能目的ごとのアドレスの定義はarch/x86/include/asm/fixmap.hで、enumのfixed_addressesで各領域ごとにインデックスが決められています。

固定マップ領域のインデックス(fixed_addresses)からリニアアドレスへの変換は__fix_to_virtマクロ、リニアアドレスからインデックス番号への変換は__virt_to_fixマクロで行います。

20 #define __fix_to_virt(x)        (FIXADDR_TOP - ((x) << PAGE_SHIFT))
21 #define __virt_to_fix(x)        ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)

FIXDADDR_TOPマクロは以下のように定義されています。VSYSCALL_ADDRはvsyscall領域の開始アドレスで、x86_64では0xffffffffff600000となります。

#define FIXADDR_TOP     (round_up(VSYSCALL_ADDR + PAGE_SIZE, 1<<PMD_SHIFT) - \
                         PAGE_SIZE)

固定マップ領域の確保はset_fixmap関数にて行います。これはマクロで__set_fixmap関数を呼び出します。この関数の実装はCPUアーキテクチャに依存します。x86_64アーキテクチャでは__native_set_fixmap関数が使われます。固定マップ領域の設定は先に説明した__fix_to_virtマクロによるリニアアドレスへの変換を行い、変換結果のアドレスをPTEテーブルへの登録を行います。

例えば、固定マップ領域のインデックス「VSYSCALL_PAGE」は0x1ffで、このインデックスに対するアドレスは0xffffffffff600000となります。この値は先に見たようにvsyscall領域のアドレスです。よって、vsyscall領域は固定マップ領域の仕組みを利用して、アドレスを固定して確保していることがわかります。 固定マップ領域のインデックス範囲は0x1ff-0x600です。アドレスに変換すると0xffffffffff600000〜0xffffffffff1ff000となります。

デバッグの理論と実践 ―なぜプログラムはうまく動かないのか

デバッグの理論と実践 ―なぜプログラムはうまく動かないのか

Linuxカーネル4.1のSLUBアローケータ(ドラフト)

はじめに

本記事は過去に書いたけど諸事情により陽の目に出ていなかった文書です。完全版ではありません。satさんがスケジューラの記事を公開したのに影響され、自分も書いたものを死蔵させておくのはもったいないので公開することにしました。

qiita.com

カーネルのバージョンは4.1系です。

文書自体も完成版ではないし、markdownから手作業ではてなblogにコピペして修正してるので章立てとか変になってるところとかあるかもしれませんが気にしないでください。 一部は文書修正してます。

スラブアローケータ

Linuxにおけるメモリ確保の方法としてページ単位でメモリ確保を行うバディシステムがあります。バディアロケータはページ単位に管理を行うため、構造体など小規模なメモリを確保するために使用すると無駄が多くなってしまいます。そこで、スラブアローケータというメモリをより小さな単位で管理する仕組みを使用します。

スラブアローケータはアローケータの実装方式の一つで、Jeff Bonwick氏によりSolaris 2.4で最初に実装されました。今日ではスラブアローケータはSolarisだけでなく、LinuxFreeBSDなどのオペレーティングシステムや、memcachedのようなメモリ管理を効率的に行う必要があるミドルウェアでも採用されています。

スラブアローケータの説明に入る前に、基本的な用語を説明します。

  • スラブキャッシュ

スラブオブジェクトを管理します。スラブキャッシュはスラブオブジェクトの種類毎に作成します。メモリの確保や解放処理の要求の受付、スラブアローケータ内でのメモリ管理など、スラブアローケータの機能を提供します。スラブアローケータではメモリの確保時に実行するコンストラクタ関数を設定することもできます。Linuxではkmem_cache構造体がスラブキャッシュです。

  • スラブオブジェクト

スラブキャッシュが管理するオブジェクトです。スラブアローケータはこのスラブオブジェクトをメモリ確保要求時に返却します。

  • スラブ

スラブオブジェクトの集合です。スラブオブジェクトはバディアロケータよりページを確保し、そこにスラブオブジェクトを作成します。

  • freelist

slubアローケータにおいて、次のメモリ確保要求時に返却するするスラブオブジェクトを指すポインタです。

  • 使用中リスト

slubアローケータでは、スラブの管理には使用中リストを使用します。

スラブアローケータは管理するオブジェクトの単位でスラブキャッシュを作成します。たとえば、inode構造体用のスラブキャッシュ、task_struct構造体用のスラブキャッシュなど、通常は構造体毎にスラブキャッシュを作成します。こうして、特定の構造体用にメモリを確保する場合、その構造体に特化したアローケータよりメモリを確保を行います。このように特定のサイズに応じたアローケータを使用することで、メモリのフラグメンテーションを防ぎやすくなります。 任意のサイズのメモリを確保できるアローケータの場合、オブジェクトの確保と解放を繰り返していくうちに、メモリのフラグメンテーションが進み、空き領域の合計は十分にあるのに、メモリが断片化しているためまとまった量のメモリを確保できずに失敗する状況が発生します。

f:id:masami256:20190509234229p:plain

図_メモリのフラグメンテーション

「図_メモリのフラグメンテーション」では、最初のうちはメモリの確保のみが行われていたのでフラグメンテーションは発生していませんが、時刻が進みオブジェクトの解放が行われたため、メモリのフラグメンテーションが発生している状態です。未使用領域が2つあり、メモリ確保の要求がどちらかの未使用領域で満たせる場合は大丈夫ですが、要求サイズが各未使用領域のサイズよりも多いきい場合、仮に2つの未使用領域の合計サイズが、要求サイズよりも大きくてもメモリ確保に失敗します。 スラブアローケータは特定のサイズに特化しているため、このようなメモリのフラグメンテーションを防いでいます。

Linuxのスラブアローケータ

Linuxでは3種類のスラブアローケータの実装があり、カーネルコンフィギュレーションで使用するアロケータを変更できます。Linux 2.6.23よりslubがデフォルトのスラブアローケータとなっています。ディストリビューションによってはslabを選択しているものもあります。

slabアローケータ

slub登場以前はデフォルトのスラブアローケータでした。Solarisのスラブアローケータと同様の設計方針で実装されています。 スラブの管理にはスラブの状態に応じて複数のリストを使用します。使用するリストは、使用中オブジェクトが存在しないempty list、使用中オブジェクトと空きオブジェクトが存在するpartial list、全てオブジェクトが使用中のfull listの3つのリストがあります。 また、cache coloringと呼ぶ領域があり、ページフレーム内で空きオブジェクトの開始位置を他のスラブキャッシュとずらすために使用します。この機能は、スラブが複数存在する場合に、キャッシュラインの競合が起きないようにするための仕組みです。

slobアローケータ

シンプルな実装で、K&Rアローケータとも呼ばれています(注1)。slobアローケータはLinuxで使用可能なスラブアローケータの一つですが、slabやslubアローケータと違い、スラブをオブジェクトのサイズによって分けていません。一つのスラブで様々なサイスを取り扱います。これはプログラミング言語Cにおけるmalloc関数の実装と同様で、これがK&Rアローケータとも言われる所以です。

注1 プログラミング言語C で紹介されているUnixでのmalloc関数の実装に由来します。

slubアローケータ

slubアローケータはLinux固有のアローケータの実装です。本書ではslubアローケータについて解説します。

スラブオブジェクトの管理

slubアローケータでは空きスラブオブジェクトの管理はメタデータを別途持たせずに、スラブオブジェクトそのものに次の空きオブジェクトのアドレスを書き込みます。これにより、空きオブジェクトを管理するために別途メタデータを使用しなくてすむように設計されています。アドレスはスラブオブジェクトの先頭に書き込みます。最後の空きスラブオブジェクトには次のオブジェクトが無いため、NULLを設定します。

f:id:masami256:20190509234329p:plain

図_空きスラブオブジェクトの管理

使用中のスラブオブジェクトは特に管理を行いません。これはオブジェクトが不要になってオブジェクトを解放するときは、そのスラブオブジェクトのアドレスは自明なため、解放対象のオブジェクトが一意に決まるためです。

slubアロケータのスラブキャッシュはfreelist変数により、次回のスラブオブジェクト要求時に返却する空きスラブオブジェクトを参照しています。これにより、スラブ内に空きスラブオブジェクトが存在する間は高速にスラブオブジェクトを返却することができます。slubアローケータはスラブオブジェクトを返却する前に、次回のスラブオブジェクトのalloc時に返却するオブジェクトを参照するようにします。もし、最後の空きオブジェクトを返却した場合は、NULLを参照するようになります。この場合、次回の空きオブジェクト確保要求時に空きスラブオブジェクトの探索、もしくはスラブの作成を行うことになります。

f:id:masami256:20190509234421p:plain

図_空きスラブオブジェクトの確保

スラブオブジェクトを解放する場合、解放するスラブオブジェクトを次回のalloc要求時に返却するようにします。この時に次回のalloc要求時に返却予定だったスラブオブジェクトのアドレスを解放するスラブオブジェクトの先頭に書き込みます。

f:id:masami256:20190509234516p:plain

図_スラブオブジェクトの解放

slubアローケータではオブジェクトの確保に使用するスラブを常にCPUごとのメモリ域に置き、kmalloc関数などでスラブオブジェクトを要求された場合、このスラブから返却を行います。

f:id:masami256:20190509234657p:plain

図_percpuエリアにある構造体からスラブキャッシュの参照

使用中リスト

slubアローケータではスラブを管理する2つのリストがあります。一つはCPUと紐付いているスラブを管理するリストで、もう一つは、CPUとは紐付いておらず、スラブが所属するNUMAノード毎に管理するリストです。 CPUと紐付いている使用中リストに登録するスラブは1つだけ空きオブジェクトが存在するスラブです。また、このリストに登録できるスラブの数はcpu_partial変数にて設定されています。この値はスラブキャッシュ作成時に決定します。このリストはpage構造体のnext変数にてつながっています。この使用中リストは図_CPUに紐づく使用中リストのようになります。

f:id:masami256:20190509235150p:plain

図_CPUに紐づく使用中リスト

NUMAノードごとのは使用中リストは図_NUMAノードごとの使用中リストのように連結リストにて管理します。このリストには登録するスラブの上限はありません。

f:id:masami256:20190509235318p:plain

図_NUMAノードごとの使用中リスト

CPUと紐付いているスラブも、使用中リストにあるスラブもいずれも使用中ですが、CPUと紐付いているスラブは使用中リストでは管理しません。何かしらの理由でCPUとの紐付けを外す時に、CPUごとに保持しているスラブを使用中リストへ移動します。例えば、スラブ中に空きオブジェクトがなくなり、使用中リストから空きオブジェクトのあるスラブを探し、見つかったスラブとCPUごとのメモリ域ににあるスラブと交換したり、または、新規にスラブを作成した時に、作成したスラブをCPUごとのメモリ域に置き、CPUから参照されていたスラブを使用中リストに繋げるなどです。

CPUがスラブオブジェクトを取得するのに使用しているスラブはいずれの使用中リストの管理下にありません。スラブから空きオブジェクトが無くなった等の理由により、オブジェクトの取得対象のスラブで無くなった時に使用中リストに移動します。

スラブのマージ機能

slubとslabアロケータは同サイズのスラブキャッシュを一つのスラブキャッシュで管理する機能があり、デフォルトでこの機能は有効になっています。この機能を使用しない場合、128バイトのスラブオブジェクトを使用する機能が2つ存在した場合、スラブアローケータは2つの128バイトのスラブキャッシュを管理する必要があります。これは管理コストが増えたり、使用するページが違うため、CPUキャッシュヒット率が悪くなります。このような問題を解決するため、slab・slubアローケータでは同サイズのスラブキャッシュは一箇所で管理する仕様となっています。

マージの機能はslabとslubアローケータで詳細は異なっていて、slubアローケータでは、新規作成するスラブオブジェクトが以下の条件に当てはまる場合、新規にスラブキャッシュを作成せずに、既存のスラブキャッシュへのエイリアスを設定します。

  1. スラブオブジェクトのサイズが同一
  2. コンストラクタを使用しない
  3. slubのデバッグ機能を使用しない
  4. スラブ作成時のフラグにマージ機能を使用しないフラグが設定されていない

4のフラグについては「スラブキャッシュ生成時に設定するフラグ」にて説明します。

Chache Coloring

Cacje Coloringはスラブオブジェクトの開始アドレスをスラブ毎にずらすことによって、CPUのキャッシュライン競合を軽減させる仕組みです。slabアローケータはこの機能を採用していますが、 slubアローケータでは採用していません。CPUのキャッシュのライン調整に関してはCPUに任せる方針となっています(注1)。

注1: http://lkml.iu.edu/hypermail/linux/kernel/0808.0/1632.html

スラブの不活性化

slubアローケータはスラブオブジェクトを現在のCPUから参照されているスラブから返却します。参照されていないスラブはNUMAごとの使用中リストに繋がれますが、CPUごとのメモリ域にあるスラブをこの領域から外し、NUMAノードごとの使用中リストに移動することをスラブの不活性化と呼びます。

frozen状態

slubアローケータではスラブに対してfrozenという状態を設定します。fronzen状態にあるスラブはページの属性にPG_activeが設定されます。kmem_cache_alloc関数などによるオブジェクトの取得はこのスラブから行います。他のCPUはこのスラブからオブジェクトを取得することは出来ず、空きオブジェクトを追加する操作のみ行なえます。 CPUと紐付いているスラブはfrozen状態となり、スラブの不活性化によりCPUとのひも付けがなくなり、使用中リストにつなぐ時にスラブはfrozen状態が解除されます。

スラブキャッシュの情報

カーネルが管理しているスラブオブジェクトは/sys/kernel/debugディレクトリにて確認できます。Acpi-Namespaceなどシンボリックリンクとなっているものはslubアローケータのスラブマージ機能により、同サイズのオブジェクトを管理するスラブキャッシュとマージを行ったためです。

$ ls -l /sys/kernel/slab/  
total 0  
drwxr-xr-x 94 root root 0 May 20 20:19 ./  
drwxr-xr-x 11 root root 0 May 20 20:14 ../  
lrwxrwxrwx  1 root root 0 May 20 20:19 Acpi-Namespace -> :t-0000040/  
lrwxrwxrwx  1 root root 0 May 20 20:19 Acpi-Operand -> :t-0000072/  
lrwxrwxrwx  1 root root 0 May 20 20:19 Acpi-Parse -> :t-0000048/  
lrwxrwxrwx  1 root root 0 May 20 20:19 Acpi-ParseExt -> :t-0000072/  
lrwxrwxrwx  1 root root 0 May 20 20:19 Acpi-State -> :t-0000080/  
lrwxrwxrwx  1 root root 0 May 20 20:19 aio_kiocb -> :t-0000128/  
drwxr-xr-x  2 root root 0 May 20 20:19 anon_vma/  
lrwxrwxrwx  1 root root 0 May 20 20:19 anon_vma_chain -> :t-0000064/  
drwxr-xr-x  2 root root 0 May 20 20:14 :at-0000016/  
drwxr-xr-x  2 root root 0 May 20 20:14 :at-0000032/  
drwxr-xr-x  2 root root 0 May 20 20:14 :at-0000040/  

図_/sys/kernel/slabディレクト

ディレクトリ名には:tから始まるものや:atから始まるものがあります。これらのprefixは、スラブキャッシュ作成時に指定するflags引数に渡した(kmem_cache構造体のflags変数に設定されます)フラグを表します。表_slab_のprefixにフラグとprefixの対応を示します。:atや:dtなどはSLAB_CACHE_DMAとSLAB_NOTRACKの複合となります。これらのprefixはフラグが設定されていれば、そのprefixが使われるのですが、:tに関してはkmem_cache構造体のflagsとSLAB_NOTRACKのAND演算の結果が0の場合に設定されます。これはSLAB_NOTRACKがデバッグ機能の設定のため、値が0に設定されているためです。各フラグの内容については「スラブキャッシュ生成時に設定するフラグ」にて説明します。

prefix フラグ
:d SLAB_CACHE_DMA
:a SLAB_RECLAIM_ACCOUNT
:F SLAB_DEBUG_FREE
:t SLAB_NOTRACK

表_slabのprefix

個々のスラブキャッシュのディレクトリには以下のようなファイルが存在します。これらがスラブキャッシュの詳細になります。これらのファイルでスラブキャッシュが有効にしている機能などを確認できます。図_at-0000032ディレクトリは:at-0000032ディレクトリの様子です。

$ ls
./       align        cpu_partial  destroy_by_rcu  min_partial  objects_partial  partial          red_zone                  sanity_checks  slabs_cpu_partial  total_objects
../      alloc_calls  cpu_slabs    free_calls      objects      objs_per_slab    poison           remote_node_defrag_ratio  shrink         slab_size          trace
aliases  cache_dma    ctor         hwcache_align   object_size  order            reclaim_account  reserved                  slabs          store_user         validate

図_at-0000032ディレクト

slubアローケータのデータ構造

slubアローケータの主要な構造体には以下の4つの構造体です。

  • kmem_cache構造体
  • kmem_cache_cpu構造体
  • kmem_cache_node構造体
  • page構造体

これら4つの構造体のうち、page構造体以外はスラブアローケータのための構造体です。 スラブアローケータの核となる構造体はkmem_cache構造体です。kmem_cache構造体はslabやslubなど、スラブアローケータの実装によってデータ構造は違います。

名前 内容
cpu_slab cpuに紐付いているスラブキャッシュ
flags スラブキャッシュ生成時に指定したフラグ
min_partial 使用中のスラブキャッシュを保持できる最小の数。デフォルトは5、最大で10
size object_sizeをalignの境界に整列したサイズ
object_size メタデータを含まないスラブオブジェクトのサイズ
offset オブジェクトのサイズ+offsetで次の空きスラブオブジェクトを指す
cpu_partial cpu毎に保持できる使用中スラブキャッシュ数
oo スラブキャッシュ作成時に確保するページ数のオーダー
max スラブキャッシュ作成時に確保するページ数のオーダー数最大値
min スラブキャッシュ作成時に確保するページ数のオーダー数最小値
allocflags slabオブジェクトを確保する際に使用するgfpフラグ
refcount スラブマージ機能によってマージされたスラブキャッシュの数
ctor スラブキャッシュ作成時に呼び出すコンストラクタ関数
inuse スラブオブジェクトの使用数
align オブジェクトをsizeof(void *)の境界に整列した値。CPUのキャッシュラインに整列する場合は、先にCPUのキャッシュラインに合わせる
name スラブキャッシュの名前
list 作成したスラブキャッシュのリスト
memcg_params memory cgroup用の設定
remote_node_defrag_ratio 他のNUMAノードからスラブオブジェクトを取得する割合
node NUMAノード毎のスラブキャッシュ情報

表_kmem_cache構造体

slubオブジェクトのsize、object_sizeは図_スラブオブジェクトのようになります。

f:id:masami256:20190509235434p:plain

図_スラブオブジェクト

kmem_cache_cpu構造体はcpuコア毎にデータを保持します。page変数はpage構造体で、この変数はオブジェクトの返却を行うスラブのpage構造体を指します。 partial変数は使用中のスラブをつなぐリストとして使用しますが、list_head構造体は使用せず、page構造体のnext変数を利用してリスト管理を行います。このリストサイズはkmem_cache構造体のcpu_partial変数で設定します。

名前 内容
freelist 次の空きスラブオブジェクトへのポインタ
tid システムでユニークなトランザクションID
page スラブオブジェクトを管理しているページ
partial 使用中スラブの小規模なリスト

表_kmem_cache_cpu構造体

kmem_cache_node構造体はNUMAノード毎のデータを保持する構造体です。この構造体のデータ構造はスラブアローケータにより違い、ifdefによって、スラブアローケータ固有のメンバ変数が定義されます。slobアローケータでは使用しません。

名前 内容
list_lock sl[au]bアローケータ共通
nr_partial 使用中リストで管理しているデータ数
partial 使用中リストにあるスラブが使用しているpage構造体を管理するリスト

表_kmem_cache_node構造体

page構造体はページフレームを管理する構造体ですが、一部のフィールドはスラブアローケータが使用します。

名前 内容
freelist 空きオブジェクトを参照
counters オブジェクト数などを管理するカウンター
inuse 使用中のスラブオブジェクト数
object スラブオブジェクト数
frozen ページのfronzen状態
next 次の使用中リストへのポインタ
pages スラブキャッシュに使用しているページフレーム数
slab_page kmem_cache_cpu構造体が指すpageを指す
slab_cache ページが管理しているスラブへのポインタ

表_page構造体

page構造体はスラブが使用するページフレームに該当します。page構造体はメンバ変数に共用体を多用しているため、データ構造が複雑になっています。そのため、ソースコードを読み進める際には注意が必要です。 特によく使用するfrozen状態を設定するfrozen変数は構造体と共用体が入り組んだデータ構造のメンバ変数となっています。counters変数により1回の処理でfrozen変数を含めてデータを一括で設定した後に、frozenだけ変更する場合もあります。

データの関連

slubアローケータで使用するデータの関連

cpu、kmem_cache_cpu構造体、kmem_cache構造体、kmem_cache_node構造体、page構造体の関連は図_スラブで使用する構造体の関連のようになります。

f:id:masami256:20190509235714p:plain

図_スラブで使用する構造体の関連

スラブのライフサイクル

スラブがkmem_cache_cpu構造体から参照されているかか、kmem_cache_node構造体から参照されているかでfrozen状態が変わります。この時のfrozen状態を図_スラブの状態に示します。

f:id:masami256:20190509235746p:plain

図_スラブの状態

(1)はスラブを作成した時の状態です。スラブを作成した場合は必ずkmem_cache_cpu構造体のpage変数からスラブを参照して、このスラブからスラブオブジェクトを返却します。この状態はkmem_cache_cpu構造体からスラブが参照されているのでfrozenは1となります。

(2)はCPUごとのメモリ域からスラブが外れた状態です。この状態はスラブ内のスラブオブジェクトが全て使用中になる、または現在のCPUが使用するNUMAノードがスラブのNUMAノードと違う場合に、kmem_cache構造体のpage変数が参照するスラブの差し替えた場合です。この状態はスラブはkmem_cache_cpu構造体から参照されていませんのでfrozenは0となります。この状態に変更するために後述するdeactivate_slab関数によるスラブの不活性化処理を行います。

(3)の状態はスラブから空きスラブオブジェクトがなくなり、不活性化されたスラブがスラブオブジェクトの解放によりスラブ内に1つだけ空きオブジェクトができた場合、もしくはkmem_cache_cpu構造体が参照しているスラブのNUMAノードがCPUのNUMAノードと違った場合に、kmem_cache_node構造体の使用中リストからkmem_cache_cpu構造体の使用中リストで参照するように変更する時に起こります。この場合は、kmem_cache_cpu構造体からスラブが参照されるようになるので、frozenは1となります。

スラブアローケータの機能

スラブキャッシュ、スラブ、スラブオブジェクトに対する主な絹おは表_スラブに対する主な操作に示したものがあります。これらのうち、kmem_cache_で始まっている関数はシンボルが公開されていて、他のサブシステムから使用することができます。スラブの作成とスラブの不活性化はslub内部の処理です。

内容 対応する関数
スラブキャッシュの作成 kmem_cache_create
スラブキャッシュの破棄 kmem_cache_destroy
スラブオブエジェクトの確保 kmem_cache_alloc
スラブオブジェクトの解放 kmem_cache_free
スラブの作成 new_slab_objects
スラブの不活性化 deactivate_slab

表_スラブに対する主な機能

スラブキャッシュの作成

スラブキャッシュの作成はkmem_cache_create関数を使用します。スラブキャッシュの作成は各スラブアローケータ共通の処理と、各スラブアローケータ固有部分に分かれています。 スラブキャッシュの作成では最初にスラブがマージ可能かチェックします。作成しようとしたスラブキャッシュがマージ可能な場合は、マージ先のスラブキャッシュの参照数を増やします。既存のobject_size変数と作成しようとしていたスラブキャッシュのオブジェクトの大きさを比較し、大きいほうをobject_sizeに再設定や、オブジェクトの使用数などの設定も行います。最後に/sys/kernel/slabにシンボリックリンクファイルを作成します。シンボリックリンクの指す先はマージ先のスラブキャッシュです。マージに成功した場合はkmem_cache_create関数の処理はこれで完了となります。 スラブキャッシュのマージを行わなかった場合は、スラブキャッシュの新規作成を行います。 スラブキャッシュを新規作成する場合はdo_kmem_cache_create関数にて行います。まず、作成するスラブキャッシュのためにkmem_cache構造体のメモリを確保します。この時もスラブアローケータによりメモリを確保します。ここで、スラブキャッシュの名前、オブジェクトサイズなどのデータを設定します。また、memcgサブシステムで使用するmemcg_params変数の設定も行います。この時にmemcg_chache_params構造体のis_root_cache変数をtrueに設定しています。is_root_chache変数はスラブキャッシュの削除などで使用します。次に、各スラブアローケータ固有の処理を_kmem_cache_create関数にて行います。ここでの処理は主に、スラブキャッシュのオブジェクトサイズ、ページフレームを確保する時のオーダー、kmem_cache_alloc関数時に使用するGFPフラグなどの設定を行います。kmem_cache構造体のcpu_partial変数は各cpu毎にいくつの使用中リストを持てるかの設定です。この設定は表cpu_partial変数の設定にある条件できまります。条件は上から順にチェックします。

条件
kmem_cache_has_cpu_pertial関数がfalseを返す 0
kmem_cache構造体のsize変数がPAGE_SIZEより大きい 2
kmem_cache構造体のsize変数が1024より大きい 6
kmem_cache構造体のsize変数が256より大きい 13
全ての条件に当てはまらない場合 30

表_cpu_partial変数の設定

kmem_cache_has_cpu_partial関数はカーネルの設定でスラブアローケータの設定を有効にしない限り、常にtrueを返すのでcpu_partialが0に設定されることはありません。

次に、各NUMAノードで使用するkmem_cache_node構造体の初期化を行います。この構造体の初期化はリスト構造の初期化やスラブ数、スラブオブジェクト数を0にするなど目立った処理は特にありません。続いて、kmem_cache_cpu構造体の初期化を行いますが、こちらも特筆すべき内容はありません。__kmem_cache_create関数では最後に、作成したスラブキャッシュをsysfsより見えるように、sysfsのエントリーを作成して終了します。 __kmem_cache_create関数に成功し、do_kmem_cache_create関数に戻ったら作成したスラブキャッシュをスラブキャッシュを管理するリストに登録します。これでスラブキャッシュの作成が完了し、スラブオブジェクトの確保ができるようになります。ただし、この時点ではスラブオブジェクトはありませんので、初回のkmem_cache_alloc関数使用時にスラブを作成します。

スラブキャッシュ生成時に設定するフラグ

スラブキャッシュ生成時に設定するフラグのうちデバッグ向けのフラグを表_スラブキャッシュ生成時のフラグに示します。これらフラグの中で、SLAB_DESTROY_BY_RCU、SLAB_DESTROY_BY_RCU、SLAB_NOLEAKTRACEが設定されている場合、マージ機能は使用しません。

フラグ 内容
SLAB_HWCACHE_ALIGN スラブオブジェクトをCPUのキャッシュの境界に合わせる
SLAB_CACHE_DMA GFPフラグにGFP_DMAを設定し、DMA向けのスラブキャッシュを作成する
SLAB_PANIC kmem_cache_crate関数が失敗した場合にカーネルパニックする
SLAB_DESTROY_BY_RCU スラブキャッシュの解放時にRCUを使用して、非同期に行う
SLAB_MEM_SPREAD cpuset機能を使用しているプロセスの場合、cpusetで設定されたcpuのノードよりメモリを確保する(slabアローケータ専用)
SLAB_NOLEAKTRACE kmemleakによるトレースを行わない
SLAB_NOTRACK kmemcheckによるチェックを行わない
SLAB_RECLAIM_ACCOUNT スラブオブジェクトの回収を許する
SLAB_TEMPORARY スラブオブジェクトが短命と設定する。SLAB_RECLAIM_ACCOUNTと同様に回収可能となる

表_スラブキャッシュ作成時のフラグ

空きオブジェクトの管理

スラブ内の空きオブジェクトは、オブジェクト内のポインタによって次の空きオブジェクトを参照します。オブジェクトは使用中はデータが書き込まれていますが、オブジェクトが未使用の場合は重要なデータは存在せず、アクセスもされないため、オブジェクトの先頭に次の空きオブジェクトのアドレスを書き込んでいます。オブジェクトが不要になって解放された場合も、解放するオブジェクトの先頭に次の空きオブジェクトのアドレスを書き込みます。最後の空きオブジェクトは次の空きが無いため、NULLを設定します。ソースコード上は空きオブジェクトをfreelistと呼んでいますが、一般的な単方向連結リストなどと違い、次のオブジェクトを指す専用のポインタを持っておらず、未使用領域を次のオブジェクトを指すポインタとして使用していまます。

空きスラブオブジェクトの設定

スラブオブジェクトを作成するときは、ループしながらスラブ内の作成できるオブジェクトの数だけを設定していきます。 kmem_cache構造体の変数をs、s->offsetを0、s->sizeを16、オブジェクトのポインタをpとした時に、以下の手順で空きオブジェクトのリストを設定していきます。

  1. pの初期値をpageの先頭アドレスにする
  2. 次の空きオブジェクトのアドレスをpのアドレス + s->sizeとする
  3. pのアドレス + s->offsetの位置に、次のオブジェクトのアドレスを書き込む
  4. pの指すアドレスを現在のアドレス + s->sizeの位置に変更する
  5. 2〜4を繰り返す
  6. 作成できるオブジェクト数分、設定を行ったら、次の空きオブジェクトのアドレスをNULLに設定する。

上記の手順を図にすると「図_スラブオブジェクトのセットアップ」のようになります。

f:id:masami256:20190509235826p:plain

図_スラブオブジェクトのセットアップ

スラブオブジェクトを解放する場合は、以下の手順によって空きオブジェクトのリストを更新し、次のkmem_cache_alloc関数時には解放対象のスラブオブジェクトを返却するようにします。

  1. 解放対象のスラブオブジェクトが次の空きオブジェクトとして、現在設定されている次の空きオブジェクトを指すようにする
  2. 現在のCPUに設定されているkmem_cache_cpu構造体のfreelist変数を解放対象のスラブオブジェクトに変更

スラブオブジェクトの確保

スラブオブジェクトの確保はkmem_cache_alloc関数を使用します。kmem_cache_alloc関数はslab、slub、slobの各スラブアローケータ共通のインターフェースですが、実装はアローケータによって異なります。

スラブオブジェクトの確保におけるフローとして、下記の4パターンがあります。1はfastpathと呼ばれるパターンで、現在のCPUで使われているスラブからオブジェクトを確保できる場合で、最も高速に処理が完了します。2〜4のパターンはslowpathとなります。2はAとBのパターンがありますが、これはオブジェクトの確保時にノード番号を指定していない場合(A)・した場合(B)です。ここでオブジェクトが確保できなければ、全NUMAノードより使用中のスラブを探し、そこからオブジェクトの確保を試みます。全ノードを探索したが空きオブジェクトが見つからなかった場合は新規にスラブを作成します。

  1. 現在のCPUにあるスラブからオブジェクトを確保
  2. (A)ローカルメモリにある使用中のスラブからオブジェクトを確保。または、 (B)指定されたNUMAノードにある使用中のスラブからオブジェクトを確保
  3. 全NUMAノードから使用中のスラブを探し、そこからオブジェクトを確保
  4. スラブを新規に作成し、そこからオブジェクトを確保

スラブオブジェクトを確保する流れは図_スラブオブジェクトの確保フローのようになります。

kmem_cache_alloc()                      (1)
  -> slab_alloc()                       (2)
    -> slab_alloc_node()                (3)
      -> __slab_alloc()                 (4)
        -> deactivate_slab()            (5)
        -> get_freelist()               (6)
        -> new_slab_objects()           (7)
          -> get_partial()              (8)
            -> get_partial_node()       (9)
            -> get_any_partial()        (10)
          -> new_slab()                 (11)
            -> allocate_slab()          (12)
        -> set_freepointer()        (13)

図_スラブオブジェクトの確保フロー

スラブオブジェクトの取得はkmem_cache_alloc関数を使用しますが、実際の処理はslab_alloc_node関数から始まります。slab_alloc_node関数は、最初に現在のCPUに設定されているkmem_cache_cpu構造体を取得します。次にこのkmem_cache_cpu構造体より次の空きオブジェクトへのポインタ(freelist変数)を取得します。また、page構造体も取得します。ここで、node_match関数を呼び出し、次の2条件のいずれかを満たす場合はfastpathとなり、freelist変数をスラブオブジェクトとして呼び出し元に返却します。

  1. スラブが作成済み(page構造体がNULLでない)
  2. スラブオブジェクトを確保するNUMAノードが指定されていて、pageが所属するノードが指定されたノードと同じ

fastpathの場合は、次のkmem_cache_alloc関数の呼び出しに備え、freelistを次の空きオブジェクトを指すようにします。この時にCPU固有の先読み命令(*注1)にてfreelistをCPUのキャッシュに読み込みます。この手法により、次回のkmem_cache_alloc関数時にデータをメモリからでなくCPUのキャッシュから読み出せるようにすることで、高速化を図っています。

slowpathの場合は、__slab_alloc関数を実行します。ここでは、ローカルメモリにあるスラブより空きオブジェクトを探索します。kmem_cache_alloc関数によるスラブオブジェクトの確保では、NUMAノードの指定は行わないため、必ずローカルメモリを優先して探索します。ローカルメモリからの探索では、再度、現在のCPUに設定されているスラブキャッシュを取得し、このスラブキャッシュより参照されているスラブを取得します。 もし、スラブが存在しない場合、新たなスラブの作成に進みます。スラブの新規作成処理は後述します。スラブが存在した場合はスラブが所属するNUMAノードのチェックをnode_match関数を用いて行います。(この処理は、後述するkmem_cache_cpu構造体の更新後にジャンプして来る場合があります。)この場合もNUMAノードの指定は行っていません。よって、page構造体がNULLでなければ(スラブ用にページフレームが確保されている)、このスラブが利用可能なスラブオブジェクトの候補となります。 スラブに対する次のチェックとして、PageActiveマクロを利用し、スラブとしてい使用しているページがアクティブか調べます。もし、アクティブで無い場合、gfpフラグにALLOC_NO_WATERMARKSが設定されているか確認します。ALLOC_NO_WATERMARKSはウォーターマークのチェックをしないという設定です。このフラグがセットされていない場合は、deactivate_slab関数を使用して、スラブを不活性化します。この処理は「スラブの不活性化」で説明します。

次にpageのfreelist変数を対象にチェックを行っていきます。まず、kmem_cache_cpu構造体のfreelistが空きオブジェクトを指しているか確認し、参照先がスラブオブジェクトで無い場合は、page構造体のfreelist変数が空きオブジェクトを指しているかget_freelist関数を実行して調べます。

kmem_cache_cpu構造体のfreelist、もしくはpage構造体のfreelist変数が空きオブジェクトを指している場合、kmem_cache_cpu構造体のfreelist変数に空きオブジェクトを指しているfreelist変数を設定します。これでCPUが参照するスラブオブジェクトがfreelistになります。この処理にはload_freelistラベルが設定されて、スラブの新規作成が成功した場合にも実行します。スラブオブジェクトの設定を行ったら、呼び出し元の関数にこのスラブオブジェクトを返して、__slab_alloc関数を終了します。

スラブを新規に作成する前に、kmeme_cache_cpu構造体のpartial変数がNULLでないかチェックします。これまでの処理ではkmem_cache_cpu構造体のpage変数に設定されているスラブを対象に空きオブジェクトを探索しましたが、partial変数のチェックで、kmem_cache_cpu構造体の使用中リストに空きオブジェクトが存在するかチェックします。使用中のスラブオブジェクトが存在している場合に、kmem_cache_cpu構造体を更新し、スラブオブジェクトを取得する対象のスラブをこのスラブにします。この処理でkmem_cache_cpu構造体のpage変数とpartital変数が同じスラブを指すようになります。そして、partial変数はスラブが指す次のpage構造体に設定します。

そして、kmem_cache_cpu構造体のfreelist変数はNULLにします。これで、kmem_cache_cpu構造体のpageとpartialの設定を更新しfreelistがNULLを指すことで、、空きスラブオブジェクトは存在してないという状態になります。ここまで行ったら、slowpathの最初の処理にジャンプします。この時、ページフレームはすでに存在しているので、node_match関数によるノードのチェックから開始します。こまでの処理でローカルメモリからはスラブオブジェクトが見つからなかったため、new_slab_objects関数を実行します。この関数は大きく2つの処理があり、1つ目の処理はリモートメモリより空きオブジェクトを検索します。この処理で空きオブジェクトが見つかれば、このオブジェクトを返却できます。リモートメモリより空きオブジェクトを探すのはget_partial関数にて行います。

get_partial関数で空きスラブオブジェクトを探索する場合は、まずスラブオブジェクトを確保するNUMAノードが指定されているか確認し、ノードが指定されていなければローカルメモリ、指定があればそのノードよりスラブオブジェクトの取得を試みます。指定したノードよりスラブオブジェクトを確保する処理はget_pertial_node関数にて行います。この関数は指定されたNUMAノードにあるスラブのリスト(kmem_cache_node構造体のpartial変数)を辿り、空きスラブオブジェクトが存在するスラブを探します。スラブ中の空きスラブオブジェクトの探索はaqcuire_slab関数にて行います。スラブ内に空きスラブオブジェクトが見つかった場合は、そのスラブをfrozen状態に変更します。そして、使用中リストより、スラブのページフレームを外します。 aquire_slab関数にてり空きスラブオブジェクトが見つかった場合、スラブは以下のいずれかの状態になります。

  1. スラブオブジェクト確保したことで空きスラブオブジェクトなくなる
  2. スラブオブジェクトを確保したが、まだ空きスラブオブジェクトが存在する

1の場合は、kmem_cache_cpu構造体のpage変数にスラブが使用してるpageを設定します。 2の場合は、kmem_cache_cpu構造体のpartial変数にスラブが設定されているか確認し、スラブが設定されていた場合は、そのスラブのfrozen状態を解除し、そして、そのスラブに使用中のスラブオブジェクトがなく、使用中スラブの数が下限以上あればそのスラブはslab_discard関数にてスラブの不活性化処理を行います。使用中のスラブオブジェクトがあれば使用中リストにそのスラブを追加します。これで元々partial変数に設定されていたスラブの処理が完了したので、新しいスラブのための設定を行います。設定するのはpage構造体のデータで、オブジェクト数の設定などを行います。 スラブ中の空きスラブオブジェクト数が十分にあれば、この見つかったスラブオブジェクトを返却します。もし、空きスラブオブジェクト数が十分になければ、別のスラブを探索します。

ローカルメモリもしくは指定したノードよりスラブオブジェクトを確保できなかった場合は、全スラブを対象に空きスラブオブジェクトを探索します。これはget_any_pertial関数にて行いますが、空きスラブオブジェクト探索するか否かは、kmem_cache構造体のremote_node_defrag_ratioの設定値により変わります。remote_node_defrag_ratioが0の場合は他のノードの探索は行いません。次にCPUのタイムスタンプカウンタ値を取得し、この値を1024で割った余りがremote_node_defrag_ratioより小さかった場合も他ノードの探索は行いません。他のノードを探索しなかった場合は、new_slab_objects関数に戻り、新規にスラブオブジェクトを作成します。remote_node_defrag_ratioの値はカーネル内部とsysfsでエクスポートするときで桁数が違います。sysfs経由でこの値を設定/確認する場合は0~100までの数値を使用しますが、カーネル内部ではその値を10倍して使用します。デフォルト値は1000となっています。 スラブオブジェクトを探索する場合は、スラブが使用するZONEより、そのNUMAノードに存在するkmem_cache_node構造体を取得します。そして、そのノードからの空きスラブオブジェクトの確保が許可されている場合は、get_partial_node関数を使用して、空きスラブオブジェクトを探します。これでオブジェクトが見つかれば、そのオブジェクトを返却します。

リモートメモリを検索しても利用可能なかった場合は、new_slab_objects関数の2段階目の処理としてスラブの新規作成処理を行います。スラブの作成処理はnew_slab関数にて行います。スラブの新規作成では、まずページフレームを確保行います。ページフレームの確保とpage構造体の基本的な設定はallocate_slab関数で行います。

最初にpageの確保処理をalloc_slab_page関数にて行います。pageの確保するNUMAオードが指定されていないければ、ローカルメモリから、指定されている場合は対象のNUMAノードよりpageの確保を試みます。pageを確保する時のオーダーはkmem_cache構造体のoo変数に設定されている値を使用します。もしページフレームの確保に失敗した場合、オーダーをkmem_cache構造体のmin変数に設定されている最小のオーダー数に変更して再度alloc_slab_page関数を実行します。これでもページフレームを確保できなければNULLを返却します。

allocate_slab関数にてpageが確保できたらpage構造体のobjects変数にオブジェクト数の設定を行います。また、ページフレームを確保したZONEの状態を変更します。kmem_cache構造体のflags変数にNR_SLAB_RECLAIMABLEが設定されている場合はページ回収可能なページ数を、設定されていない場合はページ回収不可能なページ数を既存の値に追加します。ここまでの処理でスラブのためのpageの確保処理が完了となります。ページフレームの確保ができたら、次にpage構造体への設定として、page構造体のslab_cache変数に現在のkmem_cache構造体を設定し、page構造体とスラブを関連付けます。ページフレームをスラブとしてに使用していることを示すために、pageにPG_slabビットを設定します。page構造体のpfmemallocが設定されている場合は、pageにPG_activeビットを設定します。

次に、pageに対してスラブオブジェクトを1つずつ設定していきます。この処理については「スラブオブジェクトの作成」を参照してください。 最後に、page構造体の設定で、freelist変数をpageの開始アドレスに設定します。pageの開始アドレスは1つ目のスラブオブジェクトのアドレスですので、page構造体のfreelistは最初の空きスラブオブジェクトを指すことになります。inuse変数にはpage構造体のobjects変数を設定します。frozen変数には1を設定し、pageの管理をslubアローケータが行っているとマークします。以上でスラブオブジェクトの作成処理が完了となり、呼び出し元にpage構造体を返却します。

new_slab関数の実行によりスラブの作成が成功した場合は、kmem_cache_cpu構造体の設定を行います。まず、現在のCPUに設定されているkmem_cache構造体よりkmem_cache_cpu構造体のcpu_slab変数を取得します。kmem_cache_cpu構造体のpage変数がスラブのページフレームを指している場合は、現在設定されているkmem_cache_cpu構造体を一旦無効化します。この処理は「kmem_cache_cpu構造体の初期化」にて説明します。そして、page構造体のfreelistを別の変数にコピーし、page構造体のfreelist変数はNULLにします。そして、kmem_cache_cpu構造体のpage変数にnew_slab関数で作成したスラブのページフレームを設定します。kmem_cache_cpu構造体の設定が完了したら、new_slab_object関数の引数で渡されたkmem_cache_cpu構造体の変数に、設定したkmem_cache_cpu構造体を設定します。よって、new_slab_object関数の呼び出しにより、呼び出し元の__slab_alloc関数で使用していたkmem_cache_cpu構造体の内容が変わることになります。new_slab_objects関数では返り値として、コピーしておいたpage構造体のfreelist変数を返却します。

new_slab_objects関数を呼び出した__slab_alloc関数では、スラブの作成に失敗した場合は、これ以上の処理を行えないため、NULLを返します。スラブの作成に成功した場合はload_freelistラベルにジャンプします。

slab_alloc_node関数では、fastpath、slowpathいずれの場合も、スラブオブジェクトを返す前にGFPフラグをチェックし、__GFP_ZEROフラグが設定されている場合は、スラブオブジェクトに0x0を書き込みます。また、スラブオブジェクト確保時にフック関数を登録することができ、これらが設定されている場合は、スラブオブジェクトの確保前、確保後に登録されているフック関数を実行します。これらのフック関数は通常デバッグ機能向けに使われていて、スラブを使用する側からは設定できません。

注1:x86x86_64の場合はprefetcht0命令。

スラブオブジェクトの解放

kmem_cache_alloc関数で確保したスラブオブジェクトはkmem_cache_free関数で解放します。スラブオブジェクトの解放処理は図_スラブオブジェクト解放のようになります。

kmem_cache_free()
  -> cache_from_obj()
  -> slab_free()
    -> set_freepointer()    // fastpath
    -> __slab_free()        // slowpath
      -> put_cpu_partial()
        -> unfreeze_partials()
      -> discard_slab()
      -> remove_partial()

図_スラブオブジェクトの解放

kmem_cache_free関数では実質的な処理はせず、slab_free関数にて解放の処理を行います。スラブオブジェクトの解放は、確保の場合と同じくfastpathとslowpathの2パターンがあります。解放対象のオブジェクトがCPUから参照されている場合がfastpathとなり、そうでない場合はslowpathとなります。fastpathの場合は、解放するオブジェクトを次の空きオブジェクトに設定します。この時の様子を図_スラブオブジェクト解放前と図_スラブオブジェクト解放後に示します。解放前はkmem_cache_cpu構造体のfreelistは解放するスラブオブジェクトの隣にあるスラブオブジェクトを指していますが、スラブの解放後は解放したスラブオブジェクトを指すようになります。fastpathの場合は、現在使用中のスラブに対してオブジェクトの解放処理を行うため、freelistの変更だけで済んでいます。

f:id:masami256:20190509235911p:plain

図_スラブオブジェクト解放前

f:id:masami256:20190509235927p:plain

図_スラブオブジェクト解放後

slowpathの場合は__slab_\free関数にて処理を行います。

まず、以下のループでスラブが使用するpage構造体のfreelistを設定します。この時にpage構造体のデータを一部保存する一時変数として、newを使用します。

  1. kmem_cache_node構造体がNULL出ない場合は、この構造体のロックを取得(ループ1回目はkmem_cache_node構造体はNULL)
  2. page構造体のfreelist変数をprior変数にコピーし、set_freepointer関数で、priorを次に返すオブジェクトに設定
  3. newにスラブが使用しているpage構造体のcountersをコピー
  4. newのスラブオブジェクト使用数をデクリメント
  5. スラブのfrozen状態をwas_frozen変数にコピー
  6. newのオブジェクト使用数が0またはpriorがNULLかつ、スラブがfrozen状態で無かった場合7の処理を行います
  7. page構造体のfreelist変数がNULLの場合、8の処理を行い、NULLでなかった場合は9の処理を行います。いずれの処理も終了したら10に移動します
  8. スラブのfrozen状態を1にセット
  9. スラブが所属するNUMAノードのkmem_cache_node構造体を取得
  10. cmpxchg_double_slab関数でスラブのpage構造体のfreelistとcounters変数をnewに設定したデータに更新
  11. cmpxchg_double_slab関数が変更を行わなかった場合はループを終了

7の処理はソースコード上ではfreelistのチェックだけでなく、kmem_cache_has_cpu_partial関数がtrueを返すことも条件の一つなのですが、スラブのデバック機能を使用しない場合はtrueが返ります。 8の処理でfrozen状態を1に設定していますが、これはスラブが使用中リストで管理されていなかった場合になります。

上述のループを終了した段階で、kmem_cache_node構造体が取得されていない場合で、スラブをfrozen状態に変更した場合は、スラブをkmem_cache_cpu構造体のpartial変数のリストにつなぎます。 スラブをkmem_cache_cpu構造体から外すにはput_cpu_partial関数を使用します。この処理中は割り込みを禁止します。

次に、以下の処理をループで行います。

  1. 現在のCPUが参照しているkmem_cache構造体よりkmem_cache_cpu構造体のpartial変数を取得してoldpage変数に代入
  2. oldpageがNULLで無い場合は3の処理を行い、NULLだった場合はXに移動します
  3. 使用中オブジェクト数(ループ1回目は0、4手順目で更新する)がkmem_cache構造体のcpu_partialより大きい場合、unfreeze_partials関数を実行してkmem_cache_cpu構造体のpartial変数に紐づく全てのスラブのforzne状態を解除
  4. 引数で渡されたpae構造体のpage変数のpage数、使用中オブジェクト数を更新命令
  5. page変数next変数に取得したoldpageを設定
  6. this_cpu_cmpxchg関数でkmem_cache構造体のcpu_slab変数が参照しているpartialを更新したpage変数に変更
  7. this_cpu_cmpxchg関数が更新を行わなかった場合はループを終了

unfreeze_partials関数はkmem_cache_cpuのpartialリストにあるスラブのfrozen状態に変更し、kmem_cache_nodeの使用中リストに登録します。この処理では2段階のループがあります。 page構造体のデータを更新するための作業用変数としてpage、oldとnewを使用します。

  1. kmem_cache_cpu構造体のpartialに設定されているpage構造体をpageに代入
  2. スラブが使用しているpage構造体が所属するNUMAノードのkmem_cache_node構造体を取得
  3. 取得したkmem_cache_node構造体が前回取得したノード違った場合、前回のkmem_cache_nodeがNULLでなければ、ロックを解除
  4. 取得したkmem_cache_node構造体のロックを取得
  5. pageに設定されているfreelistとcountersをoldにコピー
  6. oldに設定したcountersとfreelistをnewにコピー
  7. newのfrozen変数を0に設定
  8. __cmpxchg_double_slab関数でpage変数のfreelistとcountersをnewに設定した値に更新
  9. __cmpxchg_double_slab関数が値の更新を行わなかったら11に進み、値の更新を行った場合は5に戻り、freelistとcouters変数の更新を続けます
  10. newに設定されているスラブオブジェクトの使用数が0かつ、kmem_cache_nodeにある使用中スラブ数が十分にある場合、そのスラブは不活性化の対象とします。そうでない場合はスラブをkmem_cache_node構造体の使用中リストに登録します。

上記手順の5と6は同じデータを設定していますが、7手順目でfrozen状態を解除するため、8手順目でpage変数にはfrozen状態が解除されたデータとして登録されます。

ループを抜けた時にkmem_cache_node構造体で取得したロックを解除します。 そして、ループの10手順目で削除対象のスラブが設定した場合は、discard_slab関数を実行してスラブを不活性化します。この処理は「スラブの不活性化」にて説明します。

kmem_cache_cpu構造体のデータクリア

スラブを無効化する時にkmem_cache_cpu構造体に設定されているデータのクリアを行います。この処理はflush_slab関数で行います。この関数は最初にdeactivate_slab関数を実行し、スラブを無効化します。次に、以下の3変数の値を変更します。

スラブの不活性化

スラブの不活性化処理は、下記3処理を行います。

  1. frozen状態スラブのfreelistで管理されている未使用のスラブオブジェクトを、同じスラブのpage構造体のfreelistへ移動
  2. スラブのfrozen状態解除
  3. 移動後のスラブの状態により、使用中リストへ移動、もしくは使用中リストから削除

これらの処理により、kmem_cache_cpu構造体が使用しているスラブを差し替えることができるようになります。この処理が必要になるのは2パターンあります。

  1. スラブを新規作成し、既存のスラブと置き換える
  2. スラブが不要になった場合

1のパターンは、スラブオブジェクトの確保時に既存のスラブからはスラブオブジェクトが確保できなかったため、新規にスラブを作成する場合です。2のパターンはkmem_cache_free関数によるスラブオブジェクトの解放時に、スラブ内のオブジェクトが全て空きオブジェクトになり、かつ使用中リストの数が下限以上ある場合、もしくはkmem_cache_destroy関数にてスラブキャッシュ自体を削除する場合です。

スラブの不活性化処理を行うのはdeactivate_slab関数です。処理は大きく2段階に別れていて、1段階目は空きオブジェクトの移動。2段階目はスラブのfrozen解除と使用中リストへの追加・削除です。 空きオブジェクトの移動では、frozen状態のスラブにあるfreelist(kmem_cache_cpu構造体のfreelist変数)より、空きオブジェクトを全て、同スラブのpage構造体のfreelistへ移動します。

第2段階では、最初に1段階目の処理の後に、freelistがまだ空きオブジェクトを指しているか確認し、空きオブジェクトを指している場合は、freelistがpage構造体のfreelistに設定した空きオブジェクトを指すように変更します。 この時にテンポラリの変数として、old、newと呼ぶpage構造体を使います。空きオブジェクトを指していた場合は、newの使用中スラブ数を減らし、newのfreelistがfreelistを指すようにします。空きオブジェクトを指していない場合は、newのfreelistとoldのfreelistを同じに設定します。以降の処理で、page構造体の変数を参照する際はnewを使用します。

次に、スラブが使用しているページに対する操作を決定します。どのような操作を行うかはスラブの状態に応じて決定します。スラブの状態を表_スラブの状態に示します。

状態 内容
M_NONE 何もしない(初期値)
M_PARTIAL スラブには使用中のオブジェクトがある
M_FULL スラブに空きオブジェクトが無い
M_FREE スラブに使用中オブジェクトが無い

表_スラブの状態

スラブの状態は2つの変数(l、m)により管理します。両者とも初期値はM_NONEです。まずはmについて、表_スラブの状態設定のようにmの状態を設定します。これら状態のうちM_FULLはデバッグ用途のフラグですので、通常はM_FULL状態の場合の処理はありません。

条件 設定する状態
スラブに使用中のオブジェクトがなく、NUMAノード内の使用中リスト数が下限以上に存在する M_FREE
page構造体のfreelistが空きオブジェクトを指している M_PARTIAL
その他 M_FULL

表_スラブの状態設定

次にlとmが同値でなければ、スラブが使用しているページに対する操作を行います。最初にこのコードパスを通る場合、lにはM_NONEが設定されているため、この条件は必ず真になります。そして、以下の条件に合致する処理を行います。

条件 処理内容
l == M_PARTIAL 使用中リストからスラブを削除
l == M_FULL 空きオブジェクト無しリストからスラブを削除(このリストはデバッグ用のため、通常は存在しません)
m == M_PARTIAL スラブを使用中リストに追加
m == M_FULL スラブを空きオブジェクト無しリストに追加(このリストはデバッグ用のため、通常は存在しません)

この処理が終わった後にlの値をmの値に設定します。次に、引数で渡されたpageのfreelistとcountersがoldのfreelistとcountersが同じなら、これらをnewのfreelist、countersに変更します。変更は__cmpxchg_double_slab関数で行います。もし__cmpxchg_double_slab関数がfalseを返した場合は変更を行わず、2段階目の最初の処理にジャンプし、2段階目の処理を再度実行します。変更を行った場合は最後の処理として、mがM_FREEに設定されているか確認し、M_FREEが設定されている場合はスラブは不要と判断し、discard_slab関数を実行してスラブの削除を行います。

スラブの削除

kmem_cache_free関数や、スラブの不活性化などにより、スラブ内に使用中のオブジェクトがなくなった場合にスラブの削除処理を行います。スラブの削除を行うインターフェースとなる関数はdiscard_slab関数です。スラブの削除はkmem_cache構造体のflags変数を見て、SLAB_DESTROY_BY_RCUが設定されている場合は、RCUを使用して遅延実行し、設定されていない場合はそのまま削除処理を行います。どちらの場合も削除処理として__free_slab関数を使用します。

discard_slab関数は削除対象のスラブが所属するNUMAノードのkmem_cache_node構造体を取得し、nr_slabs変数からスラブ数の減算と、解放することになるスラブオブジェクト数をobjects変数から減算します。次に、free_slab関数にて、kmem_cache構造体のflags変数にSLAB_DESTROY_BY_RCUが設定されているか確認し、設定されている場合はスラブをスラブ削除用のRCUリストにつなぎ、処理を終了します。 SLAB_DESTROY_BY_RCUが設定されていない場合は__free_salb関数にてスラブの削除を行います。RCUを使用する場合もスラブの削除実行には__free_slab関数を使用します。 __free_slab関数が呼ばれる時点で、スラブオブジェクトに対する解放処理は行われているため、この関数ではスラブが使用しているpageの解放処理が主となります。ここでの処理は、ページが所属しているZONEより、スラブが使用していたページ数の減算。ページの属性としてPG_activeとPG_slabビットを下ろします。次にpage構造体の_mapcount変数を-1に設定します。_mapcountは共用体のメンバ変数で、他にinuse、objects、frozenの3変数を持つ構造体も共用体のメンバ変数で、_mapcountに-1を設定することで、他のinuseなどの変数も無効な値に上書きされます。task_struct構造体のreclaim_state変数がNULLでなければ、回収済みのページ数に今回解放するページ数を足します。そして、__free_pages関数を使用し、ページの解放を行います。削除したスラブがkmem_cache_create関数で作成したスラブの場合は、memcgサブシステムのアカウンティング情報よりより使用していたページ数を減らします。

スラブキャッシュの削除

スラブキャッシュが不要になったらkmem_cache_destroy関数でスラブキャッシュを削除します。スラブキャッシュの削除処理はslabアローケータと共通処理とslubアローケータ固有の処理があります。スラブキャッシュの削除はまず、各アローケータ共通であるkmem_cache_destroy関数から処理が始まります。削除処理中はロックを確保し、他のスレッドから操作できないようにします。そして、スラブキャッシュの削除を行います。これは各アローケータ固有の処理で、インターフェースは__kmem_cache_shutdown関数です。__kmem_cache_shutdown関数自体は特に処理は行わず、処理はkmem_cache_close関数にて行います。 slubアローケータでは、最初に全CPUに対して以下の処理を行います。

  1. CPUから参照されているkmem_cache_cpu構造体のpageもしくはpartial変数がNULLの場合(スラブが存在しない)、何もしない
  2. page変数にスラブが設定されている場合、flush_cpu_slab関数が__flush_cpu_slab関数を実行し、3〜5の処理を行う
  3. deactivate_slab関数を実行し、スラブを不活性化。kmem_cache_cpu構造体の変数を初期化
  4. unfreeze_partials関数にてkmem_cache_cpu構造体のpartial変数に設定されてるスラブのfrozen状態を解除
  5. スラブが使用していた不要になったページをdiscard_slab関数にて解放

上記1〜5の処理で、各CPUから参照されていたkmem_cache_cpu構造体のデータを処理したので、次にNUMAノードに設定されているスラブを片付けます。この処理はkmem_cache構造体のnode変数に設定されている、kmem_cache_node構造体のpartialリストよりノードに存在するスラブに対してdiscard_slab関数を実行し、スラブを削除します。

次にCPUごとのメモリ域にあるkmem_cache構造体のcpu_slab変数のメモリを解放します。最後に、kmem_cache構造体のnodeメンバ変数で使用していたkmem_cache_node構造体のメモリを解放します。

ここまででslubアローケータ固有の処理を終了し、スラブアローケータ共通処理に戻ります。共通処理に戻ったら確保していたロックを解除し、do_kmem_cache_release関数を実行し、sysfsでエクスポートしているスラブキャッシュのエントリを削除します。これでスラブキャッシュの削除が完了となります。

スラブキャッシュのセットアップ

スラブアロケータを使用できるようにするために、カーネルの起動時にセットアップを行います。ここでセットアップするのは、kmem_cache構造体とkmem_cache_node構造体のメモリを確保するためのスラブキャッシュと、kmalloc関数で使用する様々なサイズのスラブキャッシュです。slubアローケータのスラブキャッシュを管理するためのメモリ管理機構に、slubスラブアロケータを使用します。

スラブキャッシュのセットアップ状況はいくつかの段階があります。この定義を表_スラブキャッシュのセットアップ状況に示します。セットアップの状態は表のDOWNからFULLに向かって進みます。最初はDOWNから始まります。

状態 内容
DOWN スラブキャッシュをまだ使用できない
PARTIAL slubアローケータのkmem_cache_node構造体が使用可能になった(kmem_cache_init関数内で設定)
PARTIAL_NODE slabアローケータで使用
UP スラブキャッシュを使えるようになったが、まだスラブの全機能は使用可能にはなっていない(create_kmalloc_caches関数で設定)
FULL 全て使用可能(slab_sysfs_init関数で設定)

表_スラブキャッシュのセットアップ状況

スラブキャッシュの初期化はkmem_cache_init関数が行います。この関数では最初に__initdata領域に存在する初期化時用のkmem_cache構造体とkmem_cache_node構造体のデータを使用し、スラブキャッシュを作成します。このスラブキャッシュの作成では、kmem_cache構造体のname、size、alignなどの変数を設定し、__kmem_cache_create関数を呼び出します。__kmem_cache_create関数は通常のスラブキャッシュ作成時にも使用しますが、通常時との違いとして、スラブキャッシュの作成状況による処理の変更が2箇所あります。 1つ目の変更箇所はkmem_cache_open関数から呼ばれるinit_kmem_cache_nodes関数の処理です。init_kmem_cache_nodes関数ではスラブキャッシュの作成状態がDOWNの場合、early_kmem_cache_node_alloc関数を使用してスラブキャッシュを作成します。これは、状態がDOWNの場合、まだスラブキャッシュを使用することが出来ないため、スラブを仮に作成し、そこからメモリを確保してスラブキャッシュを作成します。この場合でもスラブやページフレーム、スラブの使用中リストは設定します。

もう一箇所は__kmem_cache_create関数で、kmem_cache_open関数を実行し、スラブキャッシュが作成できたあとに状態をチェックし、状態がUP以下の場合は、sysfsへのスラブキャッシュ登録処理を行いません。よって、最初期のセットアップではスラブキャッシュを作成しただけで処理を終了します。__kmem_cache_create関数でスラブキャッシュを設定した後は、kmem_cache構造体のrefcountを-1に設定し、スラブのマージ機能対象外になるようにします。 この手順をkmem_cache構造体、kmem_cache_node構造体のスラブキャッシュのために行います。ここまで完了したらスラブキャッシュのセットアップ状況をPARTIALに設定します。

ここまでで仮のセットアップを行ったので、次に本格的なセットアップに入ります。ここからのセットアップもまずは、kmem_cache構造体用のスラブキャッシュと、kmem_cache_node構造体用のスラブキャッシュのセットアップです。これらのセットアップはbootstrap関数にて行います。まず、仮にセットアップしたスラブキャッシュを使用し、kmem_cache構造体用のメモリを確保します。そして、新しい構造体に既存のデータをコピーします。これで__flush_cpu_slab関数を使用し、CPUが参照しているスラブを無効にします。 つぎに、全NUMAノードにあるkmem_cache_node構造体のpartialリストにつながっているページフレームが参照しているslab_cache変数に、先ほど新規作成したkmem_cache構造体を設定します。 そして、スラブキャッシュを管理するslab_cachesリストに作成したkmem_cache構造体を設定します。

kmem_cache構造体とkmem_cache_node構造体のスラブキャッシュを作成したら、次にkmalloc関数用のスラブキャッシュを作成します。この処理はcreate_kmalloc_caches関数にて行います。create_kmalloc_caches関数では作成するサイズの設定を行い、create_kmalloc_cache関数にてスラブキャッシュを作成します。スラブキャッシュの作成はcreate_boot_cache関数を使用します。create_boot_cache関数は__kmem_cache_create関数を使用して、スラブキャッシュを作成しますが、この時点ではスラブキャッシュの作成状況はPARTIALになっているため、最初にkmem_cache構造体・kmem_cache_node構造体を作成した時の用にinit_kmem_cache_nodes関数ではearly_kmem_cache_node_alloc関数ではなく、通常のkmem_cache_alloc_node関数を使用します。kmalloc関数用のスラブキャッシュを作成したらスラブキャッシュの作成状態をUPに変更します。

スラブキャッシュの作成が完了したら、slab_sysfs_init関数にてスラブキャッシュの情報をsysfs経由でエクスポートします。この時にスラブキャッシュの作成状態をFULLに変更し、スラブキャッシュの機能の設定が完了します。

slubアローケータで使用するヘルパー関数

slubアローケータ内でよく使われる関数を紹介します。

__cmpxchg_double_slab関数

__cmpxchg_double_slab関数は引数を7つ受け取りますが、そのうち重要なものを表___cmpxchg_double_slabの引数に示します。

名前
struct kmem_cache * s
struct page * page
void * freelist_old
unsigned long counters_old
void * freelist_new
unsigned long counters_new

表___cmpxchg_double_slabの引数

この関数はpage->freelistとpage->countersの値がfreelist_old、counters_oldと同一の場合は、page->freelistをfreelist_new、page->countersをcounters_newの値に設定します。CPUがアトミックな更新命令を持っている場合はCPUの命令を使用し、アトミックな更新命令を持っていない場合はロックを取得した上で値の更新を行います。

slubアローケータでは他にもthis_cpu_cmpxchg_double関数やcmpxchg_double_slab関数を値の交換のために使用していますが、処理の基本的な考え方は__cmpxchg_double_slab関数と同じです。

kmalloc関数とkfree関数による動的なメモリ確保と解放

kmalloc関数

任意のサイズのメモリを動的に確保したい場合、ユーザランドのプログラムではmalloc(3)を使用しますが、Linuxカーネル内ではkmalloc関数を使用します。 kmalloc関数のインターフェースは「図_kmallocのインターフェース」のようになっています。sizeは確保するメモリの量、flagsは__get_free_pages関数でも使用している、メモリ確保時の制御フラグです。また、メモリを0x0で埋めて返すkzalloc関数などの補助的な関数もあります。

static __always_inline void *kmalloc(size_t size, gfp_t flags);
static inline void *kzalloc(size_t size, gfp_t flags);

図_kmallocのインターフェース

kmalloc関数は確保するサイズに応じて、スラブアローケータよりメモリを確保します。kmalloc関数はカーネルコンパイル時にサイズが確定していて、サイズがkmalloc用のスラブキャッシュの最大サイズ(KMALLOC_MAX_SIZE)を超える場合はページアローケータを使用してメモリを確保します。それ以外の場合はサイズに応じたkmalloc用のスラブキャッシュよりスラブオブジェクトを取得して返します。 kmalloc用のスラブキャッシュはcreate_kmalloc_caches関数にてカーネルの起動時に作成します。

ZONE_NORMALに所属するページフレームからなるkmalloc用のスラブは「図_kmallocのスラブキャッシュ」のようになっています。

lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-1024 -> :t-0001024
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-128 -> :t-0000128
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-16 -> :t-0000016
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-192 -> :t-0000192
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-2048 -> :t-0002048
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-256 -> :t-0000256
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-32 -> :t-0000032
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-4096 -> :t-0004096
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-512 -> :t-0000512
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-64 -> :t-0000064
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-8 -> :t-0000008
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-8192 -> :t-0008192
lrwxrwxrwx  1 root root 0 Jun  9 00:27 kmalloc-96 -> :t-0000096

図_kmallocのスラブキャッシュ

例えば、48バイトのsizeを指定された場合、次に大きいkmalloc-64のスラブキャッシュよりオブジェクトを確保することになります。このようにスラブアロケータを使用することで、要求するsizeによっては無駄が出てしまいますが、メモリを効率的に速く確保できるという利点もあります。

kfree関数

kmalloc関数で確保したメモリを解放するときはkfree関数を使用します。kfree関数のインターフェースは図_kfreeのインターフェースの通りです。引数に渡すのはkmalloc関数の戻り値です。

void kfree(const void *);

図_kfreeのインターフェース

kfree関数でのメモリ解放では、実質的な処理はslab_free関数にて行います。kfree関数固有な処理は特にありません。

fedora 30からgrubの仕様が変わったのでφ(..)メモメモ

Fedora 30でChanges/BootLoaderSpecByDefaultというプロポーザルがあって、Fedora 30βでは実際にこの仕様になってます。カーネルを弄る人にはちょっと影響があるかなって感じです。

仕様

The Boot Loader Specificationに書かれています

どんな風になったか

boot時のgrubの画面は変化はありません。

f:id:masami256:20190409201409p:plain
grub

変わったのはエントリーの書き方です。今まではgrub.cfgにエントリーを追加していたわけですが、カーネルのエントリー部分が独立した感じです。

root@kerntest:/home/masami# ls /boot/loader/entries/
9575947ef933448ea2005318c989c813-0-rescue.conf                     9575947ef933448ea2005318c989c813-5.0.6-200.fc29.x86_64+debug.conf
9575947ef933448ea2005318c989c813-5.0.5-200.fc29.x86_64.conf        9575947ef933448ea2005318c989c813-5.0.6-300.fc30.x86_64.conf
9575947ef933448ea2005318c989c813-5.0.5-200.fc29.x86_64+debug.conf  9575947ef933448ea2005318c989c813-5.0.6-300.fc30.x86_64+debug.conf
9575947ef933448ea2005318c989c813-5.0.6-200.fc29.x86_64.conf        9575947ef933448ea2005318c989c813-5.1.0-rc4-test+.conf

たとえば、9575947ef933448ea2005318c989c813-5.1.0-rc4-test+.confはこんなファイルです。

title Fedora (5.1.0-rc4-test+) 30 (Thirty)
version 5.1.0-rc4-test+
linux /boot/vmlinuz-5.1.0-rc4-test+
initrd /boot/initramfs-5.1.0-rc4-test+.img
options $kernelopts
id fedora-20190408151310-5.1.0-rc4-test+
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel-

uefiとnon uefi

従来はuefi環境なら/boot/efi/EFI/fedora/grub.cfg、biosなら/boot/grub2/grub.cfgが使われていましたが、BLSでは/boot/loader/entries/にあるファイルを読むことになります。

uefiな環境でも/boot/loader/entriesにファイルが置かれ、

masami@saga:~$ file /sys/firmware/efi/
/sys/firmware/efi/: directory
masami@saga:~$ sudo ls /boot/loader/entries
6ae2390b6ece4d5c86324fadb81d220d-0-rescue.conf                     6ae2390b6ece4d5c86324fadb81d220d-5.0.5-200.fc29.x86_64+debug.conf
6ae2390b6ece4d5c86324fadb81d220d-5.0.4-200.fc29.x86_64.conf        6ae2390b6ece4d5c86324fadb81d220d-5.0.6-300.fc30.x86_64.conf
6ae2390b6ece4d5c86324fadb81d220d-5.0.4-200.fc29.x86_64+debug.conf  6ae2390b6ece4d5c86324fadb81d220d-5.0.6-300.fc30.x86_64+debug.conf
6ae2390b6ece4d5c86324fadb81d220d-5.0.5-200.fc29.x86_64.conf        6ae2390b6ece4d5c86324fadb81d220d-5.1.0-rc4-test+.conf

non uefiな環境でも/boot/loader/entriesにファイルが置かれます。

root@kerntest:/boot/loader/entries# file /sys/firmware/efi                                                                                                                                   
/sys/firmware/efi: cannot open `/sys/firmware/efi' (No such file or directory)
root@kerntest:/boot/loader/entries# ls /boot/loader/entries/
9575947ef933448ea2005318c989c813-0-rescue.conf                     9575947ef933448ea2005318c989c813-5.0.6-200.fc29.x86_64+debug.conf
9575947ef933448ea2005318c989c813-5.0.5-200.fc29.x86_64.conf        9575947ef933448ea2005318c989c813-5.0.6-300.fc30.x86_64.conf
9575947ef933448ea2005318c989c813-5.0.5-200.fc29.x86_64+debug.conf  9575947ef933448ea2005318c989c813-5.0.6-300.fc30.x86_64+debug.conf
9575947ef933448ea2005318c989c813-5.0.6-200.fc29.x86_64.conf        9575947ef933448ea2005318c989c813-5.1.0-rc4-test+.conf

カーネルのmake install

make modules_install -> make installしますよね。この場合、以下のような流れで処理が走ります。

arch/x86/boot/install.sh 
     -> /sbin/installkernel 
         -> /usr/libexec/installkernel/installkernel-bls 
             -> /bin/kernel-install

make_installの挙動

/sbin/installkernelやusr/libexec/installkernel/installkernel-bls 、それに/bin/kernelinstallはfedora 29でもありますが、f29ではBLSには対応していないのでgrub.cfgにエントリを書く方式が使われます。ちなみに、f29には/usr/libexec/installkernel/installkernel-blsと/usr/libexec/installkernel/installkernelの2つがあります(if文の判定的に-blsのほうは使われない)が、f30では-blsの方しかありません。

これらのコマンドが含まれているパッケージは以下の表のようになります。

コマンド コマンドを提供しているパッケージ
/sbin/installkernel grubby
/usr/libexec/installkernel/installkernel-bls grubby
/bin/kernel-install systemd-udev

パッケージ

カーネルの登録

/bin/kernel-installコマンドでできますが、これは/boot/loader/entriesにファイルを作るだけです。make installするのではなくて、コマンド打っていく場合はこんな感じになります。make moduels_installは済んでいるとして、まずはdracutでinitramfsをつくり、

root@kerntest:/home/masami/linux-kernel (ktest)# dracut /boot/initramfs-5.1.0-rc4-test+.img 5.1.0-rc4-test+                                                                                  

/sbin/installkernelでカーネルを/bootにインストールします。

root@kerntest:/home/masami/linux-kernel (ktest)# /sbin/installkernel 5.1.0-rc4-test+ ./arch/x86/boot/bzImage ./System.map 

そうすると、/bin/kernel-installが内部で呼ばれるのでファイルができてます。

root@kerntest:/home/masami/linux-kernel (ktest)# cat /boot/loader/entries/9575947ef933448ea2005318c989c813-5.1.0-rc4-test+.conf
title Fedora (5.1.0-rc4-test+) 30 (Thirty)
version 5.1.0-rc4-test+
linux /boot/vmlinuz-5.1.0-rc4-test+
initrd /boot/initramfs-5.1.0-rc4-test+.img
options $kernelopts
id fedora-20190409141515-5.1.0-rc4-test+
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel-

もしkernel-installを自分で実行するならこうなります。

root@kerntest:/home/masami/linux-kernel (ktest)# kernel-install add 5.1.0-rc4-test+ /boot/vmlinuz-5.1.0-rc4-test+ 

カーネルの削除

/bootにインストールしたカーネルとinitramfs、/boot/loader/entiresのファイルを消したい場合もkernel-installコマンドで出来ます。removeオプションにカーネルの話バージョンを渡せばokです

root@kerntest:/home/masami/linux-kernel (ktest)# kernel-install remove 5.1.0-rc4-test+

カーネルコマンドラインオプション

特定のエントリーに対してオプションを足したり、全部に足したりしたいですよね。Setting kernel command line arguments with Fedora 30 - Fedora Magazineが参考になります。

grubのメニューへの登録・削除

ブート時に/boot/loader/entriesにあるファイルを見てくれるので、ファイルを置けばメニューに追加され、消せばメニューから消えるという楽な仕様です。

grubの設定を確認したい

grubbyの出番です。

全部見たい場合はgrubby --info=ALLでみれます。エントリのindex番号もこれでわかります。

root@kerntest:/home/masami/linux-kernel (ktest)# grubby --info=ALL                                                                                                                            
index=0                                                                                                                                                                                       
kernel="/boot/vmlinuz-5.1.0-rc4-test+"                                                                                                                                                        
args="ro rhgb quiet nokaslr console=ttyS0,115200"                                                                                                                                             
root="UUID=620d1324-eba7-4beb-aab5-dd9975f25690"                                                                                                                                              
initrd="/boot/initramfs-5.1.0-rc4-test+.img"                                                                                                                                                  
title="Fedora (5.1.0-rc4-test+) 30 (Thirty)"                                                                                                                                                  
id="9575947ef933448ea2005318c989c813-5.1.0-rc4-test+"                                                                                                                                         
index=1                                                                                                                                                                                       
kernel="/boot/vmlinuz-5.0.6-300.fc30.x86_64+debug"

その他はgrubby --helpすれば良いと思います。

dynamic_debugはどのようにソースコードの行数、関数名などを読み取っているのか

dynamic_debugのcontrolファイルを読むとこんな感じでファイル名、関数名、そしてpr_debugに渡している文字列などが見れます。これってどうやってんだろ?というのが今回調べたところです。

masami@kerntest:~/pr_debug_test$ sudo cat /sys/kernel/debug/dynamic_debug/control | head -n 10
# filename:lineno [module]function flags format
init/main.c:804 [main]initcall_blacklisted =p "initcall %s blacklisted\012"
init/main.c:771 [main]initcall_blacklist =p "blacklisting initcall %s\012"
init/initramfs.c:477 [initramfs]unpack_to_rootfs =_ "Detected %s compressed data\012"
arch/x86/events/amd/ibs.c:885 [ibs]force_ibs_eilvt_setup =_ "No EILVT entry available\012"
arch/x86/events/amd/ibs.c:856 [ibs]setup_ibs_ctl =_ "No CPU node configured for IBS\012"
arch/x86/events/amd/ibs.c:850 [ibs]setup_ibs_ctl =_ "Failed to setup IBS LVT offset, IBSCTL = 0x%08x\012"
arch/x86/events/intel/pt.c:736 [pt]pt_topa_dump =_ "# entry @%p (%lx sz %u %c%c%c) raw=%16llx\012"
arch/x86/events/intel/pt.c:727 [pt]pt_topa_dump =_ "# table @%p (%016Lx), off %llx size %zx\012"
arch/x86/kernel/tboot.c:98 [tboot]tboot_probe =_ "tboot_size: 0x%x\012"

自前のカーネルモジュールを作ってロードした後にはcontorolファイルに値が追加されます。

/home/masami/pr_debug_test/pr_debug_test.c:20 [pr_debug_test]pr_debug_test_read =_ "debug pr_debug test\012"                                                                                                      

pr_debugの仕組み

さて、include/linux/printk.hでpr_debugがどのように定義されているか見てみます。dynamic_debugが有効な場合はCONFIG_DYNAMIC_DEBUGが定義されているのでdynamic_pr_debugが使われます。

/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG)
#include <linux/dynamic_debug.h>

/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
   dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
   printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
   no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

dynamic_pr_debug()はこのようなマクロです。

#define dynamic_pr_debug(fmt, ...)              \
do {                             \
   DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);     \
   if (DYNAMIC_DEBUG_BRANCH(descriptor))         \
       __dynamic_pr_debug(&descriptor, pr_fmt(fmt),    \
                  ##__VA_ARGS__);      \
} while (0)

ここの最初の処理がDEFINE_DYNAMIC_DEBUG_METADATAですのでこれを見てみるとこうなっています

#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
   DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
                     (STATIC_KEY_TRUE_INIT))

DEFINE_DYNAMIC_DEBUG_METADATA_KEYはこのように展開されます。

#define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init) \
   static struct _ddebug  __aligned(8)          \
   __attribute__((section("__verbose"))) name = {       \
       .modname = KBUILD_MODNAME,          \
       .function = __func__,              \
       .filename = __FILE__,              \
       .format = (fmt),                \
       .lineno = __LINE__,                \
       .flags = _DPRINTK_FLAGS_DEFAULT,        \
       dd_key_init(key, init)              \
   }

関数名、ファイル名、行数などがここで出てきてますね。この処理がdynamic_debugの肝っぽいです。nameという変数を定義して、その変数はverboseというセクションに置くようにしています(このマクロはdo {} while(0)の中で展開されるので変数はこのブロック中にあります)。この変数に値を設定してverboseセクションに変数を置くというのがdynamic_debugのポイントですね。ちなみにdd_key_initはjump_labelを使う場合の初期化用マクロです。

というわけで、dynamic_debugが有効なカーネルではpr_debugを使っているところはそのデータが__verboseセクションに置かれるということが分かりました。

__verboseセクションはinclude/asm-generic/vmlinux.lds.hで確認できます。カーネルのビルド後ならarch/x86/kernel/vmlinux.ldsがリンカのファイルです。

    /* implement dynamic printk debug */                \
    . = ALIGN(8);                          \
    __start___verbose = .;                      \
    KEEP(*(__verbose))                                              \
    __stop___verbose = .;                       \

__verboseセクションからデータを読んでいるところ

dynamic_debugの初期化時は以下のようにstartverboseからstopverboseまでのメモリ領域を読んでいってデータをddebug_add_module()でリストに登録しています。

 if (__start___verbose == __stop___verbose) {
        pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
        return 1;
    }
    iter = __start___verbose;
    modname = iter->modname;
    iter_start = iter;
    for (; iter < __stop___verbose; iter++) {
        entries++;
        verbose_bytes += strlen(iter->modname) + strlen(iter->function)
            + strlen(iter->filename) + strlen(iter->format);

        if (strcmp(modname, iter->modname)) {
            modct++;
            ret = ddebug_add_module(iter_start, n, modname);
            if (ret)
                goto out_err;
            n = 0;
            modname = iter->modname;
            iter_start = iter;
        }
        n++;
    }
    ret = ddebug_add_module(iter_start, n, modname);
    if (ret)

モジュールのロード時はload_module()からfind_module_sections()が呼ばれ、ここで__verboseセクションのデータを読み取っています。

 info->debug = section_objs(info, "__verbose",
                   sizeof(*info->debug), &info->num_debug);

そして、load_module()からdynamic_debug_setup()を呼び、ddebug_add_module()を読んでデータを登録する形となっています。

static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num)
{
    if (!debug)
        return;
#ifdef CONFIG_DYNAMIC_DEBUG
    if (ddebug_add_module(debug, num, mod->name))
        pr_err("dynamic debug error adding module: %s\n",
            debug->modname);
#endif
}

まとめ

dynamic_debugが有効なカーネルではソースコード中のpr_debug記述箇所でファイル行数、ファイル名などの情報を変数として登録し、その変数はverboseセクションに置かれる。dynamic_debugはverboseセクションからデータを読んでpr_debugの利用箇所などの情報を取得することができるという感じでした。

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習

FedoraのRISC-V portを試す

FedoraRISC-VポートはPorting Fedora to RISC-Vで記事になってて気になってたのと、RISC-V原典オープンアーキテクチャのススメを買ったしarch/riscvを読んでみようかな〜ということでqemuで動かしてみました。

(´-`).。oO(FedoraRISC-V関連の情報はArchitectures/RISC-V - Fedora Project Wikiに集まるんだと思います。

qemuのセットアップ

FedoraのドキュメントとしてはArchitectures/RISC-V/Installing - Fedora Project Wikiだと思うんですが、ナイトリービルドのサーバが繋がらなくなってました。ということで、QEMUDocumentation/Platforms/RISCV - QEMUを参考にしました。Fedoraqemurisc-vが使えるのでqemu-system-riscvパッケージをインストールするだけでOKです。

あとはドキュメントの通りでできます。

boot

起動もドキュメントの通りにやればOKです。こんな感じでログインプロンプトがでます。

f:id:masami256:20181231134107p:plain
riscv

初期状態でsshdが動いていて、rootでのsshも可能になっています。

RISC-V原典  オープンアーキテクチャのススメ

RISC-V原典 オープンアーキテクチャのススメ

Linuxカーネルソースに付属のscripts/の探索

この記事はLinux Advent Calendar 2018の12日目の記事です。

カーネルソースコードに含まれるscripts/を探索してみます。カーネルのビルド中で使うようなものもあるし、それ以外の時に使うものもあります。今回は後者の方を探してみましょう。

diffconfig

ファイルはsrcipts/diffconfigです。カーネルの.configのdiffを見やすくするツールです。

普通にdiffを取るとこんな感じです。

masami@saga:~$ diff -u /boot/config-4.19.9-300.fc29.x86_64 /boot/config-4.19.12-301.fc29.x86_64
--- /boot/config-4.19.9-300.fc29.x86_64 2018-12-14 02:44:50.000000000 +0900
+++ /boot/config-4.19.12-301.fc29.x86_64        2018-12-24 11:20:56.000000000 +0900
@@ -1,10 +1,10 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 4.19.9-300.fc29.x86_64 Kernel Configuration
+# Linux/x86_64 4.19.12-301.fc29.x86_64 Kernel Configuration
 #
 
 #
-# Compiler: gcc (GCC) 8.2.1 20181105 (Red Hat 8.2.1-5)
+# Compiler: gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
 #
 CONFIG_CC_IS_GCC=y
 CONFIG_GCC_VERSION=80201
@@ -20,7 +20,7 @@
 # CONFIG_COMPILE_TEST is not set
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_BUILD_SALT="4.19.9-300.fc29.x86_64"
+CONFIG_BUILD_SALT="4.19.12-301.fc29.x86_64"
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
@@ -93,6 +93,7 @@
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
@@ -4655,7 +4656,7 @@
 # CONFIG_DVB_MMAP is not set
 CONFIG_DVB_NET=y
 CONFIG_TTPCI_EEPROM=m
-CONFIG_DVB_MAX_ADAPTERS=8
+CONFIG_DVB_MAX_ADAPTERS=16
 CONFIG_DVB_DYNAMIC_MINORS=y
 # CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set
 # CONFIG_DVB_ULE_DEBUG is not set

diifconfigを使うとこのようになります。

masami@saga:~$ ./linux-kernel/scripts/diffconfig /boot/config-4.19.9-300.fc29.x86_64 /boot/config-4.19.12-301.fc29.x86_64
 BUILD_SALT "4.19.9-300.fc29.x86_64" -> "4.19.12-301.fc29.x86_64"
 DVB_MAX_ADAPTERS 8 -> 16
+HAVE_SCHED_AVG_IRQ y

通常のdiffと違って何がどう変わったのかが見やすくなりますね。

objdiff

ファイルはscripts/objdiffです。これはobjectファイル間のdiffを取ります。カーネル以外でも使えます。

例えば、コミット間で以下のようなファイルの変更が有った場合、

masami@saga:~/codes/objdiff-test (test %)$ git diff master a.c
diff --git a/a.c b/a.c
index ab39f2e..a0068b8 100644
--- a/a.c
+++ b/a.c
@@ -7,7 +7,7 @@ struct test {
 int main(int argc, char **argv)
 {
        struct test t = {
-               .s = "hello",
+               .s = "hello\n",
        };
 
        printf("%s\n", t.s);

こんな感じになります。

masami@saga:~/codes/objdiff-test (test %)$ ~/linux-kernel/scripts/objdiff diff
which: no colordiff in (/usr/share/Modules/bin:/usr/lib64/ccache:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/masami/bin:/home/masami/.gem/ruby/2.2.0/bin:/home/masami/go/bin:/home/masami/ltp:/home/masami/ltp/bin:/home/masami/.local/bin:/home/masami/bin:/home/masami/bin:/home/masami/.gem/ruby/2.2.0/bin:/home/masami/go/bin:/home/masami/ltp:/home/masami/ltp/bin:/home/masami/.local/bin:/home/masami/bin)
diff -Nurd /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.dis /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.dis
--- /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.dis  2018-12-30 23:36:28.063937470 +0900
+++ /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.dis  2018-12-30 23:37:13.345071254 +0900
@@ -10,8 +10,8 @@
 :      48 81 ec 10 01 00 00    sub    $0x110,%rsp
 :      89 bd fc fe ff ff       mov    %edi,-0x104(%rbp)
 :      48 89 b5 f0 fe ff ff    mov    %rsi,-0x110(%rbp)
-:      48 b8 68 65 6c 6c 6f    movabs $0x6f6c6c6568,%rax
-:      00 00 00 
+:      48 b8 68 65 6c 6c 6f    movabs $0xa6f6c6c6568,%rax
+:      0a 00 00 
 :      ba 00 00 00 00          mov    $0x0,%edx
 :      48 89 85 00 ff ff ff    mov    %rax,-0x100(%rbp)
 :      48 89 95 08 ff ff ff    mov    %rdx,-0xf8(%rbp)
Binary files /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.stripped and /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.stripped differ

bootgraph.pl

ファイルはscripts/bootgraph.plです。 カーネルの起動時にprintk.time=1とinitcall_debugをカーネルコマンドラインオプションに付けて起動する必要があります。dmesgの経過時間のところから何にどれだけ時間を使ったかを見る感じですね。

全体像はこんな感じです。

f:id:masami256:20181230224632p:plain
boot graph

拡大するとこうなってます。

f:id:masami256:20181230225324p:plain
bootgraph2

show_delta

ファイルはscripts/show_deltaです。 これも実行時間の計測ですね。前回のprintkの時刻から今回までの時間を表示してくれます。

('[0.280670 < 0.003444 >] pci 0000:00:06.0: reg 0x20: [io  0xc0a0-0xc0bf]\n',)
('[0.281820 < 0.001150 >] pci 0000:00:06.1: [8086:2935] type 00 class 0x0c0300\n',)
('[0.306576 < 0.000002 >] initcall xen_setup_shutdown_event+0x0/0x30 returned -19 after 0 usecs\n',)
('[0.307587 < 0.000000 >] calling  power_supply_class_init+0x0/0x40 @ 1\n',)
('[0.309641 < 0.000000 >] NetLabel:  domain hash size = 128\n',)
('[0.309642 < 0.000001 >] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO\n',)
('[0.359181 < 0.000003 >] initcall proc_version_init+0x0/0x22 returned 0 after 1 usecs\n',)
('[0.359707 < 0.000090 >] pnp 00:02: Plug and Play ACPI device, IDs PNP0f13 (active)\n',)
('[0.365880 < 0.000002 >] calling  thermal_init+0x0/0xe1 @ 1\n',)
('[0.370580 < 0.000040 >] initcall intel_pmc_ipc_init+0x0/0x5f returned 0 after 37 usecs\n',)
('[0.370701 < 0.000006 >] initcall ipv4_offload_init+0x0/0x74 returned 0 after 0 usecs\n',)
('[0.890552 < 0.000001 >] calling  crypto_module_init+0x0/0x11 @ 1\n',)

faddr2line

ファイルはscripts/faddr2lineです。oopsにある関数名+オフセット/関数サイズからそれがどのファイルの何行目かを調べることができます。自作したカーネルモジュールでは使えなかったけど。。

こんな風に使えます。

masami@kerntest:~/a2l$ ~/linux-kernel/scripts/faddr2line ~/linux-kernel/vmlinux do_init_module+0x22/0x210
do_init_module+0x22/0x210:
do_init_module at kernel/module.c:3436

decode_stacktrace.sh

ファイルはscripts/decode_stacktrace.shです。カーネルoopsを読み込んでデコードしてくれます。使い方はlinux-3.16で入ったdecode_stacktrace.shを試してみる - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモを参照してください。

decodecode

ファイルはscripts/decodecodeです。decode_stacktrace.shと似たような感じです。使い方はlinuxカーネルデバッグめも decodecodeでoopsの機械語列を逆アセンブル - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモを参照してください。

ver_linux

ファイルはscripts/ver_linuxです。カーネル、ビルドとか諸々のツール類の情報表示します。

masami@saga:~/linux-kernel (test %)$ ./scripts/ver_linux 
If some fields are empty or look unusual you may have an old version.
Compare to the current minimal requirements in Documentation/Changes.

Linux saga 4.19.12-301.fc29.x86_64 #1 SMP Mon Dec 24 01:58:57 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

GNU Make                4.2.1
Binutils                2.31.1
Util-linux              2.32.1
Mount                   2.32.1
Module-init-tools       25
E2fsprogs               1.44.3
Xfsprogs                4.17.0
Quota-tools             4.04
PPP                     2.4.7
Nfs-utils               2.3.3
Linux C Library         2.28
Dynamic linker (ldd)    2.28
Linux C++ Library       6.0.25
Procps                  3.3.15
Net-tools               2.10
Kbd                     2.0.4
Console-tools           2.0.4
Sh-utils                8.30
Udev                    239
Wireless-tools          29
Modules Loaded          binfmt_misc bridge coretemp crc32c_intel crc32_pclmul crct10dif_pclmul devlink drm drm_kms_helper e1000e ebtable_filter ebtable_nat ebtables fat fuse ghash_clmulni_intel hid_logitech_dj hid_logitech_hidpp i2c_algo_bit i2c_i801 intel_cstate intel_powerclamp intel_rapl intel_rapl_perf intel_uncore intel_wmi_thunderbolt ip6table_filter ip6table_mangle ip6table_nat ip6table_raw ip6_tables ip6table_security ip6t_REJECT ip6t_rpfilter ip_set iptable_mangle iptable_nat iptable_raw iptable_security ipt_MASQUERADE irqbypass iTCO_vendor_support iTCO_wdt kvm kvm_intel libcrc32c llc lpc_ich mei mei_me mxm_wmi nf_conntrack nf_conntrack_broadcast nf_conntrack_netbios_ns nf_defrag_ipv4 nf_defrag_ipv6 nf_nat nf_nat_ipv4 nf_nat_ipv6 nfnetlink nf_reject_ipv6 nouveau pcc_cpufreq snd snd_hda_codec snd_hda_codec_ca0132 snd_hda_codec_hdmi snd_hda_core snd_hda_intel snd_hwdep snd_pcm snd_seq snd_seq_device snd_seq_dummy snd_timer soundcore stp sunrpc tap ttm tun uas usb_storage vfat vhost vhost_net video wmi x86_pkg_temp_thermal xfs xt_CHECKSUM xt_conntrack xt_CT

spelling.txt

ファイルはscripts/spelling.txtです。このファイルは単体で使うと言うか、checkpatch.plでスペルチェックに使っています。ファイルの書式はこんな感じで、左側がよく有る間違いで右側が正解です。

abov||above

まとめ

他にもスクリプトは色々有ります。たとえばscripts/gdbカーネルgdbデバッグする時のスクリプトで.gdbinitで add-auto-load-safe-path /home/masami/codes/slmb/scripts/gdb/vmlinux-gdb.py という感じに読み込ませます。

ということで、なんとなくscripts/を探索してみました( ´ー`)フゥー...

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習

RHEL 8 betaのsrpmをリビルドしてmockでshellでログインできるところまで作る

この記事はLinux Advent Calendarの13日目です。

いんとろ

Powering IT’s future while preserving the present: Introducing Red Hat Enterprise Linux 8 Beta キタ━━━━(゚∀゚)━━━━!!って感じですよね。

srpmも公開されています。Index of /redhat/rhel/rhel-8-beta/baseos/source/PackagesIndex of /redhat/rhel/rhel-8-beta/appstream/source/Packagesにあります。BaseOSとかAppstreamとは?といくところはIntroducing Application Streams in RHEL 8 - RHD Blogとかを参照してもらえればokかと思います。

今回はrhel8以外の環境でrhel8のsrpmをリビルドしてrhelクローン的なものを作って遊ぼうではないかというところになります。

ビルド環境

ホストはfedora 29でビルド環境としてはmockのfedora 28にしました。RHEL 8はfedora 28ベースらしい(8.0 BETA RELEASE NOTES)のでfedora 28でいいかーって感じです。

ちなみに、mockrpmパッケージをクリーンな環境でビルドするためのツールです。意味合い的にはdebianpbuilderに近いかも?mockはchrootの環境にsystemd-nspawnを使ってます。

ビルド手順

手順としてはこういう感じになります。最初はfedora 28の環境でパッケージをビルドして、それ以降はリビルドしたパッケージを使ってmock環境を作ってビルドしていくというブートストラップ方式です。

  1. mockに必要なパッケージをダウンロードしてくる
  2. 最初はfedora 28環境でrhel 8 betaのsrpmをビルドしてrpmパッケージとsrpmパッケージを作ります
  3. 1で作ったrpmパッケージでmock環境を作り、そこで1で作ったsrpmをビルドします
  4. 2で作ったrpmパッケージで2で作ったsrpmをリビルド

今回は2の途中までしか出来てません。

パッケージのビルド

stage 0

パッケージの確認

最初に最低限のビルド環境を作る必要があるので、この環境に必要なパッケージのsrpmをダウンロードします。必要なパッケージが何か調べる方法ですがmockを使いました。fedora 29に入ってるmockパッケージだとmock環境としてrhel 8 betaの環境があります。なので、この環境を作ってその時にインストールされるパッケージを確認しました。

masami@saga:~/codes/rhel_rebuild/stage0$ ls /etc/mock/
./                    default.cfg@         fedora-27-aarch64.cfg  fedora-28-ppc64.cfg    fedora-29-x86_64.cfg        fedora-rawhide-i386.cfg     mageia-cauldron-aarch64.cfg      rhelbeta-8-aarch64.cfg
../                   default.cfg.rpmnew@  fedora-27-armhfp.cfg   fedora-28-ppc64le.cfg  fedora-30-aarch64.cfg@      fedora-rawhide-ppc64.cfg    mageia-cauldron-armv7hl.cfg      rhelbeta-8-ppc64le.cfg
custom-1-aarch64.cfg  eol/                 fedora-27-i386.cfg     fedora-28-s390x.cfg    fedora-30-armhfp.cfg@       fedora-rawhide-ppc64le.cfg  mageia-cauldron-i586.cfg         rhelbeta-8-s390x.cfg
custom-1-armhfp.cfg   epel-6-i386.cfg      fedora-27-ppc64.cfg    fedora-28-x86_64.cfg   fedora-30-i386.cfg@         fedora-rawhide-s390x.cfg    mageia-cauldron-x86_64.cfg       rhelbeta-8-x86_64.cfg
custom-1-i386.cfg     epel-6-ppc64.cfg     fedora-27-ppc64le.cfg  fedora-29-aarch64.cfg  fedora-30-ppc64.cfg@        fedora-rawhide-x86_64.cfg   opensuse-leap-15.0-x86_64.cfg    site-defaults.cfg
custom-1-ppc64.cfg    epel-6-x86_64.cfg    fedora-27-s390x.cfg    fedora-29-armhfp.cfg   fedora-30-ppc64le.cfg@      logging.ini                 opensuse-tumbleweed-aarch64.cfg
custom-1-ppc64le.cfg  epel-7-aarch64.cfg   fedora-27-x86_64.cfg   fedora-29-i386.cfg     fedora-30-s390x.cfg@        mageia-6-armv5tl.cfg        opensuse-tumbleweed-i586.cfg
custom-1-s390.cfg     epel-7-ppc64.cfg     fedora-28-aarch64.cfg  fedora-29-ppc64.cfg    fedora-30-x86_64.cfg@       mageia-6-armv7hl.cfg        opensuse-tumbleweed-ppc64.cfg
custom-1-s390x.cfg    epel-7-ppc64le.cfg   fedora-28-armhfp.cfg   fedora-29-ppc64le.cfg  fedora-rawhide-aarch64.cfg  mageia-6-i586.cfg           opensuse-tumbleweed-ppc64le.cfg
custom-1-x86_64.cfg   epel-7-x86_64.cfg    fedora-28-i386.cfg     fedora-29-s390x.cfg    fedora-rawhide-armhfp.cfg   mageia-6-x86_64.cfg         opensuse-tumbleweed-x86_64.cfg

インストールされたパッケージ数は160パッケージほどでした。そして個々のrpmパッケージがそのsrpmパッケージから調べると123個ほどでした。

srpmのダウンロード

ということで、ここで必要なのはsrpmパッケージをダウンロードしてビルドするための準備をします。ダウンロードは以下のスクリプトで行いました。

#!/bin/bash

urls=$(cat ./rpm_list.txt)

rm -fr srpms
mkdir -p srpms/{baseos,appstream}

cd srpms

for url in $urls;
do
    name=$(basename $url)
    dl_dir="baseos"

    echo $url | grep appstream >/dev/null 2>&1
    if [ $? -eq 0 ]; then
       dl_dir="appstream"
    fi

    savefile="$dl_dir/$name"

    echo "[-]Download $name to $dl_dir"
    curl -L -o $savefile $url
done

rpm_list.txtは以下のようにsrpmパッケージのリンクを1行ずつ書いてるだけです。

http://downloads.redhat.com/redhat/rhel/rhel-8-beta/baseos/source/Packages/acl-2.2.53-1.el8.src.rpm
http://downloads.redhat.com/redhat/rhel/rhel-8-beta/baseos/source/Packages/attr-2.4.48-3.el8.src.rpm

そして次のスクリプトでダウンロードしたsrpmパッケージを展開して、個々のsrpmパッケージに含まれるファイルをgitで管理するようにしてます。

#!/bin/bash

pkgrepo="../pkgrepo"

rm -fr $pkgrepo
mkdir -p $pkgrepo/{baseos,appstream}

topdir=$(pwd)

setup_dir() {
    path=$1

    dir="srpms/$path"
    srpms=$(ls $dir)

    for srpm in $srpms;
    do
        spec=$(rpm -ql $dir/$srpm | grep '.spec$')
        name="${spec%.*}"
        echo $name

        pushd . >/dev/null 2>&1

        cd $pkgrepo/$path
        mkdir $name

        cd $name
        git init
        rpm2cpio ../../../stage0/srpms/$path/$srpm | cpio -iv
        git add .
        git commit -m "initial commit"

        popd >/dev/null 2>&1
    done

}

setup_dir "baseos"
setup_dir "appstream"

ここはmockとpackageのgitリポジトリとリビルド - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモのおまけで紹介したことをやってます。

ここまでで各srpmパッケージについてspecとかパッチなんかをgitで管理できるようになりました。

stage 1

ビルド環境設定

次はパッケージをfedora 28のmock環境でビルドしていきます。最初にsrpmを作って次にrpmを作る流れです。この時にmockに渡すconfigファイルを自前で用意します。と言っても/etc/mockにあるfedora 28のファイルを名前を変えてコピーするだけなのでなくても良いんですが。それとmacros.distファイルを使います。これはそのままビルドするとディストリビューション名がfc28とかになってしまうのでこれを変更するためです。 macros.distはこんな感じです。

# dist macros.

%foobar              8
%dist                %{?distprefix}.fb8
%fb8                1

srpmの作成

srpmのリビルドはこんなスクリプトで行います。

#!/bin/bash

pkg_gitrepo="../pkg_gitrepo"
mockcfg="./foobar.cfg"
macrofile="./macros.dist"

pkgkind=("baseos" "appstream")

resultdir_root="./srpms"

if [ -d $resultdir_root ]; then
    rm -fr $resultdir_root
fi

mkdir -p $resultdir_root/{baseos,appstream}

for kind in ${pkgkind[@]};
do
    packages=$(echo $pkg_gitrepo/$kind/*)

    for pkgdir in ${packages[@]};
    do
        name=$(basename $pkgdir)
        resultdir="$resultdir_root/$kind/"

        echo "[-]$(date) Create $name srpm"
        mock -r $mockcfg --resultdir=$resultdir --macro-file=$macrofile --buildsrpm --spec $pkgdir/${name}.spec --sources $pkgdir >/dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo "[-]$(date) Success build $name srpm"
        else
            echo "[*]$(date) Fail build $name srpm"
        fi
        echo "[-]$(date) End $name srpm"
    done
done

find srpms/ -name "*.log" | xargs rm -f

echo "[-]$(date) Done."

rpmパッケージの作成

そして作成したsrpmをビルドします。

#!/bin/bash

pkg_gitrepo="../pkg_gitrepo"
mockcfg="./foobar.cfg"
macrofile="./macros.dist"

pkgkind=("baseos" "appstream")

srpmsdir="./srpms"
resultdir_root="./rpms"

if [ -d $resultdir_root ]; then
    rm -fr $resultdir_root
fi

mkdir -p $resultdir_root/{baseos,appstream}

echo "[-]$(date) build start"

for kind in ${pkgkind[@]};
do
    packages=$(echo $srpmsdir/$kind/*)

    for pkg in ${packages[@]};
    do
        srcrpm=$(basename $pkg)

        spec=$(rpm -ql $pkg | grep '.spec$')
        pkgname="${spec%.*}"

        echo "[-]$(date) Build $pkgname start"

        resultdir="$resultdir_root/$kind/$pkgname"
        mkdir -p $resultdir

        mock -r $mockcfg --resultdir=$resultdir --macro-file=$macrofile --nocheck --rebuild $pkg >/dev/null 2>&1
        ls $resultdir/*.rpm >/dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo "[-]$(date) Rebuild $pkgname success"
        else
            echo "[*]$(date) Rebuild $pkgname failed"
        fi
        echo "[-]$(date) Build $pkgname end"
    done
done

echo "[-]$(date) End"

これでビルドに成功したパッケージはヽ(=´▽`=)ノという感じで、失敗したものは原因を調べてspecファイルを修正するなどの作業が必要です。まあ。specファイルの修正があるのでgit管理できるようにしたんですね(ノω・)テヘ 単純にビルド成功させるためとしては5、6個のパッケージのspecファイルを修正したのと、いくつかのパッケージはrhel 8 betaのbinutilsが必要だったりしました。

binutilsの方はmockでビルドする前に--installオプションでリビルドしたbinutilsをインストールしてから--nocleanオプションを付けて事前に環境を綺麗にしないでビルドさせるようにしてパッケージのビルドを行いました。

こんな感じで全部のパッケージをビルドしました。

dnfのリポジトリ作成

createrepoコマンドでサクッと作りました。作り方としては、BaseOSとAppstreamは分ける必要が有るので分けてます。ディレクトリ構成としてはこんな感じにしました。repodata/はPackagesやsourcesの中に有る形です。

pkgrepo_for_stage2     ----    baseos    ----    x86_64    ----    Packages
                                     |                       |---     sources
                                     |---    appstream    ----      x86_64    ----    Packages
                                                                  |---       source

stage 2

mockの設定ファイル

stage 1で作ったパッケージを使った環境でmockを使えるようにします。ここでもやっとmock用の設定ファイルをちゃんと使うようになります。foobar.cfgとして以下のようにしました。パッケージグループは作ってないのでパッケージはベタに書いてます(´・ω・`)

config_opts['root'] = 'foobar8'
config_opts['target_arch'] = 'x86_64'
config_opts['legal_host_arches'] = ('x86_64',)
#config_opts['chroot_setup_cmd'] = 'install @buildsys-build'
config_opts['chroot_setup_cmd'] = 'install bash bzip2 coreutils cpio diffutils findutils gawk grep gzip info make patch redhat-release sed shadow-utils tar unzip util-linux which xz rpm binutils glibc-devel libgomp isl libmpc cpp'
config_opts['dist'] = 'fb8'  # only useful for --resultdir variable subst
config_opts['extra_chroot_dirs'] = [ '/run/lock', ]
config_opts['releasever'] = 'fb'
config_opts['package_manager'] = 'dnf'

config_opts['yum.conf'] = """
[main]
keepcache=1
debuglevel=2
reposdir=/dev/null
logfile=/var/log/yum.log
retries=20
obsoletes=1
gpgcheck=0
assumeyes=1
syslog_ident=mock
syslog_device=
install_weak_deps=0
metadata_expire=0
mdpolicy=group:primary
best=1

# repos

[foobar-base]
name=Foobar BaseOS
baseurl=file:///home/masami/rhel_rebuild/pkgrepo_for_stage2/baseos/x86_64/Packages
enabled=1
gpgcheck=0

[foobar-appstream]
name=Foobar Appstream
baseurl=file:///home/masami/rhel_rebuild/pkgrepo_for_stage2/appstream/x86_64/Packages
enabled=1
gpgcheck=0

[foobar-base-source]
name=Foobar BaseOS source
baseurl=file:///home/masami/rhel_rebuild/pkgrepo_for_stage2/baseos/source
enabled=0

[foobar-base-source]
name=Foobar BaseOS source
baseurl=file:///home/masami/rhel_rebuild/pkgrepo_for_stage2/appstream/source
enabled=0

mock環境にログイン

これを使ってmock環境にログインすることができます。

masami@rhel-build:~/rhel_rebuild/stage2$ mock -r ./foobar.cfg --shell /bin/bash
INFO: mock.py version 1.4.13 starting (python version = 3.7.1)...
Start: init plugins
INFO: selinux disabled
Finish: init plugins
Start: run
Start: chroot init
INFO: calling preinit hooks
INFO: enabled root cache
INFO: enabled dnf cache
Start: cleaning dnf metadata
Finish: cleaning dnf metadata
INFO: enabled HW Info plugin
Start: dnf install
Foobar Appstream                                                                                                                                                                    18 kB/s |  36 kB     00:02
Foobar BaseOS                                                                                                                                                                      491 kB/s | 1.0 MB     00:02
Dependencies resolved.
===================================================================================================================================================================================================================
 Package                                             Arch                                   Version                                                         Repository                                        Size
===================================================================================================================================================================================================================
Installing:
 isl                                                 x86_64                                 0.16.1-6.fb8                                                    foobar-appstream                                 841 k
 libmpc                                              x86_64                                 1.0.2-9.fb8                                                     foobar-appstream                                  57 k
 bash                                                x86_64                                 4.4.19-6.fb8                                                    foobar-base                                      1.5 M
 binutils                                            x86_64                                 2.30-49.fb8                                                     foobar-base                                      5.6 M
 bzip2                                               x86_64                                 1.0.6-26.fb8                                                    foobar-base                                       59 k
 coreutils                                           x86_64                                 8.30-4.fb8                                                      foobar-base                                      1.2 M
 cpio                                                x86_64                                 2.12-8.fb8                                                      foobar-base                                      264 k
 cpp                                                 x86_64                                 8.2.1-3.3.fb8                                                   foobar-base                                       10 M
 diffutils                                           x86_64                                 3.6-5.fb8                                                       foobar-base                                      358 k
 findutils                                           x86_64                                 1:4.6.0-19.fb8                                                  foobar-base                                      526 k
 gawk                                                x86_64                                 4.2.1-1.fb8                                                     foobar-base                                      1.1 M
 glibc-devel                                         x86_64                                 2.28-18.fb8                                                     foobar-base                                      1.0 M
 grep                                                x86_64                                 3.1-6.fb8                                                       foobar-base                                      272 k
 gzip                                                x86_64                                 1.9-4.fb8                                                       foobar-base                                      164 k
 info                                                x86_64                                 6.5-4.fb8                                                       foobar-base                                      197 k
 libgomp                                             x86_64                                 8.2.1-3.3.fb8                                                   foobar-base                                      187 k
 make                                                x86_64                                 1:4.2.1-9.fb8                                                   foobar-base                                      496 k
 patch                                               x86_64                                 2.7.6-7.fb8                                                     foobar-base                                      136 k
 redhat-release                                      x86_64                                 8.0-0.34.fb8                                                    foobar-base                                       44 k
 rpm                                                 x86_64                                 4.14.2-4.fb8                                                    foobar-base                                      534 k
 sed                                                 x86_64                                 4.5-1.fb8                                                       foobar-base                                      296 k
 shadow-utils                                        x86_64                                 2:4.6-4.fb8                                                     foobar-base                                      1.2 M
 tar                                                 x86_64                                 2:1.30-4.fb8                                                    foobar-base                                      837 k
 unzip                                               x86_64                                 6.0-38.fb8                                                      foobar-base                                      190 k
 util-linux                                          x86_64                                 2.32.1-6.fb8                                                    foobar-base                                      2.5 M
 which                                               x86_64                                 2.21-10.fb8                                                     foobar-base                                       47 k
 xz                                                  x86_64                                 5.2.4-2.fb8                                                     foobar-base                                      151 k
Installing dependencies:
 audit-libs                                          x86_64                                 3.0-0.5.20180831git0047a6c.fb8                                  foobar-base                                      114 k
 basesystem                                          noarch                                 11-5.fb8                                                        foobar-base                                      9.3 k
 bzip2-libs                                          x86_64                                 1.0.6-26.fb8                                                    foobar-base                                       47 k
 ca-certificates                                     noarch                                 2018.2.24-6.fb8                                                 foobar-base                                      393 k
 chkconfig                                           x86_64                                 1.11-1.fb8                                                      foobar-base                                      188 k
 coreutils-common                                    x86_64                                 8.30-4.fb8                                                      foobar-base                                      2.0 M
 cracklib                                            x86_64                                 2.9.6-14.fb8                                                    foobar-base                                       92 k
 crypto-policies                                     noarch                                 20181026-1.gitcc78cb7.fb8                                       foobar-base                                       48 k
 curl                                                x86_64                                 7.61.1-5.fb8                                                    foobar-base                                      350 k
 elfutils-libelf                                     x86_64                                 0.174-1.fb8                                                     foobar-base                                      208 k
 expat                                               x86_64                                 2.2.5-3.fb8                                                     foobar-base                                      109 k
 filesystem                                          x86_64                                 3.8-2.fb8                                                       foobar-base                                      1.1 M
 glibc                                               x86_64                                 2.28-18.fb8                                                     foobar-base                                      3.7 M
 glibc-all-langpacks                                 x86_64                                 2.28-18.fb8                                                     foobar-base                                       25 M
 glibc-common                                        x86_64                                 2.28-18.fb8                                                     foobar-base                                      796 k
 glibc-headers                                       x86_64                                 2.28-18.fb8                                                     foobar-base                                      460 k
 gmp                                                 x86_64                                 1:6.1.2-8.fb8                                                   foobar-base                                      318 k
 kernel-headers                                      x86_64                                 4.18.0-32.fb8                                                   foobar-base                                      1.3 M
 keyutils-libs                                       x86_64                                 1.5.10-6.fb8                                                    foobar-base                                       32 k
 krb5-libs                                           x86_64                                 1.16.1-19.fb8                                                   foobar-base                                      842 k
 libacl                                              x86_64                                 2.2.53-1.fb8                                                    foobar-base                                       34 k
 libarchive                                          x86_64                                 3.3.2-3.fb8                                                     foobar-base                                      356 k
 libattr                                             x86_64                                 2.4.48-3.fb8                                                    foobar-base                                       26 k
 libblkid                                            x86_64                                 2.32.1-6.fb8                                                    foobar-base                                      211 k
 libcap                                              x86_64                                 2.25-9.fb8                                                      foobar-base                                       55 k
 libcap-ng                                           x86_64                                 0.7.9-3.fb8                                                     foobar-base                                       32 k
 libcom_err                                          x86_64                                 1.44.3-1.fb8                                                    foobar-base                                       47 k
 libcurl-minimal                                     x86_64                                 7.61.1-5.fb8                                                    foobar-base                                      279 k
 libdb                                               x86_64                                 5.3.28-33.fb8                                                   foobar-base                                      757 k
 libdb-utils                                         x86_64                                 5.3.28-33.fb8                                                   foobar-base                                      147 k
 libfdisk                                            x86_64                                 2.32.1-6.fb8                                                    foobar-base                                      246 k
 libffi                                              x86_64                                 3.1-17.fb8                                                      foobar-base                                       35 k
 libgcc                                              x86_64                                 8.2.1-3.3.fb8                                                   foobar-base                                       75 k
 libgcrypt                                           x86_64                                 1.8.3-2.fb8                                                     foobar-base                                      457 k
 libgpg-error                                        x86_64                                 1.31-1.fb8                                                      foobar-base                                      240 k
 libmetalink                                         x86_64                                 0.1.3-7.fb8                                                     foobar-base                                       31 k
 libmount                                            x86_64                                 2.32.1-6.fb8                                                    foobar-base                                      228 k
 libnghttp2                                          x86_64                                 1.33.0-1.fb8                                                    foobar-base                                       76 k
 libnsl2                                             x86_64                                 1.2.0-2.20180605git4a062cf.fb8                                  foobar-base                                       56 k
 libpkgconf                                          x86_64                                 1.4.2-1.fb8                                                     foobar-base                                       33 k
 libpwquality                                        x86_64                                 1.4.0-8.fb8                                                     foobar-base                                      101 k
 libselinux                                          x86_64                                 2.8-5.fb8                                                       foobar-base                                      177 k
 libsemanage                                         x86_64                                 2.8-3.1.fb8                                                     foobar-base                                      160 k
 libsepol                                            x86_64                                 2.8-1.fb8                                                       foobar-base                                      337 k
 libsigsegv                                          x86_64                                 2.11-5.fb8                                                      foobar-base                                       29 k
 libsmartcols                                        x86_64                                 2.32.1-6.fb8                                                    foobar-base                                      171 k
 libstdc++                                           x86_64                                 8.2.1-3.3.fb8                                                   foobar-base                                      446 k
 libtasn1                                            x86_64                                 4.13-3.fb8                                                      foobar-base                                       75 k
 libtirpc                                            x86_64                                 1.1.4-3.fb8                                                     foobar-base                                      111 k
 libutempter                                         x86_64                                 1.1.6-14.fb8                                                    foobar-base                                       30 k
 libuuid                                             x86_64                                 2.32.1-6.fb8                                                    foobar-base                                       91 k
 libverto                                            x86_64                                 0.3.0-5.fb8                                                     foobar-base                                       23 k
 libxcrypt                                           x86_64                                 4.1.1-4.fb8                                                     foobar-base                                       72 k
 libxcrypt-devel                                     x86_64                                 4.1.1-4.fb8                                                     foobar-base                                       24 k
 libxml2                                             x86_64                                 2.9.7-5.fb8                                                     foobar-base                                      694 k
 lua-libs                                            x86_64                                 5.3.4-10.fb8                                                    foobar-base                                      117 k
 lz4-libs                                            x86_64                                 1.8.1.2-4.fb8                                                   foobar-base                                       54 k
 mpfr                                                x86_64                                 3.1.6-1.fb8                                                     foobar-base                                      220 k
 ncurses                                             x86_64                                 6.1-5.20180224.fb8                                              foobar-base                                      377 k
 ncurses-base                                        noarch                                 6.1-5.20180224.fb8                                              foobar-base                                       79 k
 ncurses-libs                                        x86_64                                 6.1-5.20180224.fb8                                              foobar-base                                      333 k
 openssl-libs                                        x86_64                                 1:1.1.1-6.fb8                                                   foobar-base                                      1.4 M
 p11-kit                                             x86_64                                 0.23.14-2.fb8                                                   foobar-base                                      270 k
 p11-kit-trust                                       x86_64                                 0.23.14-2.fb8                                                   foobar-base                                      137 k
 pam                                                 x86_64                                 1.3.1-3.fb8                                                     foobar-base                                      741 k
 pcre                                                x86_64                                 8.42-4.fb8                                                      foobar-base                                      207 k
 pcre2                                               x86_64                                 10.31-11.fb8                                                    foobar-base                                      237 k
 pkgconf                                             x86_64                                 1.4.2-1.fb8                                                     foobar-base                                       37 k
 pkgconf-m4                                          noarch                                 1.4.2-1.fb8                                                     foobar-base                                       16 k
 pkgconf-pkg-config                                  x86_64                                 1.4.2-1.fb8                                                     foobar-base                                       14 k
 popt                                                x86_64                                 1.16-14.fb8                                                     foobar-base                                       60 k
 readline                                            x86_64                                 7.0-10.fb8                                                      foobar-base                                      198 k
 rpm-libs                                            x86_64                                 4.14.2-4.fb8                                                    foobar-base                                      331 k
 rpm-plugin-selinux                                  x86_64                                 4.14.2-4.fb8                                                    foobar-base                                       69 k
 setup                                               noarch                                 2.12.2-1.fb8                                                    foobar-base                                      179 k
 systemd-libs                                        x86_64                                 239-8.fb8                                                       foobar-base                                      524 k
 tzdata                                              noarch                                 2018e-2.fb8                                                     foobar-base                                      458 k
 xz-libs                                             x86_64                                 5.2.4-2.fb8                                                     foobar-base                                       93 k
 zlib                                                x86_64                                 1.2.11-10.fb8                                                   foobar-base                                      100 k

Transaction Summary
===================================================================================================================================================================================================================
Install  106 Packages

Total size: 79 M
Installed size: 378 M
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Running scriptlet: filesystem-3.8-2.fb8.x86_64                                                                                                                                                               1/1
  Preparing        :                                                                                                                                                                                           1/1
  Installing       : libgcc-8.2.1-3.3.fb8.x86_64                                                                                                                                                             1/106
  Running scriptlet: libgcc-8.2.1-3.3.fb8.x86_64                                                                                                                                                             1/106
  Installing       : tzdata-2018e-2.fb8.noarch                                                                                                                                                               2/106
  Installing       : redhat-release-8.0-0.34.fb8.x86_64                                                                                                                                                      3/106
  Installing       : setup-2.12.2-1.fb8.noarch                                                                                                                                                               4/106
  Running scriptlet: setup-2.12.2-1.fb8.noarch                                                                                                                                                               4/106
warning: /etc/hosts created as /etc/hosts.rpmnew

  Installing       : filesystem-3.8-2.fb8.x86_64                                                                                                                                                             5/106
  Installing       : basesystem-11-5.fb8.noarch                                                                                                                                                              6/106
  Installing       : pkgconf-m4-1.4.2-1.fb8.noarch                                                                                                                                                           7/106
  Installing       : ncurses-base-6.1-5.20180224.fb8.noarch                                                                                                                                                  8/106
  Installing       : pcre2-10.31-11.fb8.x86_64                                                                                                                                                               9/106
  Installing       : libselinux-2.8-5.fb8.x86_64                                                                                                                                                            10/106
  Installing       : ncurses-libs-6.1-5.20180224.fb8.x86_64                                                                                                                                                 11/106
  Installing       : glibc-all-langpacks-2.28-18.fb8.x86_64                                                                                                                                                 12/106
  Installing       : glibc-common-2.28-18.fb8.x86_64                                                                                                                                                        13/106
  Running scriptlet: glibc-2.28-18.fb8.x86_64                                                                                                                                                               14/106
  Installing       : glibc-2.28-18.fb8.x86_64                                                                                                                                                               14/106
  Running scriptlet: glibc-2.28-18.fb8.x86_64                                                                                                                                                               14/106
  Installing       : bash-4.4.19-6.fb8.x86_64                                                                                                                                                               15/106
  Running scriptlet: bash-4.4.19-6.fb8.x86_64                                                                                                                                                               15/106
  Installing       : libsepol-2.8-1.fb8.x86_64                                                                                                                                                              16/106
  Running scriptlet: libsepol-2.8-1.fb8.x86_64                                                                                                                                                              16/106
  Installing       : zlib-1.2.11-10.fb8.x86_64                                                                                                                                                              17/106
  Installing       : info-6.5-4.fb8.x86_64                                                                                                                                                                  18/106
  Installing       : bzip2-libs-1.0.6-26.fb8.x86_64                                                                                                                                                         19/106
  Installing       : xz-libs-5.2.4-2.fb8.x86_64                                                                                                                                                             20/106
  Installing       : gmp-1:6.1.2-8.fb8.x86_64                                                                                                                                                               21/106
  Running scriptlet: gmp-1:6.1.2-8.fb8.x86_64                                                                                                                                                               21/106
  Installing       : libcap-2.25-9.fb8.x86_64                                                                                                                                                               22/106
  Installing       : libdb-5.3.28-33.fb8.x86_64                                                                                                                                                             23/106
  Running scriptlet: libdb-5.3.28-33.fb8.x86_64                                                                                                                                                             23/106
  Installing       : libattr-2.4.48-3.fb8.x86_64                                                                                                                                                            24/106
  Installing       : libacl-2.2.53-1.fb8.x86_64                                                                                                                                                             25/106
  Installing       : sed-4.5-1.fb8.x86_64                                                                                                                                                                   26/106
  Running scriptlet: sed-4.5-1.fb8.x86_64                                                                                                                                                                   26/106
  Installing       : libuuid-2.32.1-6.fb8.x86_64                                                                                                                                                            27/106
  Running scriptlet: libuuid-2.32.1-6.fb8.x86_64                                                                                                                                                            27/106
  Installing       : libxcrypt-4.1.1-4.fb8.x86_64                                                                                                                                                           28/106
  Installing       : popt-1.16-14.fb8.x86_64                                                                                                                                                                29/106
  Installing       : mpfr-3.1.6-1.fb8.x86_64                                                                                                                                                                30/106
  Running scriptlet: mpfr-3.1.6-1.fb8.x86_64                                                                                                                                                                30/106
  Installing       : elfutils-libelf-0.174-1.fb8.x86_64                                                                                                                                                     31/106
  Installing       : libcom_err-1.44.3-1.fb8.x86_64                                                                                                                                                         32/106
  Running scriptlet: libcom_err-1.44.3-1.fb8.x86_64                                                                                                                                                         32/106
  Installing       : lua-libs-5.3.4-10.fb8.x86_64                                                                                                                                                           33/106
  Installing       : chkconfig-1.11-1.fb8.x86_64                                                                                                                                                            34/106
  Installing       : libcap-ng-0.7.9-3.fb8.x86_64                                                                                                                                                           35/106
  Installing       : audit-libs-3.0-0.5.20180831git0047a6c.fb8.x86_64                                                                                                                                       36/106
  Running scriptlet: audit-libs-3.0-0.5.20180831git0047a6c.fb8.x86_64                                                                                                                                       36/106
  Installing       : libffi-3.1-17.fb8.x86_64                                                                                                                                                               37/106
  Installing       : p11-kit-0.23.14-2.fb8.x86_64                                                                                                                                                           38/106
  Running scriptlet: p11-kit-0.23.14-2.fb8.x86_64                                                                                                                                                           38/106
  Installing       : lz4-libs-1.8.1.2-4.fb8.x86_64                                                                                                                                                          39/106
  Installing       : libsemanage-2.8-3.1.fb8.x86_64                                                                                                                                                         40/106
  Installing       : libmpc-1.0.2-9.fb8.x86_64                                                                                                                                                              41/106
  Running scriptlet: libmpc-1.0.2-9.fb8.x86_64                                                                                                                                                              41/106
  Installing       : libdb-utils-5.3.28-33.fb8.x86_64                                                                                                                                                       42/106
  Installing       : libxml2-2.9.7-5.fb8.x86_64                                                                                                                                                             43/106
  Installing       : coreutils-common-8.30-4.fb8.x86_64                                                                                                                                                     44/106
  Running scriptlet: coreutils-common-8.30-4.fb8.x86_64                                                                                                                                                     44/106
  Installing       : readline-7.0-10.fb8.x86_64                                                                                                                                                             45/106
  Running scriptlet: readline-7.0-10.fb8.x86_64                                                                                                                                                             45/106
  Installing       : expat-2.2.5-3.fb8.x86_64                                                                                                                                                               46/106
  Installing       : libmetalink-0.1.3-7.fb8.x86_64                                                                                                                                                         47/106
  Installing       : keyutils-libs-1.5.10-6.fb8.x86_64                                                                                                                                                      48/106
  Installing       : libgpg-error-1.31-1.fb8.x86_64                                                                                                                                                         49/106
  Installing       : libgcrypt-1.8.3-2.fb8.x86_64                                                                                                                                                           50/106
  Running scriptlet: libgcrypt-1.8.3-2.fb8.x86_64                                                                                                                                                           50/106
  Installing       : libnghttp2-1.33.0-1.fb8.x86_64                                                                                                                                                         51/106
  Installing       : libpkgconf-1.4.2-1.fb8.x86_64                                                                                                                                                          52/106
  Installing       : pkgconf-1.4.2-1.fb8.x86_64                                                                                                                                                             53/106
  Installing       : pkgconf-pkg-config-1.4.2-1.fb8.x86_64                                                                                                                                                  54/106
  Installing       : libsigsegv-2.11-5.fb8.x86_64                                                                                                                                                           55/106
  Installing       : gawk-4.2.1-1.fb8.x86_64                                                                                                                                                                56/106
  Installing       : libsmartcols-2.32.1-6.fb8.x86_64                                                                                                                                                       57/106
  Running scriptlet: libsmartcols-2.32.1-6.fb8.x86_64                                                                                                                                                       57/106
  Installing       : libstdc++-8.2.1-3.3.fb8.x86_64                                                                                                                                                         58/106
  Running scriptlet: libstdc++-8.2.1-3.3.fb8.x86_64                                                                                                                                                         58/106
  Installing       : libtasn1-4.13-3.fb8.x86_64                                                                                                                                                             59/106
  Running scriptlet: libtasn1-4.13-3.fb8.x86_64                                                                                                                                                             59/106
  Installing       : p11-kit-trust-0.23.14-2.fb8.x86_64                                                                                                                                                     60/106
  Running scriptlet: p11-kit-trust-0.23.14-2.fb8.x86_64                                                                                                                                                     60/106
  Installing       : libverto-0.3.0-5.fb8.x86_64                                                                                                                                                            61/106
  Installing       : ncurses-6.1-5.20180224.fb8.x86_64                                                                                                                                                      62/106
  Installing       : pcre-8.42-4.fb8.x86_64                                                                                                                                                                 63/106
  Installing       : grep-3.1-6.fb8.x86_64                                                                                                                                                                  64/106
  Running scriptlet: grep-3.1-6.fb8.x86_64                                                                                                                                                                  64/106
  Installing       : openssl-libs-1:1.1.1-6.fb8.x86_64                                                                                                                                                      65/106
  Running scriptlet: openssl-libs-1:1.1.1-6.fb8.x86_64                                                                                                                                                      65/106
  Installing       : coreutils-8.30-4.fb8.x86_64                                                                                                                                                            66/106
  Installing       : crypto-policies-20181026-1.gitcc78cb7.fb8.noarch                                                                                                                                       67/106
  Running scriptlet: crypto-policies-20181026-1.gitcc78cb7.fb8.noarch                                                                                                                                       67/106
  Running scriptlet: ca-certificates-2018.2.24-6.fb8.noarch                                                                                                                                                 68/106
  Installing       : ca-certificates-2018.2.24-6.fb8.noarch                                                                                                                                                 68/106
  Running scriptlet: ca-certificates-2018.2.24-6.fb8.noarch                                                                                                                                                 68/106
  Installing       : libblkid-2.32.1-6.fb8.x86_64                                                                                                                                                           69/106
  Running scriptlet: libblkid-2.32.1-6.fb8.x86_64                                                                                                                                                           69/106
  Installing       : libmount-2.32.1-6.fb8.x86_64                                                                                                                                                           70/106
  Running scriptlet: libmount-2.32.1-6.fb8.x86_64                                                                                                                                                           70/106
  Installing       : krb5-libs-1.16.1-19.fb8.x86_64                                                                                                                                                         71/106
  Installing       : libtirpc-1.1.4-3.fb8.x86_64                                                                                                                                                            72/106
  Running scriptlet: libtirpc-1.1.4-3.fb8.x86_64                                                                                                                                                            72/106
  Installing       : libnsl2-1.2.0-2.20180605git4a062cf.fb8.x86_64                                                                                                                                          73/106
  Running scriptlet: libnsl2-1.2.0-2.20180605git4a062cf.fb8.x86_64                                                                                                                                          73/106
  Installing       : libcurl-minimal-7.61.1-5.fb8.x86_64                                                                                                                                                    74/106
  Installing       : curl-7.61.1-5.fb8.x86_64                                                                                                                                                               75/106
  Installing       : systemd-libs-239-8.fb8.x86_64                                                                                                                                                          76/106
  Running scriptlet: systemd-libs-239-8.fb8.x86_64                                                                                                                                                          76/106
  Installing       : libfdisk-2.32.1-6.fb8.x86_64                                                                                                                                                           77/106
  Running scriptlet: libfdisk-2.32.1-6.fb8.x86_64                                                                                                                                                           77/106
  Installing       : gzip-1.9-4.fb8.x86_64                                                                                                                                                                  78/106
  Running scriptlet: gzip-1.9-4.fb8.x86_64                                                                                                                                                                  78/106
  Installing       : cracklib-2.9.6-14.fb8.x86_64                                                                                                                                                           79/106
  Installing       : libpwquality-1.4.0-8.fb8.x86_64                                                                                                                                                        80/106
  Installing       : pam-1.3.1-3.fb8.x86_64                                                                                                                                                                 81/106
  Running scriptlet: pam-1.3.1-3.fb8.x86_64                                                                                                                                                                 81/106
  Installing       : shadow-utils-2:4.6-4.fb8.x86_64                                                                                                                                                        82/106
  Running scriptlet: libutempter-1.1.6-14.fb8.x86_64                                                                                                                                                        83/106
  Installing       : libutempter-1.1.6-14.fb8.x86_64                                                                                                                                                        83/106
  Installing       : libarchive-3.3.2-3.fb8.x86_64                                                                                                                                                          84/106
  Installing       : rpm-4.14.2-4.fb8.x86_64                                                                                                                                                                85/106
  Installing       : rpm-libs-4.14.2-4.fb8.x86_64                                                                                                                                                           86/106
  Running scriptlet: rpm-libs-4.14.2-4.fb8.x86_64                                                                                                                                                           86/106
  Installing       : rpm-plugin-selinux-4.14.2-4.fb8.x86_64                                                                                                                                                 87/106
  Installing       : kernel-headers-4.18.0-32.fb8.x86_64                                                                                                                                                    88/106
  Running scriptlet: glibc-headers-2.28-18.fb8.x86_64                                                                                                                                                       89/106
  Installing       : glibc-headers-2.28-18.fb8.x86_64                                                                                                                                                       89/106
  Installing       : libxcrypt-devel-4.1.1-4.fb8.x86_64                                                                                                                                                     90/106
  Installing       : glibc-devel-2.28-18.fb8.x86_64                                                                                                                                                         91/106
  Running scriptlet: glibc-devel-2.28-18.fb8.x86_64                                                                                                                                                         91/106
  Installing       : util-linux-2.32.1-6.fb8.x86_64                                                                                                                                                         92/106
  Running scriptlet: util-linux-2.32.1-6.fb8.x86_64                                                                                                                                                         92/106
  Installing       : binutils-2.30-49.fb8.x86_64                                                                                                                                                            93/106
  Running scriptlet: binutils-2.30-49.fb8.x86_64                                                                                                                                                            93/106
  Installing       : xz-5.2.4-2.fb8.x86_64                                                                                                                                                                  94/106
  Installing       : cpp-8.2.1-3.3.fb8.x86_64                                                                                                                                                               95/106
  Running scriptlet: cpp-8.2.1-3.3.fb8.x86_64                                                                                                                                                               95/106
  Installing       : tar-2:1.30-4.fb8.x86_64                                                                                                                                                                96/106
  Running scriptlet: tar-2:1.30-4.fb8.x86_64                                                                                                                                                                96/106
  Installing       : patch-2.7.6-7.fb8.x86_64                                                                                                                                                               97/106
  Installing       : isl-0.16.1-6.fb8.x86_64                                                                                                                                                                98/106
  Running scriptlet: isl-0.16.1-6.fb8.x86_64                                                                                                                                                                98/106
  Installing       : bzip2-1.0.6-26.fb8.x86_64                                                                                                                                                              99/106
  Installing       : unzip-6.0-38.fb8.x86_64                                                                                                                                                               100/106
  Installing       : diffutils-3.6-5.fb8.x86_64                                                                                                                                                            101/106
  Running scriptlet: diffutils-3.6-5.fb8.x86_64                                                                                                                                                            101/106
  Installing       : findutils-1:4.6.0-19.fb8.x86_64                                                                                                                                                       102/106
  Running scriptlet: findutils-1:4.6.0-19.fb8.x86_64                                                                                                                                                       102/106
  Installing       : libgomp-8.2.1-3.3.fb8.x86_64                                                                                                                                                          103/106
  Running scriptlet: libgomp-8.2.1-3.3.fb8.x86_64                                                                                                                                                          103/106
  Installing       : make-1:4.2.1-9.fb8.x86_64                                                                                                                                                             104/106
  Running scriptlet: make-1:4.2.1-9.fb8.x86_64                                                                                                                                                             104/106
  Installing       : cpio-2.12-8.fb8.x86_64                                                                                                                                                                105/106
  Installing       : which-2.21-10.fb8.x86_64                                                                                                                                                              106/106
  Running scriptlet: filesystem-3.8-2.fb8.x86_64                                                                                                                                                           106/106
  Running scriptlet: glibc-all-langpacks-2.28-18.fb8.x86_64                                                                                                                                                106/106
  Running scriptlet: glibc-common-2.28-18.fb8.x86_64                                                                                                                                                       106/106
  Running scriptlet: info-6.5-4.fb8.x86_64                                                                                                                                                                 106/106
  Verifying        : isl-0.16.1-6.fb8.x86_64                                                                                                                                                                 1/106
  Verifying        : libmpc-1.0.2-9.fb8.x86_64                                                                                                                                                               2/106
  Verifying        : audit-libs-3.0-0.5.20180831git0047a6c.fb8.x86_64                                                                                                                                        3/106
  Verifying        : basesystem-11-5.fb8.noarch                                                                                                                                                              4/106
  Verifying        : bash-4.4.19-6.fb8.x86_64                                                                                                                                                                5/106
  Verifying        : binutils-2.30-49.fb8.x86_64                                                                                                                                                             6/106
  Verifying        : bzip2-1.0.6-26.fb8.x86_64                                                                                                                                                               7/106
  Verifying        : bzip2-libs-1.0.6-26.fb8.x86_64                                                                                                                                                          8/106
  Verifying        : ca-certificates-2018.2.24-6.fb8.noarch                                                                                                                                                  9/106
  Verifying        : chkconfig-1.11-1.fb8.x86_64                                                                                                                                                            10/106
  Verifying        : coreutils-8.30-4.fb8.x86_64                                                                                                                                                            11/106
  Verifying        : coreutils-common-8.30-4.fb8.x86_64                                                                                                                                                     12/106
  Verifying        : cpio-2.12-8.fb8.x86_64                                                                                                                                                                 13/106
  Verifying        : cpp-8.2.1-3.3.fb8.x86_64                                                                                                                                                               14/106
  Verifying        : cracklib-2.9.6-14.fb8.x86_64                                                                                                                                                           15/106
  Verifying        : crypto-policies-20181026-1.gitcc78cb7.fb8.noarch                                                                                                                                       16/106
  Verifying        : curl-7.61.1-5.fb8.x86_64                                                                                                                                                               17/106
  Verifying        : diffutils-3.6-5.fb8.x86_64                                                                                                                                                             18/106
  Verifying        : elfutils-libelf-0.174-1.fb8.x86_64                                                                                                                                                     19/106
  Verifying        : expat-2.2.5-3.fb8.x86_64                                                                                                                                                               20/106
  Verifying        : filesystem-3.8-2.fb8.x86_64                                                                                                                                                            21/106
  Verifying        : findutils-1:4.6.0-19.fb8.x86_64                                                                                                                                                        22/106
  Verifying        : gawk-4.2.1-1.fb8.x86_64                                                                                                                                                                23/106
  Verifying        : glibc-2.28-18.fb8.x86_64                                                                                                                                                               24/106
  Verifying        : glibc-all-langpacks-2.28-18.fb8.x86_64                                                                                                                                                 25/106
  Verifying        : glibc-common-2.28-18.fb8.x86_64                                                                                                                                                        26/106
  Verifying        : glibc-devel-2.28-18.fb8.x86_64                                                                                                                                                         27/106
  Verifying        : glibc-headers-2.28-18.fb8.x86_64                                                                                                                                                       28/106
  Verifying        : gmp-1:6.1.2-8.fb8.x86_64                                                                                                                                                               29/106
  Verifying        : grep-3.1-6.fb8.x86_64                                                                                                                                                                  30/106
  Verifying        : gzip-1.9-4.fb8.x86_64                                                                                                                                                                  31/106
  Verifying        : info-6.5-4.fb8.x86_64                                                                                                                                                                  32/106
  Verifying        : kernel-headers-4.18.0-32.fb8.x86_64                                                                                                                                                    33/106
  Verifying        : keyutils-libs-1.5.10-6.fb8.x86_64                                                                                                                                                      34/106
  Verifying        : krb5-libs-1.16.1-19.fb8.x86_64                                                                                                                                                         35/106
  Verifying        : libacl-2.2.53-1.fb8.x86_64                                                                                                                                                             36/106
  Verifying        : libarchive-3.3.2-3.fb8.x86_64                                                                                                                                                          37/106
  Verifying        : libattr-2.4.48-3.fb8.x86_64                                                                                                                                                            38/106
  Verifying        : libblkid-2.32.1-6.fb8.x86_64                                                                                                                                                           39/106
  Verifying        : libcap-2.25-9.fb8.x86_64                                                                                                                                                               40/106
  Verifying        : libcap-ng-0.7.9-3.fb8.x86_64                                                                                                                                                           41/106
  Verifying        : libcom_err-1.44.3-1.fb8.x86_64                                                                                                                                                         42/106
  Verifying        : libcurl-minimal-7.61.1-5.fb8.x86_64                                                                                                                                                    43/106
  Verifying        : libdb-5.3.28-33.fb8.x86_64                                                                                                                                                             44/106
  Verifying        : libdb-utils-5.3.28-33.fb8.x86_64                                                                                                                                                       45/106
  Verifying        : libfdisk-2.32.1-6.fb8.x86_64                                                                                                                                                           46/106
  Verifying        : libffi-3.1-17.fb8.x86_64                                                                                                                                                               47/106
  Verifying        : libgcc-8.2.1-3.3.fb8.x86_64                                                                                                                                                            48/106
  Verifying        : libgcrypt-1.8.3-2.fb8.x86_64                                                                                                                                                           49/106
  Verifying        : libgomp-8.2.1-3.3.fb8.x86_64                                                                                                                                                           50/106
  Verifying        : libgpg-error-1.31-1.fb8.x86_64                                                                                                                                                         51/106
  Verifying        : libmetalink-0.1.3-7.fb8.x86_64                                                                                                                                                         52/106
  Verifying        : libmount-2.32.1-6.fb8.x86_64                                                                                                                                                           53/106
  Verifying        : libnghttp2-1.33.0-1.fb8.x86_64                                                                                                                                                         54/106
  Verifying        : libnsl2-1.2.0-2.20180605git4a062cf.fb8.x86_64                                                                                                                                          55/106
  Verifying        : libpkgconf-1.4.2-1.fb8.x86_64                                                                                                                                                          56/106
  Verifying        : libpwquality-1.4.0-8.fb8.x86_64                                                                                                                                                        57/106
  Verifying        : libselinux-2.8-5.fb8.x86_64                                                                                                                                                            58/106
  Verifying        : libsemanage-2.8-3.1.fb8.x86_64                                                                                                                                                         59/106
  Verifying        : libsepol-2.8-1.fb8.x86_64                                                                                                                                                              60/106
  Verifying        : libsigsegv-2.11-5.fb8.x86_64                                                                                                                                                           61/106
  Verifying        : libsmartcols-2.32.1-6.fb8.x86_64                                                                                                                                                       62/106
  Verifying        : libstdc++-8.2.1-3.3.fb8.x86_64                                                                                                                                                         63/106
  Verifying        : libtasn1-4.13-3.fb8.x86_64                                                                                                                                                             64/106
  Verifying        : libtirpc-1.1.4-3.fb8.x86_64                                                                                                                                                            65/106
  Verifying        : libutempter-1.1.6-14.fb8.x86_64                                                                                                                                                        66/106
  Verifying        : libuuid-2.32.1-6.fb8.x86_64                                                                                                                                                            67/106
  Verifying        : libverto-0.3.0-5.fb8.x86_64                                                                                                                                                            68/106
  Verifying        : libxcrypt-4.1.1-4.fb8.x86_64                                                                                                                                                           69/106
  Verifying        : libxcrypt-devel-4.1.1-4.fb8.x86_64                                                                                                                                                     70/106
  Verifying        : libxml2-2.9.7-5.fb8.x86_64                                                                                                                                                             71/106
  Verifying        : lua-libs-5.3.4-10.fb8.x86_64                                                                                                                                                           72/106
  Verifying        : lz4-libs-1.8.1.2-4.fb8.x86_64                                                                                                                                                          73/106
  Verifying        : make-1:4.2.1-9.fb8.x86_64                                                                                                                                                              74/106
  Verifying        : mpfr-3.1.6-1.fb8.x86_64                                                                                                                                                                75/106
  Verifying        : ncurses-6.1-5.20180224.fb8.x86_64                                                                                                                                                      76/106
  Verifying        : ncurses-base-6.1-5.20180224.fb8.noarch                                                                                                                                                 77/106
  Verifying        : ncurses-libs-6.1-5.20180224.fb8.x86_64                                                                                                                                                 78/106
  Verifying        : openssl-libs-1:1.1.1-6.fb8.x86_64                                                                                                                                                      79/106
  Verifying        : p11-kit-0.23.14-2.fb8.x86_64                                                                                                                                                           80/106
  Verifying        : p11-kit-trust-0.23.14-2.fb8.x86_64                                                                                                                                                     81/106
  Verifying        : pam-1.3.1-3.fb8.x86_64                                                                                                                                                                 82/106
  Verifying        : patch-2.7.6-7.fb8.x86_64                                                                                                                                                               83/106
  Verifying        : pcre-8.42-4.fb8.x86_64                                                                                                                                                                 84/106
  Verifying        : pcre2-10.31-11.fb8.x86_64                                                                                                                                                              85/106
  Verifying        : pkgconf-1.4.2-1.fb8.x86_64                                                                                                                                                             86/106
  Verifying        : pkgconf-m4-1.4.2-1.fb8.noarch                                                                                                                                                          87/106
  Verifying        : pkgconf-pkg-config-1.4.2-1.fb8.x86_64                                                                                                                                                  88/106
  Verifying        : popt-1.16-14.fb8.x86_64                                                                                                                                                                89/106
  Verifying        : readline-7.0-10.fb8.x86_64                                                                                                                                                             90/106
  Verifying        : redhat-release-8.0-0.34.fb8.x86_64                                                                                                                                                     91/106
  Verifying        : rpm-4.14.2-4.fb8.x86_64                                                                                                                                                                92/106
  Verifying        : rpm-libs-4.14.2-4.fb8.x86_64                                                                                                                                                           93/106
  Verifying        : rpm-plugin-selinux-4.14.2-4.fb8.x86_64                                                                                                                                                 94/106
  Verifying        : sed-4.5-1.fb8.x86_64                                                                                                                                                                   95/106
  Verifying        : setup-2.12.2-1.fb8.noarch                                                                                                                                                              96/106
  Verifying        : shadow-utils-2:4.6-4.fb8.x86_64                                                                                                                                                        97/106
  Verifying        : systemd-libs-239-8.fb8.x86_64                                                                                                                                                          98/106
  Verifying        : tar-2:1.30-4.fb8.x86_64                                                                                                                                                                99/106
  Verifying        : tzdata-2018e-2.fb8.noarch                                                                                                                                                             100/106
  Verifying        : unzip-6.0-38.fb8.x86_64                                                                                                                                                               101/106
  Verifying        : util-linux-2.32.1-6.fb8.x86_64                                                                                                                                                        102/106
  Verifying        : which-2.21-10.fb8.x86_64                                                                                                                                                              103/106
  Verifying        : xz-5.2.4-2.fb8.x86_64                                                                                                                                                                 104/106
  Verifying        : xz-libs-5.2.4-2.fb8.x86_64                                                                                                                                                            105/106
  Verifying        : zlib-1.2.11-10.fb8.x86_64                                                                                                                                                             106/106

Installed:
  isl-0.16.1-6.fb8.x86_64                      libmpc-1.0.2-9.fb8.x86_64                           bash-4.4.19-6.fb8.x86_64                               binutils-2.30-49.fb8.x86_64
  bzip2-1.0.6-26.fb8.x86_64                    coreutils-8.30-4.fb8.x86_64                         cpio-2.12-8.fb8.x86_64                                 cpp-8.2.1-3.3.fb8.x86_64
  diffutils-3.6-5.fb8.x86_64                   findutils-1:4.6.0-19.fb8.x86_64                     gawk-4.2.1-1.fb8.x86_64                                glibc-devel-2.28-18.fb8.x86_64
  grep-3.1-6.fb8.x86_64                        gzip-1.9-4.fb8.x86_64                               info-6.5-4.fb8.x86_64                                  libgomp-8.2.1-3.3.fb8.x86_64
  make-1:4.2.1-9.fb8.x86_64                    patch-2.7.6-7.fb8.x86_64                            redhat-release-8.0-0.34.fb8.x86_64                     rpm-4.14.2-4.fb8.x86_64
  sed-4.5-1.fb8.x86_64                         shadow-utils-2:4.6-4.fb8.x86_64                     tar-2:1.30-4.fb8.x86_64                                unzip-6.0-38.fb8.x86_64
  util-linux-2.32.1-6.fb8.x86_64               which-2.21-10.fb8.x86_64                            xz-5.2.4-2.fb8.x86_64                                  audit-libs-3.0-0.5.20180831git0047a6c.fb8.x86_64
  basesystem-11-5.fb8.noarch                   bzip2-libs-1.0.6-26.fb8.x86_64                      ca-certificates-2018.2.24-6.fb8.noarch                 chkconfig-1.11-1.fb8.x86_64
  coreutils-common-8.30-4.fb8.x86_64           cracklib-2.9.6-14.fb8.x86_64                        crypto-policies-20181026-1.gitcc78cb7.fb8.noarch       curl-7.61.1-5.fb8.x86_64
  elfutils-libelf-0.174-1.fb8.x86_64           expat-2.2.5-3.fb8.x86_64                            filesystem-3.8-2.fb8.x86_64                            glibc-2.28-18.fb8.x86_64
  glibc-all-langpacks-2.28-18.fb8.x86_64       glibc-common-2.28-18.fb8.x86_64                     glibc-headers-2.28-18.fb8.x86_64                       gmp-1:6.1.2-8.fb8.x86_64
  kernel-headers-4.18.0-32.fb8.x86_64          keyutils-libs-1.5.10-6.fb8.x86_64                   krb5-libs-1.16.1-19.fb8.x86_64                         libacl-2.2.53-1.fb8.x86_64
  libarchive-3.3.2-3.fb8.x86_64                libattr-2.4.48-3.fb8.x86_64                         libblkid-2.32.1-6.fb8.x86_64                           libcap-2.25-9.fb8.x86_64
  libcap-ng-0.7.9-3.fb8.x86_64                 libcom_err-1.44.3-1.fb8.x86_64                      libcurl-minimal-7.61.1-5.fb8.x86_64                    libdb-5.3.28-33.fb8.x86_64
  libdb-utils-5.3.28-33.fb8.x86_64             libfdisk-2.32.1-6.fb8.x86_64                        libffi-3.1-17.fb8.x86_64                               libgcc-8.2.1-3.3.fb8.x86_64
  libgcrypt-1.8.3-2.fb8.x86_64                 libgpg-error-1.31-1.fb8.x86_64                      libmetalink-0.1.3-7.fb8.x86_64                         libmount-2.32.1-6.fb8.x86_64
  libnghttp2-1.33.0-1.fb8.x86_64               libnsl2-1.2.0-2.20180605git4a062cf.fb8.x86_64       libpkgconf-1.4.2-1.fb8.x86_64                          libpwquality-1.4.0-8.fb8.x86_64
  libselinux-2.8-5.fb8.x86_64                  libsemanage-2.8-3.1.fb8.x86_64                      libsepol-2.8-1.fb8.x86_64                              libsigsegv-2.11-5.fb8.x86_64
  libsmartcols-2.32.1-6.fb8.x86_64             libstdc++-8.2.1-3.3.fb8.x86_64                      libtasn1-4.13-3.fb8.x86_64                             libtirpc-1.1.4-3.fb8.x86_64
  libutempter-1.1.6-14.fb8.x86_64              libuuid-2.32.1-6.fb8.x86_64                         libverto-0.3.0-5.fb8.x86_64                            libxcrypt-4.1.1-4.fb8.x86_64
  libxcrypt-devel-4.1.1-4.fb8.x86_64           libxml2-2.9.7-5.fb8.x86_64                          lua-libs-5.3.4-10.fb8.x86_64                           lz4-libs-1.8.1.2-4.fb8.x86_64
  mpfr-3.1.6-1.fb8.x86_64                      ncurses-6.1-5.20180224.fb8.x86_64                   ncurses-base-6.1-5.20180224.fb8.noarch                 ncurses-libs-6.1-5.20180224.fb8.x86_64
  openssl-libs-1:1.1.1-6.fb8.x86_64            p11-kit-0.23.14-2.fb8.x86_64                        p11-kit-trust-0.23.14-2.fb8.x86_64                     pam-1.3.1-3.fb8.x86_64
  pcre-8.42-4.fb8.x86_64                       pcre2-10.31-11.fb8.x86_64                           pkgconf-1.4.2-1.fb8.x86_64                             pkgconf-m4-1.4.2-1.fb8.noarch
  pkgconf-pkg-config-1.4.2-1.fb8.x86_64        popt-1.16-14.fb8.x86_64                             readline-7.0-10.fb8.x86_64                             rpm-libs-4.14.2-4.fb8.x86_64
  rpm-plugin-selinux-4.14.2-4.fb8.x86_64       setup-2.12.2-1.fb8.noarch                           systemd-libs-239-8.fb8.x86_64                          tzdata-2018e-2.fb8.noarch
  xz-libs-5.2.4-2.fb8.x86_64                   zlib-1.2.11-10.fb8.x86_64

Complete!
Finish: dnf install
Start: creating root cache
Finish: creating root cache
Finish: chroot init
INFO: Installed packages:
Start: shell
[root@990c9a5364794a4788e69f8b4eb784ff /]#

ビルド環境としてのmock

ちょっと依存関係の解決が必要でまだ解決してないので綺麗なビルド環境としては使えません(´・ω・`) 

Error: 
 Problem: conflicting requests
  - nothing provides libgcc_s.so.1 needed by gcc-8.2.1-3.3.fb8.x86_64
ERROR: Command failed: 
 # /usr/bin/dnf --installroot /var/lib/mock/foobar8/root/ --releasever fb --disableplugin=local --setopt=deltarpm=False install bash bzip2 coreutils cpio diffutils findutils gawk grep gzip info make patch redhat-release sed shadow-utils tar unzip util-linux which xz rpm binutils glibc-devel libgomp isl libmpc cpp gcc
Foobar Appstream                                                                                                                                                                   3.0 kB/s | 3.0 kB     00:01    
Foobar BaseOS                                                                                                                                                                      3.0 kB/s | 3.0 kB     00:01    
Error: 
 Problem: conflicting requests
  - nothing provides libgcc_s.so.1 needed by gcc-8.2.1-3.3.fb8.x86_64

まとめ

RHELクローン的な物を作る遊びでした。段階を踏んで自分自身で自分をビルドしていくというブートストラップ方式はコンパイラ的な感じですね。