はじめに
Linuxカーネル(以下カーネル)に機能を追加する、あるいはバグを修正する自作コードには次の2つの種類があります。
- カーネルの変更
- 新規カーネルモジュールの作成
これらの変更を長期間メンテナンスするには次の方法があります。
- Linux開発コミュニティに働きかけて独自コードを公式のmainlineと呼ばれるツリーにコードをマージする
- 独自コードを自分自身で管理して、mainlineカーネルの新バージョンが出るたびに追従する(後述)
本記事は前者の方法に比べて後者の方法をとった場合に必要なメンテナンスコストについて述べます。本記事の表題にはlinuxと書いていますが、linuxと似たようなドラスティックな変更(後述)を是とするソフトウェアすべてに当てはまる話なのでlinuxの開発には関係ないかたにも役立つ話かと思います。
mailineカーネルのバージョンアップへの追従に必要なコスト
昨日書いたエントリで述べたように、カーネルは外部インターフェース(ユーザ空間とのインターフェース)は基本的には変えませんが、内部インターフェースは変わることがままあります。インターフェースを変更するときはmainlineにマージされれているコードについては、インターフェースを変更した人やサブシステムメンテナなど1が責任を持って新しいインターフェースに置き換えます。
このときmainlineにマージされていないコードに対する配慮はありません。したがって、ある時点のカーネルバージョンに対応する自作コードを作っており、それが問題なくビルドできていたとしても、そのコードが使っているインターフェースがその後に変更された場合、その自作コードはビルドできなくなります。このため独自コードを新しいバージョンに追従するためのコストがかかります。影響を受けるのは既存カーネルのコード変更、新規カーネルモジュールの両方です。
インターフェースが変わらなくても、関数内の処理論理が書き換えらえることがあります。このときは既存カーネルに対する変更を新しい処理論理に合わせて変更する必要があります2。
自作コードを長時間メンテナンスしなければならなければ、多くのバージョンのカーネルに追従する必要があるため、毎回上記のコストがかかります。さらに独自コードは時間を追うごとに増えていく傾向にあるので、一回の追従に必要なコストは雪だるま式に増えていきます。
独自コードだけではなく古いコードには新しいカーネルに入っているバグ修正の変更、とくに脆弱性に対処する変更もバックポートし続ける必要があります。
これを繰り返すと最終的に収集がつかなくなって追従が不可能になります。
次のような場合を想定してコストが増えていく様子を見てみましょう。
- v4.18に対してパッチAを適用
- 新カーネルv4.19に対してパッチAを適用
- v4.18に対して新パッチBを適用、v4.19にもパッチBを適用
- v4.18, v4.19に対して新パッチCを適用、新カーネルv4.20に対してパッチA, B, Cを適用
- v4.18, v4.19, v4.20に対して新パッチDを適用、新カーネルv4.21に対してパッチA, B, C, Dを適用
- あぁ^~
これを続けると、自作コードの量(ここではパッチの数)が増えるにつれて、および、追従すべきカーネルの数が増えるごとに追従コストが爆発的に増えていくことがわかっていただけると思います。
すべての自作コードはmainlineにマージすべきか
ここまで述べたことから、すべてのカーネル関連コードはmainlineにマージすべきなのかという疑問を持たれるかもしれません。それに対する私の見解は「場合による」です。メインライン化の手順にもコツがありますし、時間もかかりますし、必ずマージされるとも限りません。自作コードをどれだけの期間メンテナンスする必要があるのかを判断した上でどちらの方法をとるかを決めればいいと思います。
おわりに
本記事ではLinuxカーネルに関する独自コードのメンテナンスに必要なコストが時を経るにつれてどんどん膨らむこと、そのコストが場合によっては当該コードのmainline化によって減らせることを述べました。これは一度体験してみないとなかなかコスト感がわからないため、これまでに様々な組織が独自管理を選択した後に収集がつかない状態になった結果、独自コードのmainline化を基本方針にするようになりました。本書を読むことによって、独自管理のコストについて学んでいただいた上で、どのように管理するかを判断する材料にしていただければ幸いです。