LinuxカーネルHack: GMailで購読中のMLに投げられたパッチをLinuxカーネルに適用する方法

久しぶりに、Linuxカーネルのメインラインをgit pullして、UMLカーネルをビルドしようとしたら、ビルドに失敗してしまった。原因はビルドできない壊れたコードがメインラインに入ってしまったため。今回は、ビルドできるようになるまでにやったことから、手順を整理し、Linux Kernel Mailing Listなどで流れているパッチをカーネルに適用するまでの流れを書いておこうと思う。今回の内容は、GMailで購読中のMLからパッチを当てる場合に今後も参考になると思う。

1. 問題の発見

ビルドしようとすると、ptrace.cがビルドできなくなっていることが判明。

% make clean
% make ARCH=um defconfig
% make ARCH=um
[...]
arch/um/kernel/ptrace.c: In function ‘arch_ptrace’:
arch/um/kernel/ptrace.c:125: error: ‘datavp’ undeclared (first use in this function)
arch/um/kernel/ptrace.c:125: error: (Each undeclared identifier is reported only once
arch/um/kernel/ptrace.c:125: error: for each function it appears in.)

2. 調査

arch/um/kernel/ptrace.cの変更履歴をチェック。つい最近の変更があった模様。どうやら、このコミットで壊れたようだ。

% git log -p --color arch/um/kernel/ptrace.c
      1 commit 0a3d763f1a68c97daae57e40c6d698986d1b38f4
      2 Author: Namhyung Kim <namhyung@gmail.com>
      3 Date:   Wed Oct 27 15:34:04 2010 -0700
      4
      5     ptrace: cleanup arch_ptrace() on um
      6
      7     Remove unnecessary castings using void pointer and fix copy_to_user()
      8     return value. Also add missing __user markup on the argument of
      9     arch_ptrctl().
     10
     11     Signed-off-by: Namhyung Kim <namhyung@gmail.com>
     12     Cc: Jeff Dike <jdike@addtoit.com>
     13     Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
     14     Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
     15
     16 diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
     17 index 963d82b..a5e33f2 100644
     18 --- a/arch/um/kernel/ptrace.c
     19 +++ b/arch/um/kernel/ptrace.c
[...]
     50         case PTRACE_SET_THREAD_AREA:
     51 -               ret = ptrace_set_thread_area(child, addr,
     52 -                                            (struct user_desc __user *) data);
     53 +               ret = ptrace_set_thread_area(child, addr, datavp);
     54                 break;

もしかして、Linux Kernel Mailing Listにすでにパッチが投稿されているかも?と考え、検索。GMailで購読してるので、検索は圧倒的に楽。「datavp」で検索。ビンゴ。

Both 0a3d763 and 9b05a69 broke the um build.
This patch fixes the issues.

0a3d763 introduced the undeclared variable "datavp".
The patch seems completely untested. :-(

9b05a69 changed arch_ptrace()'s signature but did not
update um/include/asm/ptrace-generic.h.

http://linux.derkeiler.com/Mailing-Lists/Kernel/2010-10/msg12263.html

3. パッチの取得

パッチファイルは、ブラウザの画面に表示されてるパッチをコピー&ペーストで作れば出来そうだけど、実はこれではうまくいかない。意図しない所で改行が入ってしまうので、パッチファイルとして使えないから。(自分もミスった)

メールソースを取得すれば、ありのままのメッセージが取得できる。メールソースからパッチを当てればうまくいく。

手順としては、GMailの「返信」の右隣にある「▼」から「メッセージのソースを表示」を選択。次に、ブラウザの「ファイル」->「名前を付けてページを保存」を選択。手元の環境では、WindowsGMailを見てて、SambaでWindowsLinuxを共有しているので、WindowsからLinuxに直接ファイルを保存した。

4. パッチの適用

保存したパッチをあてる。パッチ(diff)の前に、メールヘッダーやらがあって、一見うまくパッチを適用できなさそうだけど、うまくあてられる。

% cd ~/linux-2.6
% patch -p1 < um.patch
patching file arch/um/include/asm/ptrace-generic.h
patching file arch/um/kernel/ptrace.c

再度make。無事makeが通るようになった。

追記(2010/10/31)

git amの方がログに残るし便利とのコメントをいただいたので、早速試してみた。

パッチ適用。おー!できた!「um: fix ptrace build error」のメッセージはどこからひっぱってきているのかな?と思ったら、メールソースのSubjectからみたい。

% git am um.patch
Applying um: fix ptrace build error

git logを見てみると、パッチの内容からログメッセージがちゃんと入ってる。確かに、パッチを受け取った側は、git amでパッチ適用する方が便利!問題なければ、後はgit pushするだけと。よくできてる。

% git log
commit 69f4b578ea0829b3d083800dd3a6d043b4622373
Author: Richard Weinberger <richard@nod.at>
Date:   Thu Oct 28 17:42:30 2010 +0200

    um: fix ptrace build error

    Both 0a3d763 and 9b05a69 broke the um build.
    This patch fixes the issues.

    0a3d763 introduced the undeclared variable "datavp".
    The patch seems completely untested. :-(

    9b05a69 changed arch_ptrace()'s signature but did not
    update um/include/asm/ptrace-generic.h.

    Signed-off-by: Richard Weinberger <richard@nod.at>

git amはコミット権が無いとできないのかと思っていたらそうではなかった。思い込みはいけないな。。

git applyも試してみたけど、単にパッチ適用したい場合はこっちも使えそう。

ちなみに、適用したパッチのコミットを取り消すには、以下のコマンドでできる。「^」を付ける必要あり。

% git reset --hard HEAD^
HEAD is now at c0f62ed... Merge branches 'msm-fixes' and 'msm-video' of git://codeaurora.org/quic/kernel/dwalker/linux-msm

git applyとgit amは、このページの解説が参考になる。
http://progit.org/book/ja/ch5-3.html

apply でのパッチの適用
[...]
これは、作業ディレクトリ内のファイルを変更します。patch -p1 コマンドでパッチをあてるのとほぼ同じなのですが、それ以上に「これでもか」というほどのこだわりを持ってパッチを適用するので fuzzy マッチになる可能性が少なくなります。また、git diff 形式ではファイルの追加・削除やファイル名の変更も扱うことができますが、patch コマンドにはそれはできません。そして最後に、git apply は「全部適用するか、あるいは一切適用しないか」というモデルを採用しています。一方 patch コマンドの場合は、途中までパッチがあたった中途半端な状態になって困ることがあります。git apply のほうが、全体的に patch よりもこだわりを持った処理を行うのです。git apply コマンドはコミットを作成するわけではありません。実行した後で、その変更をステージしてコミットする必要があります。

patchコマンドよりも優れていると。

「「これでもか」というほどのこだわりを持ってパッチを適用する」凄い気になるこの一文。何してるんだろうw?