5: パッチのポスティング

遅かれ早かれ、自分の成果物をコミュニティに提示してレビューを受け、最終的にはメインライン・カーネルにマージするという時がきます。当然ながら、カーネル開発コミュニティではパッチのポストに関する一連の約束事や手順を発展させたものであり、これらに従うことは関係者すべてにとって有益なことです。本書では、これらの内容について簡単に述べてあります。またより詳しい情報はカーネル・ドキュメンテーションのディレクトリにあるSubmittingPatches、SubmittingDrivers、SubmitChecklistの各ファイルにも記述されています。

5.1: ポスティングの時期

パッチが完全に「準備完了」の状態になるまでポストは避けたいという誘惑を持つこともあるでしょう。単純なパッチの場合、これで問題はありません。しかし、その開発が複雑なものだった場合、その完成までの過程でコミュニティからのフィードバックを得られることに大きな意味があります。そのため、進行中の成果をポストすること、あるいは関心のある開発者がその進捗をいつでも把握できるよう、git ツリーを提供することも考慮すべきです。

まだマージ可能なレベルには達していないと考えられるコードをポストする場合、そのポストの中でその旨を述べることもいいでしょう。また、残りの主な作業内容や、既知の問題点についても言及します。未完成と分かっているパッチに注目する人は少ないでしょうが、その開発を正しい方向に向けるために役立ちたいと考える人は参加してきます。

5.2: パッチ作成の前に

開発コミュニティにパッチを送る前にやるべきことは多数あります。これには以下の内容が含まれます。

  • 自分にできる範囲でコードのテストを行う。これには、カーネルのデバッグ・ツールを使うこと、オプションのあらゆる合理的な組み合わせに対しカーネルのビルドが可能なことを確認すること、クロス・コンパイラを使い、異なるCPUアーキテクチャー用にビルドを行うこと等が含まれます。
  • そのコードがカーネルのコーディング・スタイル・ガイドラインに適合していることを確認してください。
  • その変更は性能に影響しませんか?影響がある場合、その変更の影響度(または効果)を示すベンチマークを行い、その結果をまとめてパッチに添付します。
  • コードをポストする権限が自分にあることを確認します。その仕事が企業のために行われたものであれば、その企業がその成果物の権利を持っている可能性が高く、GPLに基づくリリースに合意していなければなりません。

一般に、コードをポストする前に少し余分に考えるという努力は必要で、また十分に価値があることです。

5.3: パッチの作成

ポスト用のパッチ作成には驚くほど多くの作業が必要になる場合があります。しかし、繰り返しになりますが、仮に短期的なものであっても、ここで時間を節約しようという考えはお勧めできません。

パッチはカーネルの特定のバージョンに対して作成されなければなりません。原則として、パッチはLinusの git ツリーにある最新のメインラインをベースにすることが必要です。ただし、より広範囲なテストやレビューを行うため、 -mmやlinux-next、あるいはサブシステムのツリーに対応するバージョンの作成が必要となる場合もあります。そのパッチの分野やその他の進行中の状況により、これら別のツリーをベースにした場合、コンフリクトの解決やAPI変更への対応などを含む多大な作業が必要になる場合があります。

最も単純な変更のみを単一のパッチにすべきです。それ以外は一連の論理的なパッチ群として作成することが必要です。パッチの分割には多少の技術が必要です。開発者によっては、コミュニティの期待する方法に従うにはどうしたら良いか、長い期間をかけて理解しなければならない場合があります。一方、すぐに役立ついくつかの経験則もあります。

  • ポストする一連のパッチ群は、まず間違いなく自分の作業用のリビジョン管理システムにある変更とは別のものになります。まず、自分の行った変更がその最終的な状態にあることを確認し、次に他人が理解できるような方法でこれらを分割します。開発者達は、その変更に至るまでに通過した経路にではなく、自己完結の状態にある独立した変更に関心があります。
  • 個々の論理的に独立した変更を別々のパッチとしてフォーマットすることが必要です。これらの変更には小さなもの(例:「この構造にフィールドをひとつ追加」)も、大きなもの(例:新しい大きなドライバの追加)もありますが、いずれも概念的には1行で説明が行える程度に小さいことが必要です。各パッチはそれ自体でレビューが可能で、その記述された通りの実行内容を検証可能な、具体的な変更になっていることが必要です。
  • このガイドラインを別な言葉で言い換えると、「同じパッチに別の種類の変更を混在させないこと」ということになります。ひとつのパッチで重要なセキュリティ上のバグを修正し、いくつかの構造を再編成し、更にコードの再フォーマットを行うといった場合、そのパッチは無視されてしまい、重要な変更が失われる可能性が高くなります。
  • 個々のパッチはそれぞれカーネルにマージされ、そのビルドと実行が正しく行えなければなりません。すなわち、その一連のパッチ群が途中で中断されたとしても、カーネルとしては依然として動作可能でなければなりません。リグレッションを発見するために「git bisect」ツールが使われる場合、パッチの部分適用が一般的によく行われます。これによりカーネルが壊れてしまうような場合、問題点を突き止めるための作業に従事している開発者やユーザーに多大の迷惑をかけることになります。
  • しかし、これを過度に行うことも避けなければなりません。最近、ある開発者はひとつのファイルに対する一式の修正を500個の独立したパッチとしてポストしましたが、この行為はそのカーネルのメーリングリストで彼を一番の人気者にはしませんでした。1個のパッチは、それが論理的な変更内容を1個だけ含むものである限り、合理的な範囲で大きなものとすることができます。
  • ひとつの一連のパッチ群の中の最後のパッチによりそのパッチ全体が有効になるまではそのインフラが使用されないようにするという方法で、まったく新しいインフラを追加することは魅力的かもしれません。しかし、可能な限り、このような方法は避けるべきです。もしその一連のパッチによるリグレッションが発生した場合、原因の切り分け作業により、実際のバグはどこか他にあった場合でも、その最後のパッチが問題の原因として特定されてしまうことになります。新しいコードを追加するパッチは、可能な限りそのコードを直ちに有効にすることが必要です。

