凪のあすから聖地巡礼2024(10周年記念 熊野市スペシャルトークショー参加記)

前回

kujira16.hateblo.jp

前回の訪問からの出来事

前に熊野市を訪れたのは2018年の春だったので、凪のあすからの放送開始から4.5周年くらいの時期だったということになります。凪のあすからは放送当時は爆発的に人気を博したわけではなかったと思うのですが、ファンには今でも根強い人気があり、放送から何年も経ってからも展示会の開催や新規イラストの公開、新規グッズの販売などが行われていました。

2019年(放送開始からだいたい6年)の「色づく世界の明日から」とのコラボレーション展

2021年(放送開始から8年)の「色づく世界の明日から」「白い砂のアクアトープ」とのコラボレーション展。10時に整理券を受け取って入場できたのが16:30とかだった記憶があります。

時が経つのは早いもので、公式から10周年である旨のツイートが出たのを見たときには「ついこの前は5周年だったはずなのに…」という感じでした。今年も何やってくれるのかな?さすがにもう難しいかな?と思っていたところ、「10周年記念CMを一緒に見よう!」という趣旨の Twitter スペースにて、今年は凪あす10周年記念イヤーとしてさまざまな企画を準備している旨の発表が行われていました。

またグッズの販売などやってくれるのかな?と期待していたところ以下の告知が行われました。

トークショーをやってくれるのか! 10年も前のアニメなのに!

開催場所は…… 三重県熊野市!?!?!?

準備

公式のバスツアーが企画されており参加費6万円を払って行くつもりだったのですが「6万円を即決できる人はそこまで多くないだろうし、家に帰ってから申し込むか」と思って油断していたらあっという間に枠が無くなってびっくりしました。あのときすぐ申し込むべきだった…

そういうわけで自前で諸々を手配しました。前回の聖地巡礼をしたときには私は奈良に住んでいて列車の時間さえ合わせれば片道4時間程度で行くことができたので、訪れる場所を絞ればなんとか日帰りでも行けたのですが、さすがに今回は片道6時間ほどかかるので余裕を持ったスケジュールを組みました。最終的には月曜日に休みを取って2泊3日のスケジュールとしました。

せっかくなので熊野市内で宿泊も手配したかったのですが、市内で宿泊できる施設のキャパシティをオーバーしていたのか予約できなかったので和歌山県新宮市(特急で熊野市駅から1駅20分、各駅停車なら30分)で宿泊することにしました。

1月13日(土)

社会人パワーで躊躇なく特急料金を払って行きました。熊野市駅までは名古屋駅から特急で3時間ほどです。

名古屋駅での案内

乗った列車です。前回乗ったときから名称が「ワイドビュー南紀」から「南紀」に変わったり、4両編成が基本だったところ2両編成が基本になったり、30年前の時代を感じる車両だったところ2023年の夏に車両がモデルチェンジされたりしました。

特急南紀3号

新幹線によく乗る人は分かると思うのですが内装は明らかに N700S と共通している部分があります。全席コンセント利用可能、Free Wi-Fi あり、ということでスマホで時間をつぶしたい現代っ子でも心配いりません。ただし Free Wi-Fi も携帯電話もトンネルの中ではだいたい繋がりません。

ワイドビュー南紀」のころと比べて内装は大型アップグレード

車両がモデルチェンジしたことで気を付けないといけなくなったことがあります。それは座席の配置です。名古屋から熊野市方向への南紀ではD席が海側の席です。車両がモデルチェンジする前はA席が海側だったらしく、インターネット上の情報が混在しています。私はこれに気付かず海側と反対の席を予約してしまいました。逆に熊野市から名古屋方向への南紀ではA席が海側です

前回訪れた時と変わらず新鹿の海水浴場はきれいでした。

新鹿の海

熊野市駅も相変わらずでした。

熊野市駅

