twitter icon   twitter icon   rss icon

Linux.com Japan

Home Linux コミュニティ カーネル開発者への道 Kernel MessageにIDを!

カーネル開発者への道

『Kernel MessageにIDを!』

Act3:ついにプロトタイプパッチへ!

「次 のステップはプロトタイプパッチを作って議論すべき」とのTedの意見を受け、メッセージDB TFの主要メンバーの一人であるNTT OSSセンターの伊藤和夫から、以下のメールはTed へ配信された。 

Hi all,



On 2010/07/25 21:40, Takahashi, Hideki wrote:


>>>      -  What is the best way for the next step?

>>>         Making a prototype patch we'd like to have and sending it to

>>>         you for having your comments, or something else?

>>
>> I think a prototype patch would be the next step, yes.  I think it

>> should be relatively easy to do....



So, here it is at last.  Sakaue-san did most of the work, and
 I (kazuo ito) just made it compile, supplied a quick-hack Kconfig, and translated (or made up? -- please check!) discussion between the author and me.


---->8------>8------>8------>8------>8------>8------>8------>8—



What is it?

-----------


This patch provides an optional enhancement to printk(), configurable by CONFIG_TBD, to print automatically generated message ids.


TBD: It would be nice to make it a set of patches comprising of a generic framework/hook and printk with msg id as its first application.


Rationale
---------

Message ids would help users unfamiliar with part of the code in question to locate where messages come from, facilitating them to analyse problems, file bug reports, and so on.


Given their enough uniqueness, they could also be used as compressed strings to store more messages in the dmesg buffer if vast majority of the format strings occupy much larger space than their id counterparts.


TBD: more attractive usecases.


Implementation
--------------

There are a couple of places where we can implement our proposal:

- a configurable macro replacement for (v)printk or its implementation;

- configurable code section in vprintk a la printk_time; and

- set of printk wrapper macros.


Macro replacement of (v)printk is the most flexible and TDB: use cases.

An if clause in vprintk like printk_time yields the simplest implemention, and one can expect uniform behaviour from all the invocations of (v)printk.

 

A set of printk wrappers doesn't require changes to kernel/printk.c but the rest of the kernel, which isn't very practical goal to pursue.


Message ID's are computed at run time.  While compilation-time calculation would be useful for embedded system where we would be able to substitute message ID's for format strings in kernel binaries, it does not work when the the format argument to (v)printk is a variable.


To identify a vprintk invocation (almost) uniquely, (TDB: message ID)


  Note:

The tentative patch uses hash value alone.

Ted's patch outline uses __PATH__, __LINE__, and hash.



Although  traditional cpp build-ins __FILE__ and __LINE__ could have been used for the same purpose if kernel version is supplied with them, we consider them to be no better than hash based message ID (+ file/path) because one has to look at another place to find kernel version.



Patch
-----
As a starting point, it tentatively follows the easiest way, i.e. an additional configurable code section in vprintk.


TBD: Work on it.  It's just a straw man.

TBD: find best place to put the Kconfig entry.



diff --git a/kernel/printk.c b/kernel/printk.c

index 444b770..ed01714 100644

--- a/kernel/printk.c

+++ b/kernel/printk.c


@@ -564,6 +564,13 @@ static int printk_time = 0;


 #endif


 module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);

+#if defined(CONFIG_PRINTK_MSGID)

+static int printk_msgid = 1;


+#else

+static int printk_msgid = 0;


+#endif

+module_param_named(msgid, printk_msgid, bool, S_IRUGO | S_IWUSR);

+
 /* Check if we have any console registered that can be called early in

boot. */ static int have_callable_console(void)

 

 {@@ -788,6 +795,26 @@ asmlinkage int vprintk(const char *fmt, va_list args)


                                       emit_log_char(*tp);

                               printed_len += tlen;


                       }


+                       if (printk_msgid) {


+                               #define MSG_HASH_LEN 256*256


+                               char midbuf[10];


+                               const char *p;


+                               unsigned midlen;


+                               unsigned long mid;


+
+                               mid = 0;


+                               p = fmt;


+                               while (*p && *p != ':')


+                                       p++;


+                               if (!*p)


+                                       p = fmt;


+                               while (*p)


+                                       mid += *p++;


+                               midlen = sprintf(midbuf, "(%05lu): ", mid % MSG_HASH_LEN);


+                               for (p = midbuf; p < midbuf + midlen; p++)

+                                       emit_log_char(*p);

+                               printed_len += midlen;

+                       }



                       if (!*p)

                               break;

 

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug

index e722e9d..b2fdaa3 100644

--- a/lib/Kconfig.debug

+++ b/lib/Kconfig.debug

@@ -9,6 +9,14 @@ config PRINTK_TIME

         operations.  This is useful for identifying long delays

         in kernel startup.