完全なパッチ群を作成する作業は、「実際の作業」が終了した後に相当な時間と検討を要する、非常に困難なプロセスとなる場合があります。しかし、正しく行われれば、その費やした時間には高い価値があります。

5.4: パッチのフォーマッティング

この段階でポスト用の完全なパッチ群が得られたことになりますが、まだ多くの作業が残されています。各パッチは、その目的を素早くかつ明確に他人に伝えるためのメッセージへと書式を整えなければいけません。そのため、各パッチは以下に示す内容で構成されます。

  • そのパッチの作者名を示す、「From:」行(オプション)。この行が必要なのは他人のパッチをEメールで送付するときに限られますが、疑問に思ったときは追加しておいても害はありません。
  • そのパッチが実行する内容の1行の記述。このメッセージは、そのパッチのスコープが何かを理解するのに十分なものである必要があります。これは「簡易版」のchangelogに表示される内容となります。このメッセージは通常、関係するサブシステム名を最初に置き、次にそのパッチの目的を記述します。たとえば、以下のようになります。

gpio: fix build on CONFIG_GPIO_SYSFS=n

  • 空白行に続く、パッチ内容の詳細な説明。この説明は必要に応じて長文にすることができ、そのパッチの機能と、カーネルへの適用が必要な理由について記述します。
  • 1行以上のタグ行と、少なくとも、パッチの作者による1行の「Signed-off-by:」行。タグについて以下に詳しく説明します。

通常、以上の3項目がその変更をリビジョン管理システムに入力する際のテキストとなります。これらの項目の後には以下の内容が続きます。

  • パッチ本体、「-u」オプションのユニファイドパッチ形式にて。「-p」オプションをdiffに使用すると、その変更に関数名が関連付けされ、他の人にとって読みやすいパッチになります。

パッチ内の無関係なファイル(ビルド・プロセスで生成されたファイルやエディターのバックアップ・ファイルなど)に変更を含めることは避けることが必要です。この点についてはドキュメンテーション・ディレクトリ内の「dontdiff」ファイルが役立ちます。「-X」オプションを付けてdiffに渡してください。

上述の各タグは、そのパッチの開発にどれだけ多くの開発者が関係しているかの説明に使われます。これらはSubmittingPatchesドキュメントに詳しく解説されていますが、以下にその簡単なまとめを示します。これらの行はそれぞれ以下の構成を持っています。

tag: 氏名<e-mail address> その他のオプション

一般によく使わるタグには以下のものがあります。

  • Signed-off-by: これは、そのパッチをカーネルに含めるために提出する権限がその開発者にあるということを示す、開発者の証明書です。これは「Developer's Certificate of Origin(作成元に関する開発者の証明書)」への同意を示すものであり、その完全なテキストはDocumentation/SubmittingPatchesにあります。適切なサインオフが行われていないコードはメインラインにマージできません。
  • Acked-by: これはそのパッチをカーネルに含めることが適切であるという同意を示す、別の開発者(通常は該当するコードのメンテナー)の証明書です。
  • Tested-by:そのパッチのテストを行い、正常に動作することを確認した人の名前を示します。
  • Reviewed-by: ここに名前を記された開発者がそのパッチが適正かどうかのレビューを行ったことを示します。詳細についてはDocumentation/SubmittingPatchesにあるレビューアのメッセージを参照して下さい。
  • Reported-by: そのパッチ修正の対象となった問題を報告してくれたユーザーの名前を示します。このタグはコードをテストして不具合があれば報告してくれる(正当に評価されないことの多い)人々の功績を評価するために使われます。
  • Cc: パッチのコピーを受け取り、それについてコメントした人の名前を示します。

