彷徨えるフジワラ

年がら年中さまよってます

Solaris10 のソース状態構築 - その1

DTrace Day 2010.03 で発表した Unlimited DTrace を、Solaris10 上で稼動させるには、Solaris10 向けに DTrace をビルドする必要が。

とりあえず DTrace の部分限定で良いので、OpenSolaris のソースを元に特定の版の Solaris10 相当のソースを構築できないか、OpenSolarisのMLに投げたところ、さとうさんから:

#各 Solaris 10 update release 毎に特定するのは難易度高すぎです

との返信が。

そういわれると俄然やる気になってしまう天邪鬼な私。基本的に職人肌の人間はそういうものだと思うけど、だからスーツの連中にまんまと顎でこき使われる、という話も。
それはともかく。

あーだ、こーだ、試行錯誤の末に、以下の結論に到達。

コンパイルの際に使用するヘッダは対象環境(Solaris10)の /usr/include 配下のものなので、まずは DTrace 関連のヘッダファイルを Solaris10 環境の /usr/include 配下のものと揃える必要がある

ということで、早速マッチング作業を。

修正済みバグ識別子の入手

Solaris10 の各 update における障害修正吸収状況は、各 update 毎のドキュメントの一部として "patch list" が公開されている。

但し、update1 から update5 までの patch list は RELEASE NOTE の一部として(例: "Solaris 10 5/08 Release Notes")、それ以後の patch list は独立したドキュメント(例: "Solaris 10 10/09 Patch List")になっているので注意が必要。

patch list の HTML ページから:

  • ページ内容を入手(sparc/i86 向け両方)
  • バグ識別子のみを抽出して、1行1バグ識別子化
  • 各 update 毎に両アーキテクチャのバグ識別子一覧を統合したファイルを作成

ということで、grep やら tr やらを駆使して、s10u1 〜 s10u8 までの 8 つのファイルが完成。

関連リビジョンのログの取得

OpenSolaris ソースリポジトリMercurial で手元に clone した上で、以下のコマンド実行をする。

hg log --template '======== {rev}:{node|short}\n{desc}\n' \
    usr/src/uts/common/sys/dtrace.h \
    usr/src/uts/common/sys/dtrace_impl.h \
    usr/src/lib/libdtrace/common/dtrace.h \

これで /usr/include 配下にインストールされるヘッダファイルに関する全履歴が表示される。厳密には "-k" 指定を併用しないと駄目な場合があるのだけど、OpenSolaris の履歴は基本一本道なので、同一ファイルへの同一修正は発生する筈が無いから気にしないことに。

出力は以下の感じ。

    :
    :
======== 5478:d21b1fd9aff6
6600430 library dependencies for DTrace
6602183 names of all non USDT based providers ....
======== 4421:8ddf0d909338
6491350 Auto mpss and kpr combo can ....
======== 4291:2650d270ece9
    :
    :

ワザワザ "--template" 指定をしているのは、コミットログ=取り込み済みバグ識別子を全て表示したいのと、日付等の余計な情報を取り除きたいため。

バグ識別子とのマッチング実施

各 update におけるバグの取り込みの有無を、各リビジョンのコミットログ中のバグ識別子から判定するための Python スクリプト(mark_bugid.py)をでっちあげる。

import sys

patchid2update = {}

for updateid in sys.argv[1:]:
    fp = open(updateid)
    for patchid in fp:
        patchid = patchid.strip()
        update = patchid2update.setdefault(patchid, [])
        update.append(updateid)

for line in sys.stdin:
    line = line.strip()
    if (line.startswith('========') or
        line.startswith('PSARC ')):
        print ('%s' % (line))
    else:
        patchid = line[:line.find(' ')]
        update = patchid2update.get(patchid)
        if update:
            print ('+(%s) %s' % (','.join(update), line))
        else:
            print ('%s' % (line))

バグ識別子一覧ファイル(s10u*)と、関連リビジョンログ(dtrace_headers.log)を以下の要領で処理させると:

$ python mark_bugid.py s10u* < dtrace_headers.log
    :
    :
======== 5478:d21b1fd9aff6
6600430 library dependencies for DTrace
6602183 names of all non USDT based providers ....
======== 4421:8ddf0d909338
+(s10u5,s10u6,s10u7,s10u8) 6491350 Auto mpss and kpr combo can ....
======== 4291:2650d270ece9
    :
    :

こんな感じで、各バグがどの update で修正されたものかをマーキングしてくれる。

マーキング結果によると、ヘッダファイルに対する修正適用状況は:

  • Solaris10update5 〜 Solaris10update8 は 8ddf0d909338 どまり(d21b1fd9aff6 は未取り込み)
  • Soalris10update4 は b34b45f03271 どまり(48f0fd311ddb は未取り込み)
  • それ以前の版は対応するのが嫌になるほど古いので無視

という結果に。

未取り込みリビジョン以前で一番大きなタグ付け対象リビジョンを、ソースのベースとすることに。

  • Solaris10update5 〜 Solaris10update8 は onnv_78
  • Soalris10update4 は onnv_65

但し、つまみ喰い的にバグ修正が取り込まれているため、例えば以下のリビジョンはベースリビジョンよりも前にコミットされているにも関わらず、Solaris10update8 時点ではこれらによる障害修正が取り込まれていなかったりする。

なので、これらに関しては、DTrace に関する修正部分だけを逆向きパッチで backout してやる。

backout に関しては、芋蔓式に依存性のある修正の backout が必要になるかも?などと思っていたけど、予想よりもすんなり成功。唯一、2650d270ece9 が依存している 854a761722c7 を backout 対象に追加したぐらい。

まぁ、854a761722c7 に関しては厳密に言うと backout が一部 reject されてしまったんだけど、実害の無い程度の失敗なのと、ここから派手に芋蔓しそうだったので、とりあえず妥協。

これで、ベースソースを確定することができるので、次は実際に Solaris10 環境にソースを持って行ってのビルド実験と行きましょう。

ここまでは、あくまで DTrace 関連のヘッダファイルに限定しての調査なので、実は大きなカーネル内部 I/F (関数引数や、構造体定義など)の変更が Solaris10 では未取り込み、なんてことで、このままではビルドできない可能性も無いわけでは無い。

そうなると、後は地道に backout の繰り返しだなぁ。

まぁ、ヘッダファイルの変更履歴調査と同じ要領で、ソース部分の Solaris10 取り込み状況もチェックを済ませてあるので、それほど酷い話にはならなと思う(思いたい)けどね。