まずは熊野市観光案内所に行きました。1階の熊野市観光協会は道の向かい側の建物に入っていたと記憶していたのですが移転したようです。

熊野市観光案内所

目的はこれ!グッズも買いました。

聖地巡礼マップ

観光案内所の2階では凪のあすから10周年記念展が開催されています。

観光案内所の2階は10周年記念展

名シーンの原画も見ることができます

この場所では普段は熊野大花火大会の展示が行われているようです。

普段は熊野大花火大会の展示

展示を駆け足で見た後には列車で3駅戻って新鹿に向かいました。凪あすファン交流会による非公式の聖地巡礼ツアーに参加するためです。

twipla.jp

新鹿駅のひとつ前の波田須駅で、二木島の巡礼ツアーに行っていたグループと合流しました。「15名程度乗り込んでくる予定なのでそこで合流しましょう」と言われていたのですが、実際には30名近く乗り込んできたように思います。波田須駅は無人駅で、三重県統計書によれば一日の平均乗車人員が十数名程度のところ、一度に普段とは異なる人数が乗り込んできていたので地元の高校生が困惑していました。

新鹿駅も普段は無人駅です(花火大会の時だけ駅員が派遣されてくるらしい)。ワンマン列車のため、運転手さんに整理券を渡して現金で運賃を支払うシステムですが、このときも運転手さんが困惑していたような…

新鹿駅

新鹿駅の駅舎

アニメのキャプチャと一緒に新鹿を案内してもらいました。

ここの干物のお店は前回も開いていなかったのですが、夏の海開きしている間だけ開いているらしいです。

清七屋ストアーは営業していました。飲み物を買っている人もいました。

海水浴場では「海の色を巡りに」展で購入したアクリルスタンドと一緒に記念撮影。

熊野古道を歩いて波田須まで移動しました。熊野古道の中でも新鹿と波田須の間は比較的穏やかな山道なので、これくらいの険しさを想定して熊野古道のほかの山道を歩くと後悔するとのことです。

波田須では新鹿小学校波田須分校(旧波田須小学校)の校舎を見学させていただきました。この学校は19年前から休校中という扱い(あくまで廃校ではない)で普段は入ることができない場所となっています。

いつの日か再開されるときのために校舎は維持されているものの、何度も訪れている人によれば以前は無かった亀裂が入っている箇所があったり、ここ数年のうちに崩れたりしている箇所があるとのことでした。来年で休校から20年であり、波田須町の集落と新鹿をつなぐ唯一の道路に面しているということもあって、校舎の維持に関して今後どのような判断が行われるかは分かりません。いつか行きたいと思っている方は機会を逃さないように行動することをおすすめします。

この後は天女座にお邪魔させてもらい、TIKTOK で配信している演奏を鑑賞させていただきました。

このあとは波田須駅から新宮駅の宿へ。お刺身を堪能したり熊野地域の柑橘系のお酒を楽しんだりしました。

1月14日(日)

トークショーの前後でデジタルスタンプラリーで指定された観光スポットを回ることにしました。午前中は海ひかりと鬼ヶ城センターに行きました。

海ひかり

鬼ヶ城センター

鬼ヶ城センターで買ったおみやげ

鬼ヶ城

昼食をとろうと思っていたお食事処は開いていなかったので海辺でめはり寿司を食べました。

めはり寿司

昼過ぎからは10周年記念トークショーに行きました。開場時間近くになると熊野市駅前は聖地巡礼マップを手にした若い人で賑わっており、あっちにもこっちにも凪のあすからのファンだらけ、という状態になっていました。

会場は熊野市民会館でキャパシティは760名です。

熊野市民会館

トークショーの内容については Twitter でかんたんにまとめてくれている人が何人かいるのでそちらにお任せします。