+config PRINTK_MSGID

+       bool "Show message id on printks"

+       default n

+       depends on PRINTK

+       help

+         Selecting this option causes message id to be

+         included in printk output.

+
 config ENABLE_WARN_DEPRECATED

       bool "Enable __deprecated logic"

       default y



 Signed-off-by: Hiroshi Sakaue < このメールアドレスは、スパムロボットから保護されています。アドレスを確認するにはJavaScriptを有効にしてください >

 Signed-off-by: Kazuo Ito <ito.kazuo@oss.ntt.co.jp>


--
伊藤 和夫 (kazuo ito)

  前提となる問題意識の共有や、方法論の議論は終了させ、 まずは議論のたたき台となるパッチを伊藤から、Ted および他のメッセージDB TFに向けて発信された。

実 装の選択肢として、(1) Tedからアイデアが示されたprintkのマクロによる置換、(2) カーネルメッセージにタイムスタンプを付与するパッチと同 様のvprintk内部への処理追加、(3) printkラッパーマクロの3種 類があるが、議論の起点として、最も修正範囲が少ない可能な実装 (2)を坂上・伊藤が提示した。

 

#1: There are no other ways than to make it a macro


Given format string hashes are not unique enough for message ids, we have to use macros to supply additional information like directory and or file name, or we would have to check and re-write all the invocations of (v)printk and put module names somewhere in their format strings.



#2: Breaking existing and well-known kernel APIs.


A question that keeps bothering me is that both printk and vprintk are EXPORT_SYMBOLs, with ominous 'asmlinkage' tucked in front of them.  Although I'm not sure if there's somethings special for them to be asmlinkage, makings them macros will certainly break kernel modules that

make use of these functions.


Regards,

 

  その後、伊藤より、(1) フォーマット文字列のハッシュ値だけではメッセージのIDの 一意性が不十分ならば、ディレクトリ、ファイル名などの追加情報を付加するためにマクロを使わざるを得ない、(2) よく知られたカーネルAPI であるprintkvprintkを変更してもよいものなのかという追加意見が出た。

こ れに対してTedからは下記の返信があった。 

The high level comments I have is:



1) Why not use a CRC?  There is a very nice 32-bit function that can
be found in lib/crc32.c in the kernel sources.  It will reduce the
number of new lines of code that you need to put into the printk
sources, and a CRC will give you a much better checksum than a simple
additive checksum --- especially when we consider that input data is
primarily going to be US-ASCII.