パッチにタグを追加する際には注意が必要です。その人の明示的な許可なしに名前を記載してもよいのはCc: の場合のみです。

5.5: パッチの送付

パッチをメールで送信する前に考慮すべきことがいくつかあります。

  • 自分が使用しているメーラーがそのパッチを壊すことがないと確信できますか?メール・クライアントにより行われる不必要な余白の変更や行折返しが含まれたパッチは受け取り側の環境に適合せず、その細部を検討してもらえない場合が多くなります。もし何らかの疑念があれば、そのパッチを自分宛に送り、そのまま正しく表示されることを確認してください。

Documentation/email-clients.txtには、パッチを送信する際に特定のメール・クライアントを正しく動作させるためのヒントがいくつか記載されています。

  • 自分のパッチにばかげた間違いが含まれていない自信がありますか?パッチは常にscripts/checkpatch.plを実行し、そこで出力される問題指摘に対処することが必要です。ただし、checkpatch.plはカーネル・パッチのあるべき姿について十分に検討した結果として具体化されたものですが、自分よりも有能だということはないということを忘れないでください。checkpatch.plの指摘による修正を行うとコードが更に悪化するような場合もあります。そのような場合、修正は行わないでください。

パッチは必ず平文テキストで送付することが必要です。添付ファイルにはしないでください。レビューアが返信する際にパッチの該当部分の引用が難しくなってしまいます。パッチは添付ファイルではなく、自分のメッセージ中に直接入力して下さい。

パッチをメールで送る場合、そのパッチに関心を持つ可能性がある人にもコピーを送ることが大事です。他の一部のプロジェクトとは異なり、カーネル・プロジェクトではコピー先が十分以上に多過ぎることを奨励しています。メーリングリスト上へのポストを関連する人々が必ず見るとは思わないでください。特に、コピー先には以下を含めることが必要です。

  • 影響を受けるサブシステムのメンテナー 既に述べた通り、まずMAINTAINERSファイルでこれらの人々を探します。
  • 同じ分野に関係する他の開発者、特に現在そこで活動中と思われる開発者。自分の対象とするファイルで過去に修正を行ったことのある人を git で確認することも有効です。
  • それがバグ報告や機能要求に対応したものであれば、その当初のポスト元にもコピーを送ります。
  • 関連するメーリングリストにコピーを送るか、または該当するリストがない場合はlinux-kernel に送ります。
  • そのパッチがバグ修正用の場合、その修正を次回の安定バージョンにも適用すべきか検討し、適用が必要な場合、stable@kernel.orgもパッチのコピーを受け取る必要があります。また、パッチ自体のタグにも「Cc: stable@kernel.org」を追加します。これにより、その修正がメインラインにマージされた時、安定化チームがその通知を受け取れるようになります。

パッチの受取人を選択する場合、最終的にそのパッチを承認しマージさせてくれる人は誰かを考えておくとよいでしょう。パッチをLinus Torvaldsに直接送り、彼にマージしてもらうことも可能ですが、通常はそのような方法はとられません。Linusは多忙であり、カーネルの特定部分の世話をするサブシステムのメンテナーが存在します。通常はメンテナーにパッチをマージしてもらうことになります。明確なメンテナーが存在しない場合、多くの場合は最後の手段としてAndrew Mortonがそのパッチを扱います。

パッチ本体には適切な表題行が必要です。パッチ表題行の正規のフォーマットは以下に示すような形になります。

[PATCH nn/mm] subsys: パッチの説明(1行)

ここで、「nn」はそのパッチの順番、「mm」はその系列に含まれるパッチの合計数、「subsys」は影響を受けるサブシステムです。当然ながら単一の独立したパッチの場合「nn/mm」は省略可能です。

大きなパッチ群の場合、パート・ゼロとして前書きを送ることが慣例になっています。ただし、この約束事は例外なく守られているわけではありません。これを使う場合、その前書きの内容はカーネルのchangelogには含まれないことに注意してください。そのため、パッチ自体に完全なchangelog情報を含めるようにして下さい。

原則として、複数の部分で構成されるパッチの場合、2番目以降の部分は最初の部分に対する返信として送ることが必要です。これによりすべての送信が受信側ではひとつのスレッドでつながります。gitやquiltなどのツールには、ひとつのパッチの組を適切にスレッド化して送信するコマンドが含まれています。ただし、長い組のパッチでgitを使う場合、「--no-chain-reply-to」オプションを設定し、過度に深いネスティングは避けるようにして下さい。