前日の非公式聖地巡礼ツアーのとき、参加者の間で「どれくらい席が埋まるのだろうか」と心配する声が上がっていました。凪のあすからが素晴らしい作品であることを信じて疑わない熱心なファンの間でさえそういった不安の声が上がっていたのです。しかし実際に会場に行ってみるとほとんど空席はなく、トークショー内での発表では参加者は700人とのことでした。美浜町(熊野市の隣)出身の東地和生美術監督も「はるばる遠いところようこそお越しくださいました」「熊野でやると聞いたとき『嘘でしょ!?』と思った」という旨のことを話されていたくらいですが、これだけの人が集まったということで凪のあすからの根強い人気を再確認しました。

トークショー後は引き続きデジタルスタンプラリーで指定されている獅子巖(ししいわ)と花の窟(はなのいわや)を見に行きました。

獅子巖

花の窟

花の窟の近くの道の駅ではいろいろなお土産を買うことができます。

観光協会でデジタルスタンプラリーの景品の缶バッジとアンケート回答の景品のポストカードをもらいました。

1月15日(月)

最終日は宿泊した新宮市の観光スポットを訪れました。

浮島の森

浮島の森に渡る橋

新宮城跡の石垣

新宮城跡の石垣

熊野速玉大社

昼食にはこの地域の名物であるさんま寿司を頂きました。おいしいのでふるさと納税で取り寄せようかな…

さんま寿司

美しい海も見納めです。

メディアの反応

地域紙である吉野熊野新聞では10周年記念イベントについて一面で取り上げられていました。

www.shimbun-online.com

www.yomiuri.co.jp

www.chunichi.co.jp

www.chunichi.co.jp

おわりに

これまでの熊野市の聖地巡礼では凪のあすからの空気感を感じることができ、世界遺産の一部となっている観光スポットを楽しむことができたものの、公式にコラボして何かが行われていたわけではなかったので、何かあればいいのにな、と思っていました。今回このように大きな形でコラボが行われたことで「何か少し物足りないような気がするなぁ」と思っていた気持ちに区切りをつけられたように思います。熊野市を頻繁に訪れることは難しいですが、ふるさと納税などで細く長い関係が続けていければいいですね。そして凪のあすからはこれからも応援していきたいと思います。

ICPC 2023 Asia Yokohama Regional スタッフ参加記

今年もスタッフとして参加していました。

私の ICPC との関わり

  • 2012 - 2016: 選手
  • 2017: コーチ
  • 2018 - 2019: スタッフ
  • (2020 - 2021): オンライン開催のため関わりなし
  • 2022 - 2023: スタッフ

どうやったらスタッフとして参加できる?

以下から JAG に参加しましょう

jag-icpc.org

Day 0 (11/24)

参加していません(参加された方はお疲れさまでした)。

机並べやパソコンの設置、電源や LAN ケーブルの配線などが行われていたそうです(たいへんだ…)

Day 1 (11/25)

9時集合でした。私はスタッフとして参加するようになった最初の年から「君は選手として何回もアジア地区予選に来ているから受け付けで何を聞かれるか分かっているだろう」と言われて毎年受付の担当をやっているので、今年も引き続き受付を担当していました。@kyuridenamida (ICPC Secretaries) @smiken_61 (ICPC Secretaries) @pepsin_amylase (JAG) @blue_jam (JAG) @tsutaj (JAG) とホスト校の東工大の方(もはや世代が違いすぎて分からない)とやっていました。

入口のところで待機しておいて3人揃ったら受付に通す、というのが私の仕事だったのですが、イレギュラーなパターンがいくつか発生することがあり、うまく捌いていく必要があります。何年も担当していると、さすがに典型的なイレギュラーパターンについては分かってきます。今年は以下のようなことに気を付けながら受付に通していました。

  • 欠席の連絡を受けているチームを除いて3人揃うまで受付に通さない
  • 受付に通す前に学生証を用意させる(受付が混雑するので)
  • 海外の大学のチームの場合には学生証にラテンアルファベット表記が無ければパスポートも用意させる(現地語表記だけだと参加登録されている本人かどうか判定が難しい)
  • コーチが来ていないチームは不参加なのかまだ来ていないだけなのか聞く。開会式に間に合う予定の場合はコーチが来るのも待ってもらう。間に合わない場合は選手だけで入ってもらう
  • コーチが複数チームを兼任している場合はチームIDが最も小さいチームと一緒に受け付けに通す