2) I'd suggest using hex instead of decimal, since it will result in a
smaller message digest (8 characters instead of up to 11).  In fact,
something that might even be worth considering is a base 36 encoding
(see: http://en.wikipedia.org/wiki/Base_36).

 


(中略)

One of the reasons why I suggested including __FILE__, __LINE__, and
__func__ is that it can be helpful in disambiguating the source of the
subsystem in case of hash collisions.  (Given that we are using a
32-bit hash, using random strings, given that there are 75,676
printk's in a recent version of the kernel, the probability of a hash
collision is just under 50%, due to the birthday paradox.  Using an
additive hash, and given a the decided non-random ASCII text, the
probabilities will be quite a bit higher; one of the reasons I
strongly urge use of a CRC.)



On the other hand, using __FILE__, and __func__ will substantially
 increase the size of the compiled kernel, which could be considered
unfortunate.

 


So I'd suggest maybe the better thing to do instead is to use a 64-bit
CRC, combined with a 13 character base-36 message code (i.e.,
8FQJD-5NOQ-3CW9).  This should reduce the chance of collisions to a
negligible level.  If you are concerned with collisions caused by two
identical strings being used in different contexts, with possibly
different meanings, you may want to mix in the filename into the CRC.

Best regards,

 


                                               - Ted

 

> #1: There are no other ways than to make it a macro

> Given format string hashes are not unique enough

> for message ids, we have to use macros to supply

> additional information like directory and or file

> name, or we would have to check and re-write all the

> invocations of (v)printk and put module names somewhere

> in their format strings.

 

Yes, if you care about two different format strings having different meanings, you will need to mix in the directory/file name information.

 

> #2: Breaking existing and well-known kernel APIs.

> A question that keeps bothering me is that both

> printk and vprintk are EXPORT_SYMBOLs, with ominous 'asmlinkage'

> tucked in front of them.  Although I'm not sure if there's

> somethings special for them to be asmlinkage, makings

> them macros will certainly break kernel modules that

> make use of these functions.

 

Breaking kernel modules' ABI is not anything upstream will care about.

(Remember, from LKML's perspective, out-of-tree modules are evil and deserve no solicitude.  We break ABI's for out-of-tree modules all the time.  Companies who are silly enough to have out-of-tree modules pay the price of needing to adapt to changing internal kernel ABI's.)

 

As far as the 'asmlinkage', that means there are assembly functions that will need to be fixed.  A quick "find . -name \*.[sS] | xargs grep printk" will turn up the various callers that will need to befixed.

 

But if we rename printk to __printk, and change to be a printk, aquick compile will turn up the assembly code users of printk easily enough --- and yes, they will need to be fixed.

 

Best regards,

 

                                       - Ted

  まず最初の返信では、Ted より次の2つ のコメントがあった。(1) カーネルにあるCRCを使えば行数も減るし、US-ASCII文字列に対してよりよいハッシュ値が得られる。(2) なぜ16進数でなく10進 数を使うのか?

 __FILE____LINE__を使う案は、ハッシュ値が競合した際の区別に役立つと考え てのことだが、__FILE__ __func__ はカーネル のサイズに少なからぬ影響があるのを嫌がる人もいるだろう。そう考えると、64ビットCRC36進数で表示するのがいいのではないか。これだと、13文 字で済むし、ハッシュ値が衝突する可能性も極めて低い、との主張であった。

  さらに続いてTedから(2つ目のメール)異なる場所にあるフォーマット文字 列を区別したければ、ディレクトリ/ファイル情報を含めるしか方法はない。upstream の開発者は、四六時中カーネルABIを変更しているから、ABI変更を気にする必要はない、とのアドバイスがあった。

 

難題の発生  〜オープンソース 本来の検討プロセスへの順応〜:

  プロトタイプパッチのたたき台はTedを含めた検討メンバーに出された。

  ところがここでこのプロジェクトへの取り組みに関する重要な課題が顕在化した。それは、オープンソース特有のメーリングリストベースでのコミュニケーショ ンへの対応である。

  本来オープンソースコミュニティの議論は、メーリングリスト(LinuxカーネルではLKML)を使い、高い透明性で、基本的には「個人」が議論の主体 となる。

  また、この開発プロセスはIBMなども非常に尊重しており、コミュニティの中での開発を徹 底するため、開発者同士の社内でのコミュニテーションを禁じていた時期もあったほどだ。 

 

参考:ITPro掲 載コラム『IBM副社長が語る「Linuxビジネス10年の教訓」』より

 

当時のIBMLinuxをエンタープライズ分野で活用するにあたり、「拡張性(Scalability)」、 「ファイルシステム」、「ボリューム マネジメント」などの分野に課題を抱えていた。この課題を解決するため、IBMは 開発したコードをコミュニティに提供しようとした。また、コミュニティと 対話をする際にも、事前に社内で何十時間にもおよぶ社内会議で対応をまとめた上でコミュニティと対峙した。

  しかし、一般的なビジネスプロシージャから考えればしごく当然のこの手法は、ことオープンソースの世界においては、Frye氏 の言葉を借りれば “It didn't work”(上手くいかなかった)のである。

 

  今回メッセージDB TFが採用しているプロセスは正にかつてIBMが実際に行い「上手く行かない」と判断したプロセスであ る。

  ただし、この開発プロセスは、日本人で、特にこれまでLKMLへ投稿したことが無い開発者にとっては寧ろ心強く、実際にTFメ ンバーがLKMLに投稿する段階では、議論はかなり煮詰まっているはずで、 投稿者は背後で何名もの同士がサポートしてくれているような、そんな安心感が得られるはずである。従って、ここまでの段階では、メッセージDB TFにとってはこれも一つのやり方であると言える。

  ところが、プロトタイプパッチがTedや他のMLメ ンバーに向けて発信された現段階では、このプロセスに限界が出て来た。

  問題点は2つ:

1.       日本のメンバー は、Tedからレスがある度に、実際にFace to Faceで会議を開催したり、もしくは日本側だけのMLで 協議を行い、纏まった結果を伊藤が代表してTedにぶつけていた。この一連のプロセスが、非常に冗長で時間 がかかる。

2.       Tedからすれば、メールには伊藤ばかりが返信するので、多くの 開発者が関心を持っているようには見えない。

  この点に関しては、参加のメンバーも当然理解している点ではある。ただ、慣れないプロセスであり、しかも英語でのコミュニケーションであると言う点が日本 側のメンバーを硬直させてしまう点であると考えられる。

  この課題は、いま現在も今後の課題として残っていくものである。

 


Linux Foundationについて

Linux Foundation はLinux の普及,保護,標準化を進めるためにオープンソース コミュニティに資源とサービスを提供しています

 

The Linux Foundation Japan

サイトマップ

問い合わせ先

サイトに関するお問い合わせはこちらまで

Linux Foundation Japan

Linux Foundation

Linux Training

提案、要望

Linux.com JAPANでは広く皆様の提案、要望、投稿を受け付ける予定です。

乞うご期待!