トップ «前の日記(2003年08月31日) 最新 次の日記(2003年09月05日)» 編集
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|10|12|
2009|02|03|06|07|10|11|12|
2010|01|02|03|04|07|09|10|11|12|
2011|01|03|04|05|06|07|08|10|
2012|01|06|08|09|10|12|
2013|01|02|03|04|07|09|11|12|
2014|01|03|04|05|06|09|
2015|04|
2016|01|08|
ここは旧えびめもです。えびめも2に移行します(2016/12/1)

2003年09月04日 晴れ

Linuxカーネル八苦

先月のARCNETのRFC1051問題に引き続き、またdeepなbugを発見した。 この案件はかなりbug出しに貢献しているとおもうぞ。

BUGの状況は、sh/linux-2.4.21, samba 2.2.3a-12 を利用して、WindowsXP機の共有フォルダを smbmount すると、日付が全て 1970/1/1 になってしまう問題が出た。ちなみに、同じバージョンのi386機で検証するとbugが出ない。やっかいだ。簡単に直るとは思わない。経験的に、こういうときに考えられる原因としては、

1.エンディアン(バイトオーダ)の違い
2.intサイズの違い
今回はどちらも 32bit little endianだ。
3.バイトアライメント制限の違い。
ネットワークプロトコルのヘッダーを、構造体のポインタ変数でキャストして読むと構造体のpackの隙間の違いで、メンバーがずれる問題が発生することがある。普通はそういうことがおきないようにプロトコルヘッダーを組むんだけど。。。

まずはSMBのプロトコル仕様書を探さないとなぁ。。なんてかなり基礎からの洗い直しを覚悟した。ところが、日付のうち、時刻はどうなっているか ls の --full-time オプションで調べたところ、

# ls /mnt/ -l --full-time
合計 115
drwxrwxr-x    1 root     ebihara      4096 木  1月 01 09:05:09 1970 10.開発資料
drwxrwxr-x    1 root     ebihara      4096 木  1月 01 09:05:37 1970 20.客先別書類
drwxrwxr-x    1 root     ebihara      4096 木  1月 01 09:00:40 1970 30.総務経理受発注関連
といった具合に、時刻は 数分〜数秒 の範囲でバラけていた(時間が9時間プラスされているのはtimezoneだろう)。ここから想像するに、タイムスタンプの割り算の余りが分秒になっていて、商が0000になっている(=UNIX時間で1970/1/1) と想像が付いた。

調べを進めるとNTのタイムスタンプは、UTCベースを 1601/1/1 からの経過0.1マイクロ秒時間とした64bit値であることがわかった。一方UNIX時間は知ってのとおり1970/1/1からの経過秒数(32bit値)だ。ここまでわかればもうちょいだ。SH3CPUでの64bit演算が怪しい。で、linuxカーネルの fs/smbfs/proc.c の

#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
smb_ntutc2unixutc(u64 ntutc)
{
        /* FIXME: what about the timezone difference? */
        /* Subtract the NTFS time offset, then convert to 1s intervals. */
        u64 t = ntutc - NTFS_TIME_OFFSET;
        do_div(t, 10000000);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ここが怪しいというところまで踏み込めたので、あとはlinuxカーネルソースの include/asm-sh/div64.h に対する以下のパッチをあてたところ、案の定正常動作になった。
--- include/asm-sh/div64.h-orig Fri Sep  5 01:48:09 2003
+++ include/asm-sh/div64.h      Fri Sep  5 01:31:54 2003
@@ -3,8 +3,8 @@
 
 #define do_div(n,base) ({ \
 int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
+__res = ((unsigned long long ) n) % (unsigned) base; \
+n = ((unsigned long long ) n) / (unsigned) base; \
 __res; })
 
 #endif /* __ASM_SH_DIV64 */
u64型割り算演算が libgcc の __udivdi3 を利用するのでmoduleにexportするなら(smbfs.oをモジュールにするなら)arch/sh/kernel/sh_ksyms.c にシンボルを追加する必要がある。
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
 DECLARE_EXPORT(__sdivsi3);
 DECLARE_EXPORT(__ashrdi3);
 DECLARE_EXPORT(__ashldi3);
 DECLARE_EXPORT(__lshrdi3);
+DECLARE_EXPORT(__udivdi3);
答えだけ書くと簡単な話だけども、発見するのに2日仕事時間とられてしまった。(>_<)

火星

8/28に地球に大接近だった。残念ながら8/28は雲っていて火星を見ることは出来なかったが8月に入ってから毎日のように明るく輝いていた。昨日も薄雲を通り越して火星が光っていたのには驚いた。雲越しに見える天体なんて月くらいのものだろうに。極大を超えてから、火星は急速に西に移動しているようだ。仕事が終わって会社を出て空を見上げると、だいたい毎日同じ時間だが、どんどん西に逃げているように思う(調べてないけど)。さようなら火星。思い出をありがとう。あっという間に過ぎ去った、短かった2003年の8月の夜は、君の思い出でいっぱいだ。

こおろぎ

り〜ん、り〜ん、り〜ん、と室内からコオロギの声が聞こえた。驚いた。もう秋なのか。

室内で鳴いているようだけど、探そうにも近づくと黙ってしまう。皆で静かにしていたら、植木鉢の下から出てきた。外に逃がした。外は意外と涼しい。