開会式とリハーサル終了後は実行委員会からスタッフに夕食会の提供があり、JAG のスタッフ21名で横浜の中華街に繰り出しました。支払うお金(結構な大金)は事務局の方から私に託されていたのですが「お金を持っている人~!」という表現で呼ばれていたので複数人の知り合いからいじられました。横浜中華街の平均的なお店よりもグレードの高い中華だったため美味しかったです。

Day 2 (11/26)

8時15分集合でした。

朝から小雨が降っており、選手の傘をどうしようかという懸念がスタッフ用 Slack で持ち上がっていました。傘を入れるポリ袋が売っていないか横浜駅近くのドン・キホーテに探しに行ったのですが無かったので不安になりながら会場に向かいましたが、受け付け開始直前にはあまり降っておらず傘を持ってくる選手が少なかったので助かりました。来年はバックアッププランが用意されるのだと思います。

受け付けの仕事は

  • 学生証(必要ならパスポートも)に加えてTシャツと名札を着用しているか確認する
  • コーチは別室に案内する

ということが変わります。受け付け終了の5分前には全チームが入場できていたのでヒヤヒヤすることなく始められました。

コンテスト中は会場内の巡回、印刷物配り、トイレに行きたい選手の案内をしていました。話は変わりますが、私が ICPC のスタッフとして防ぎたいと考えていることの優先順位は、1. コンテスト全体が無効になる、2. 悪意がないのに選手が失格になる(失格にせざるを得ない状況になる)ことです。コンテストが無効になるというのは会場内の重要なケーブルが不通になることによって容易に発生するおそれがあり、スタッフは口うるさく DO NOT STEP ON THE CABLES と言っているわけです。また悪意がないのに選手が失格になるというのはトイレの場所が分からなくなってコンテスト会場外のスタッフ以外の人とコミュニケーションをとる、会場の建物の外に出てどこかに行ってしまう、などによって発生するおそれがあります。横浜産貿ホールでトイレは ICPC の参加者で占有しているわけではないので、この会場で開催している間はスタッフの付き添いが必要になりそうです。

印刷物配りでジョブが飛んでくるのを待っている間はコンテストの問題文(スタッフ向けの福利厚生として配布される)を読んで解いていました。たぶん自分が選手として出ていたら4完だったと思います。

コンテスト終了後はゴミ集め、おやつとして支給されたドーナツの摂取、コンテスト会場の片付けなどをしていました。

懇親会では自費制作した JAG 缶バッジの配布を @rian_tkb にお願いしていました。50個持って行ったのですがだいたい配り切れたと聞いているので満足です。

kujira16.hateblo.jp

おわりに

疲れましたがやりがいは感じられました。ICPC Secretaries や実行委員会の方は大変なのだと思いますが、JAG として参加する分にはプレッシャーはあまりなく気負わずに参加できるので次回も参加していると思います。

dm-integrity によるブロックデバイスのデータ破損の検出

Linux で利用可能な device mapper のひとつに dm-integrity があります。これは汎用的なブロックストレージにデータ破損を検出する機能を付与することができる仕組みです。この記事は dm-integrity について私が気になったいくつかのトピックをまとめたものであり、一部はドキュメントに記載されていない、ソースコードから読み取った内容を含んでいます。

device mapper とは?

