linux-next に patch 投げた -> 入った
LinuxCon で話した kernel hackers に linux-next を使え、と言われたので linux-next を使おうとしました。とりあえず、いつも通りの make oldconfig
% git clone git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git % cd linux-next % zcat /proc/config.gz > .config % make oldconfig
ところが、 oldconfig がうまく動いていないです。なぜか、すでに定義してあるはずの "EXPERIMENTAL" を "NEW" と認識しています。 .config がうまく読まれてないですね。
<snip> scripts/kconfig/conf --oldconfig Kconfig # # using defaults found in /boot/config-2.6.34-ccs-r1 # * * Restart config... * * * General setup * Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [N/y/?] (NEW)
とりあえず、適当なとこでテストしてみて git bisect を試みます。
% git checkout v2.6.36-rc6 % make oldconfig # <- 普通に動く % git bisect start master v2.6.36-rc6
結果、こういうことになった最初の commit は 8f9b217448dfb8acf2b320960247d3139c9744a6 だったとわかります。
% git show commit 8f9b217448dfb8acf2b320960247d3139c9744a6 Merge: c193b46 0455029 Author: Michal Marek Date: Wed Sep 29 14:10:52 2010 +0000 Merge branch 'kconfig' into for-next diff --cc arch/mips/Kconfig index 3ad59dd,3377167..9f61741 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@@ -10,12 -10,8 +10,10 @@@ config MIP select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_KPROBES + select HAVE_KRETPROBES select RTC_LIB if !MACH_LOONGSON - mainmenu "Linux/MIPS Kernel Configuration" - menu "Machine selection" config ZONE_DMA
一見 "make oldconfig" で実行されるプログラム "scripts/kconfig/conf" には関係ないように見えます。でも、よく見るとこれはマージコミットなので、この二つの親から原因が来てるはずです。
親1 c193b46 >--- 8f9b217448dfb8acf2b320960247d3139c9744a6 親2 0455029
問題のコードあたりにおける親とマージコミットの差分を見てみます。
% git diff c193b46 8f9b217448dfb8acf2b320960247d3139c9744a6 scripts/kconfig/ <snip> # とにかくいっぱい % git diff 0455029 8f9b217448dfb8acf2b320960247d3139c9744a6 scripts/kconfig diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore index 6a36a76..624f650 100644 --- a/scripts/kconfig/.gitignore +++ b/scripts/kconfig/.gitignore @@ -17,6 +17,7 @@ gconf.glade.h # conf mconf +nconf qconf gconf kxgettext diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index eba5906..5459a38 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -598,12 +598,12 @@ int main(int ac, char **av) break; case savedefconfig: break; - case oldconfig: case oldaskconfig: rootEntry = &rootmenu; conf(&rootmenu); input_mode = silentoldconfig; /* fall through */ + case oldconfig: case listnewconfig: case oldnoconfig: case silentoldconfig:
親2 "0455029" とマージコミットの差分はそんなにない、のでおそらくは "0455029" 系のツリーの中に bug を(潜在的に)起こす commit がある可能性が高いです。ログを調べます。
% git log ..0455029
……正直わかりません ^^;
省略した diff に戻ります。上からあやしそうな diff を探していきます。 printf とかが変わっているのはどうでもいいですね。
あやしげな diff を見つけました。
--- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -221,24 +221,23 @@ load: while (fgets(line, sizeof(line), in)) { conf_lineno++; sym = NULL; - switch (line[0]) { - case '#': - if (memcmp(line + 2, "CONFIG_", 7)) + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) continue; - p = strchr(line + 9, ' '); + p = strchr(line + 2 + strlen(CONFIG_), ' '); if (!p) continue; *p++ = 0; if (strncmp(p, "is not set", 10)) continue; if (def == S_DEF_USER) { - sym = sym_find(line + 9); + sym = sym_find(line + 2 + strlen(CONFIG_)); if (!sym) { sym_add_change_count(1); break; } } else {
switch を if に書きかえているようです。ところが、 switch で使っていた break はそのまま残っていますね。これでは break は while の外側に出ていしってしまいます!
ログに戻ってそれっぽい commit の捜索...
% git log ..0455029 <snip> commit 8baefd30b5b0101aa07aa75da44a9eee881eed28 Author: Arnaud Lacombe Date: Tue Aug 24 00:14:47 2010 -0400 kconfig: replace a `switch()' statement by a more flexible `if()' statement With the upcoming dynamical configuration prefix, we can no longer assume that the prefix will start by a 'C'. As such, we can no longer hardcode this value in the `case ...:', so replace the `switch() { ... }' statement by a more flexible 'if () { ... }' statement. Signed-off-by: Arnaud Lacombe Reviewed-by: Sam Ravnborg Reviewed-by: Michal Marek
間違いなくこれですね。内容を確認。
% git show 8baefd30b5b0101aa07aa75da44a9eee881eed28 commit 8baefd30b5b0101aa07aa75da44a9eee881eed28 Author: Arnaud Lacombe <lacombar@gmail.com> Date: Tue Aug 24 00:14:47 2010 -0400 kconfig: replace a `switch()' statement by a more flexible `if()' statement With the upcoming dynamical configuration prefix, we can no longer assume that the prefix will start by a 'C'. As such, we can no longer hardcode this value in the `case ...:', so replace the `switch() { ... }' statement by a more flexible 'if () { ... }' statement. Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Michal Marek <mmarek@suse.cz> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index dc11d51..d9181de 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -221,8 +221,7 @@ load: while (fgets(line, sizeof(line), in)) { conf_lineno++; sym = NULL; - switch (line[0]) { - case '#': + if (line[0] == '#') { if (memcmp(line + 2, "CONFIG_", 7)) continue; p = strchr(line + 9, ' '); @@ -254,12 +253,7 @@ load: default: ; } - break; - case 'C': - if (memcmp(line, "CONFIG_", 7)) { - conf_warning("unexpected data"); - continue; - } + } else if (memcmp(line, "CONFIG_", 7) == 0) { p = strchr(line + 7, '='); if (!p) continue; @@ -286,12 +280,9 @@ load: } if (conf_set_sym_val(sym, def, def_flags, p)) continue; - break; - case '\r': - case '\n': - break; - default: - conf_warning("unexpected data"); + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); continue; } if (sym && sym_is_choice_value(sym)) {
やっぱり、ここで break の変更を忘れています。 break のところを if(){}else if{} ... else{} を脱出するように書き直してあげたところうまく "make oldconfig" が動くようになりました。
linux-next へ投げてみたところ無事マージされました。
http://thread.gmane.org/gmane.linux.kernel/1043051
(ほんとのところはこんなにうまくはいかず、 "NEW" で grep したり printf をはさんだりしてこの場所を特定しています…)