dm-integrity は device mapper の一種です。device mapper は仮想ブロックデバイスを作成する機能で、Linux カーネルに組み込まれており LVM のバックエンドとして利用されています。基となるブロックストレージ (underlying device) に付加的な機能を追加した仮想的なブロックデバイスを作成することができます。たとえば仮想ブロックデバイスへの書き込みを複数の underlying device に分散させることで RAID を実現したり (dm-raid)、仮想ブロックデバイスへの書き込みを暗号化してから underlying device に書き込むことでユーザー空間から透過的にディスク上のデータを暗号化したり (dm-crypt) することができます。

dm-integrity が解決したい課題

プログラムからディスクに書き込んだはずのデータは、不幸なことに壊れている場合があります。プログラムや Linux カーネルに不具合が無かったとしても、たとえば以下のような原因でデータ破損が起きる可能性があります。

  • ストレージのファームウェアに不具合があり不正なデータが書き込まれた
  • RAID コントローラーに不具合があり不正なデータが書き込まれた
  • ストレージデバイスへの物理的なダメージにより書き込まれたはずのビット列が変化した

このようなデータ破損は bit rot や silent data corruption と呼ばれ、大規模なインフラを構築しているような企業では無視できない確率で発生する可能性があります。

dm-integrity では仮想ブロックデバイスに書き込んだデータをそのまま保存すると同時に、書き込んだデータのチェックサムを別の場所に記録します。読み出し時には読み出したデータのチェックサムと記録したチェックサムとの比較を行うことでデータ破損を検出します。

dm-integrity と dm-crypt を組み合わせたデータ保護

dm-crypt はディスクに書き込まれるデータを透過的に暗号化する機能を提供する device mapper です。dm-integrity は dm-crypt と組み合わせることもできます。dm-integrity のみを利用した場合はチェックサムとの比較によりデータ破損を検出できますが、データセンターへの不正な侵入や保守作業員の買収などの手段により攻撃者がストレージデバイスのデータを書き換え可能なとき、データとチェックサムの両方を改ざんされてしまった場合には改ざんを検出することができません。dm-integrity と dm-crypt を組み合わせると、データから計算したハッシュをチェックサムとするのではなく、データと秘密鍵から計算した HMAC をチェックサムとすることで、データやチェックサムの改ざんを難しくすることができます。

データが壊れてしまったら検出できても意味がないのでは?

読み出そうとしたデータが壊れていることが分かっても壊れる前のデータが読み出せるようになるわけではないため、それほど有用ではないのでは?と思うかもしれません。たしかに壊れてしまったディスクからデータを読み出すことはできませんが、検出できること自体が有用な場合があります。

まず壊れたデータを返すよりは、データが壊れていることが分かった時点で処理を停止して応答を返さないほうがよい場合があります。このような場合、データが壊れていることを検出するだけでも十分な意味があります。

次に分散システムを構築しているような場合です。少数のノード故障に耐えることを意図して作られた分散システムであれば、壊れたデータを含むノードは落としてしまうことで、データが壊れていない他のノードでサービスを継続することができます。

最後に RAID-1 などで複数のディスクにデータを保存しているような場合です。device mapper で作成されるのは仮想的なブロックデバイスのため、複数の物理ディスクそれぞれについて仮想ブロックデバイスを作ってから RAID で束ねるようなこともできます。このような構成では RAID を構成するそれぞれの物理ディスクについてデータ破損を検出するためのチェックサムが記録されることになります。データ破損が検出されたデバイスは壊れてしまったものとして RAID から切り離して残りのディスクでサービスを継続することができます。

dm-integrity 以外に同じ問題を解決する技術にはどんなものがあるのか?

dm-integrity は device mapper の仕組みを使うことでデータのチェックサムを付与する機能をブロックデバイス自体に付与していますが、これ以外のレイヤーでデータのチェックサムを付与している技術もあります。

データベースなどのアプリケーションやライブラリでは silent data corruption を想定した機能が備わっておりデフォルトで有効になっている場合が多いです。たとえば MySQL では innodb_checksum_algorithm という項目により設定可能ですが、16 KiB のページごとに CRC32 を付与し整合性をチェックする設定がデフォルトで有効になっています。

ファイルシステムレベルでチェックサムを持つ場合もあります。有名なのは Btrfs と ZFS です。

dm-integrity を採用することが適切な場面

silent data corruption の耐性があるシステムを構築する必要があるようなとき、どのような場面では dm-integrity を採用することが適切になるでしょうか?データにチェックサムを付与する機能がないファイルシステム(典型的には ext4 や XFS)を使わざるを得ない制約があり、かつアプリケーションレベルでチェックサムを付与することができないような状況が考えられます。

具体的には RHEL がサポートしている範囲のテクノロジーで silent data corruption への耐性があるシステムを構築したいという場合には候補に挙がるかもしれません。SUSE のデフォルトファイルシステムは Btrfs であり、近年の UbuntuZFS のサポートを強化していますが、Red Hat はこれらのファイルシステムには積極的ではありません。RHEL でよく使われている ext4, XFS に関しては、ext4 では metadata_csum オプション、XFS では crc= オプションによりファイルシステムメタデータにはチェックサムを付与できる機能がありますが、データにチェックサムを付与できる機能はありません。一方、RHEL では dm-integrity は TechPreview ではなく supported ということになっているようです。Red Hat には device mapper の開発者が多数在籍しておりストレージ機能の拡充を device mapper で解決する傾向がありますが、silent data corruption の対策も device mapper のレイヤーで問題を解決したいという方針なのかもしれません。

もし ext4 や XFS にもデータにチェックサムを付与する機能が搭載されるようなことがあれば dm-integrity は不要になるのでしょうか? 実は、ext4 や XFS にデータのチェックサムを付与する機能が搭載されただけではそれほど状況は変わりません。データにチェックサムを付与する機能がこれらのファイルシステムに搭載されたとして、データ破損が見つかった場合にできるのはファイルが破損していることを通知してデータの読み取りを拒否することだけです*1。一方、dm-integrity を使う方法では前述したように RAID と組み合わせることでデータ破損が見つかったディスクを RAID から切り離して残りのディスクでサービスを継続することができます。よって、もし ext4 や XFS にもデータにチェックサムを付与する機能が搭載されるとしても、dm-integrity は不要になるとは限りません。

3つの動作モードとその特徴

dm-integrity ではデータの書き込み時にデータとチェックサムの2つを書き込む必要があります。データベースのストレージレイヤーの心得がある人ならお察しの通り、これは書き込みを2回するだけの単純な操作ではありません。単純に2箇所を書き換えるだけではデータの書き込みとチェックサムの書き込みの間で予期しない電源断やカーネルパニックによって処理が中断されたとき、ディスク上に永続化されているデータとチェックサムが矛盾する可能性があります。

この対策として dm-integrity は3つの動作モードを提供しています。

  • J (journaled write): ジャーナルを利用するモードです。データ部、チェックサム部を変更する前にまず変更内容をジャーナルに書き出してディスクに永続化し、そのあとデータ部、チェックサム部に変更を適用します。最も整合性が強いですが、必要な書き込み量が増えるため性能的には不利です。

  • B (bitmap mode): データとチェックサムが一致していない可能性があるセクタをビットマップで管理するモードです。詳細は後述します。

  • D (direct write): 何も対策しない漢気モードです。電源断が生じたマシンを再起動したときには、データ破損が生じていなかったとしてもデータとチェックサムが一致しない可能性があります。またデータとチェックサムの矛盾が見つかったとしても、電源断によって起きた不一致なのかデータが破損したのか判別することができません。一方、オーバーヘッドはほかのモードと比べて小さいため、運用によっては利用を検討できる場合があります。たとえば予期しない電源断が生じたマシンは単純に再起動後に復帰させず運用から外して修理に出し、修理から帰ってきたらサーバーを初期化して再セットアップしてから運用に復帰させるような運用ではこの問題を許容できるでしょう。

データフォーマット

データフォーマットは dmsetup の meta_device パラメータ、あるいは integritysetup の --data-device オプションを渡すかどうかで大きく変わります*2

meta_device を指定しない場合は dm-integrity のスーパーブロック、ジャーナルまたはビットマップに続いてデータを含むブロックとチェックサムを含むブロックが交互に続く(インターリーブされる)フォーマットになります。

meta_device を指定した場合にはデータを書き込むデバイスと dm-integrity のスーパーブロックやチェックサムを書き込むデバイスが分離されます。この機能は Linux 4.19 で導入されました。このフォーマットではすでにデータが書き込まれているデバイスに対して dm-integrity の device mapper を重ねてチェックサムを新たに付与することができます*3。また、何らかの事情で dm-integrity が使えなくなった場合にデータデバイスに直接アクセスすることもできます。

どちらの方式のほうが優れているか考えたとき、私の理解ではインターリーブされるフォーマット(meta_device を使わない方式)の利点は思いつきませんでした。meta_device を使わない場合は必要な underlying device が一つだけである一方、meta_device を使う場合は underlying device が二つ必要という点が気になるかもしれません。しかし device mapper を利用する場合には大抵は LVM による論理ボリューム (dm-linear) を利用すると思われるので、それほど問題にならないと考えています。

bitmap mode での処理の流れ

bitmap mode ではデータとチェックサムが確実に一致しているはずであるかどうかを表すビット列をディスク上に永続化しています。ビットマップの1ビットがデータの何セクタ分に相当するかは調整可能で、dmsetup の sectors_per_bit パラメータ、integritysetup コマンドでは --bitmap-sectors-per-bit というオプション*4で制御できます。ただしここで与えた値が必ず使われるわけではなく、ビットマップ領域がディスクに収まらないときにはビットマップ領域のサイズを小さくするために sectors_per_bit を勝手に大きくする調整が入るようです

このビットマップのそれぞれのビットが SET と CLEAR という状態をとります。SET は対応するセクタのディスク上のデータとチェックサムが一致しないかもしれない状態です。これに対して CLEAR はデータとチェックサムが一致しているはずの状態です。電源断が発生したとき、ビットマップが SET になっているセクタでは D (direct write) と同様にデータ破損が発生していなくてもデータとチェックサムが一致しない可能性があり、データ破損が起きたのかどうか定かでありません。一方、ビットマップが CLEAR になっているセクタでデータとチェックサムが一致しなければ確実にデータ破損が起きています。

ビットマップの SET と CLEAR がこのような意味を持つため、bitmap mode ではビットマップの SET をディスク上に FLUSH してからでないとデータやチェックサムを書き換えてはならないといった制約を守りながら書き込みをする必要があります。bitmap mode は journaled mode と比べてオーバーヘッドが小さいとはいえ、一度の書き込みの中で何度か FLUSH を待たなければいけないポイントがあり、ある程度のオーバーヘッドは覚悟する必要があります。逆にビットマップを CLEAR にする処理は多少の遅延が許容されるため dmsetup の bitmap_flush_interval パラメータや integritysetup の --bitmap-flush-time オプションで調整することができます。

使用できるハッシュ関数

チェックサムの計算に利用できるアルゴリズムは dmsetup の internal_hash パラメータや integritysetup の --integrity オプションで指定できます。ここで指定可能なハッシュ関数の一覧や名前のフォーマット("SHA-256" なのか "sha256" なのか)はドキュメントに記載はありませんが、結局のところ渡されたパラメータは crypto_alloc_shash に渡されています。crypto_alloc_shash で取得できるハッシュ関数は crypto_register_shash や crypto_register_shashes で登録されたもののようなので、crypto/ ディレクトリ以下で使いたいハッシュ関数のファイルを探して登録されているかどうかを調べればよさそうでした。md5, sha1, sha256, sha512, sha3-256, xxhash64 などは登録されていました。

チェックサムの計算方法

チェックサムintegrity_sector_checksum という関数で計算されています。要約すると以下のようになります。

crypto_shash_init(req);
crypto_shash_update(req, (const __u8 *)&sector_le, sizeof sector_le);
crypto_shash_update(req, data, ic->sectors_per_block << SECTOR_SHIFT);
crypto_shash_final(req, result);

sector_le は書き込み先のセクタの位置(リトルエンディアン表現)、data は書き込もうとしているデータを指すポインタです。ic->sectors_per_block << SECTOR_SHIFTチェックサム1つに対応するデータの大きさ(バイト換算)で dmsetup するときに block_size というパラメータで指定することができます。したがって、チェックサムの計算には書き込もうとしているデータだけでなくセクタ位置も含まれることが分かります。チェックサムの計算にデータのみを利用した場合はデータの内容の破損は検知することができる一方で、データの内容は合っているが書き込み位置がおかしくなるような場合のデータ破損を検知することができません。セクタ位置をチェックサムに含めることにより、このようなデータ破損を検知することができるようになります。

buffer_sectors とは

dmsetup の buffer_sectors パラメータ、あるいは integritysetup の --buffer-sectors オプションとして謎のパラメータを渡すことができるようになっています。この値をもとに計算される log2_buffer_sectors という変数は dm-integrity のソースコード中でチェックサムの保存先の位置を計算する処理など、さまざまな重要な箇所で登場します。このパラメータは dm_bufio という buffered I/O の仕組みのバッファサイズを指定するもので、dm_bufio_client_create() の block_size というパラメータとして与えられます。このバッファサイズを基準として読み書きを行うために、ディスクレイアウトを決める際には block_size の倍数になるようにする必要があったり、読み書きの際に指定するポジションも block_size を基準に指定しなければならないといった理由があり、ソースコード中のいろいろな箇所でバッファサイズが登場しています。

終わりに

dm-integrity を利用しようとしていた時期があり、一時期ソースコードに踏み込んだ調査をしていたこともあったのですが、途中で没になってしまったので中途半端なところで終わってしまいました。

コードリーディングは処理の流れを追うだけならついていけなくもないのですが、queue_work() を駆使して処理を別スレッドにたらい回しにしている箇所が多数あるため、処理の順番を想像するのが難しかったです。自分でゼロから正しく書けと言われたり、バグを見つけろと言われたら無理です…

*1:Btrfs や ZFSチェックサム機能にも同様の問題があるのではと思ったかもしれませんが、Btrfs や ZFS にはファイルシステム自体に複数のディスクを扱うストレージプールとしての機能があるため、正常なデータが書き込まれているディスクからデータを復元できる可能性があります。

*2:meta device と data device は対になる概念なので、ツールによって指定対象が逆なのがややこしい…

*3:すでにデータが保存されているデバイスに対してチェックサムを追加したいときにはよく検証してから使ってください。integritysetup format --no-wipe してから integritysetup open --integrity-recalculate するのが正しい使い方です。--no-wipe なしで実行するとデータが消えます…

*4:integritysetup コマンドで --bitmap-sectors-per-bit を使うときには罠があります。integritysetup format してから integritysetup open するのが通常の使い方ですが、--bitmap-sectors-per-bit オプションは integritysetup open で設定してください。integritysetup format ではありません。--bitmap-sectors-per-bit で指定した値を journal_watermark に設定したうえで bitmap mode ではなく journaled write で初期化しようとしてしまいます。そして --bitmap-sectors-per-bit に100より大きい値を設定していたときには Invalid argument というエラーが出て失敗します。どうやら integritysetup が journaled write 以外のモードを想定せずに設計されていたところ、あとから bitmap mode に対応させようとした結果としてこのようなことになってしまったようです