ZFS root の再構築でちょっと苦労した

zpool でエラーが出た

ちょっと zpool status してみたらエラーがあるぞと言われ、zpool statux -vx してみということなのでやった結果が以下。 <0xc729>:<0xf1b5> となっているのは、エラーがあるスナップショットを消したらなくならないかと思ってやったけど消えませんねというやつ。

  pool: dim
 state: ONLINE
status: One or more devices has experienced an error resulting in data
    corruption.  Applications may be affected.
action: Restore the file in question if possible.  Otherwise restore the
    entire pool from backup.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A
  scan: scrub repaired 0B in 00:09:05 with 0 errors on Fri Jan 19 04:06:21 2024
config:

    NAME        STATE     READ WRITE CKSUM
    dim         ONLINE       0     0     0
      raidz2-0  ONLINE       0     0     0
        ada0p3  ONLINE       0     0     8
        ada1p3  ONLINE       0     0     8
        ada2p3  ONLINE       0     0     8
        ada3p3  ONLINE       0     0     8

errors: Permanent errors have been detected in the following files:

        dim/ezjail/alphanor@daily-2024-02-17:/usr/local/include/boost/url/grammar/variant_rule.hpp
        <0xc729>:<0xf1b5>
        dim/ezjail/alphanor@daily-2024-02-16:/usr/local/include/boost/url/grammar/variant_rule.hpp
        dim/ezjail/alphanor@daily-2024-02-18:/usr/local/include/boost/url/grammar/variant_rule.hpp

親切にも https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A を読んでみなと言っているので読んでみたところ、

Unfortunately, the data cannot be repaired, and the only choice to repair the data is to restore the pool from backup. Applications attempting to access the corrupted data will get an error (EIO), and data may be permanently lost.

とか言われる。 その下を読んでみるとファイルのデータがおかしいだけなら上書きするだけでよさそうだけれども、どうも最悪のケースぽいので pool を再構築することにした。

データ移行

新しい pool を用意してデータを移すのはわりと楽な話で、 別のPCでバックアップを格納しているガチャベイ を借りてきてHDDを4台突っ込んで zraid2 で pool を作成し、 ZFS のバックアップ - Cugel’s Saga で書いたように取ってあるバックアップからデータを移せば済む。 今回は pool は一応生きているので、壊れていない snapshot を zfs send で転送した。 エラーが出ているファイルシステムだけは、1月頭の snapshot まで2か月弱遡らないと転送できなかったが、 幸いそこはしばらく触っていなかったのでログが少し失われたくらいで済んだ。

起動ではまる

boot しない

さて、新しい pool の作成はそんなに苦労せずに済んだのだが、 この pool の ROOT から起動するのができなくて時間をとってしまった。

bectl

これは私が最近の ZFS root 事情を知らなかったせいで、 いまどきは bectl で起動するファイルシステムを指定する必要があるのであった。 新しい pool は当然 Boot Environment が登録されていないので、 -r オプションで beroot を指定する。-t オプションは「次回起動時より」の指定である。

# bectl -r mar/ROOT activate -t default

FreeBSD で Canon PIXUS TS8630 プリンターを CUPS で使う

世の FreeBSD ユーザーよ

Canon のプリンタ―はやめて EPSON を使おう

CanonLinux で CUPS から印刷できるように Linux 用のソフトウェアを配布している(i386X86_64 と arm と mips64el)。 それは Linux ユーザーには良いことであろう。 しかし、嘆かわしいことに「Linux版のプリンター用ソフトウェアを配布している」ということをもって、 FreeBSD ユーザー向けに Canon のプリンターを薦める向きが存在する。

FreeBSD には Linux エミュレーション機能があるから Linux 用のソフトウェアを使えるし良いじゃないか? EPSON を見よ。エプソンは CUPS 用のフィルタのソースコードを公開していて、FreeBSD native でフィルターをビルドして使えるのである。 USB接続であれば、スキャナーだって SANE 機能を使って使えるのである。 FreeBSD のような弱小 OS のユーザーが応援すべきは、このようにソースコードを公開して使えるようにしてくれている EPSON のような企業である。

何々? Canon だって CUPS 用ソフトウェアの「ソースコード」を公開しているよ?

馬鹿者、その tarball の中身をよく見ろ。 プリンターとのやり取りを行う部分のライブラリがバイナリでしか提供されていないではないか。 結局、FreeBSD native にそのソフトウェアをビルドしては使えないのだ。 そういうのは「ソースコードを公開している」などとは言わない。覚えておくように。

こういうところ、Canon 本体では「環境問題に貢献」とかいってその手の賞を取ったりして、 さもそういうことに気を使っていそうに宣伝しているのに、 関連会社のキヤノングローバル戦略研究所では大々的に温暖化否定論を流布するばかりか、 その流布している人物を政府の委員会に押し込んで政策に影響を与えようとしているという狡い振る舞いをしている企業らしさが現れていると言うべきである。

繰り返すが、FreeBSD ユーザーならプリンターは EPSON を買って使うようにしよう。

まあ、EPSON もスキャナーをネットワーク越しに使うソフトウェアはソースコードを公開していないんだけどね。

しかし、うっかり Canon のプリンターを買ってしまった

私はちゃんと確認しない馬鹿なので、Canon の web でプリンタードライバーの「ソースコード」が配布されているということだけを見て、それならソースに手を入れる必要はあるかもしれないが FreeBSD でも使えるぞと思って Canon PIXUS TS8630 を買ってしまった。まったくけしからんことである。 しかし、買ったからには使いたいので、FreeBSDLinux エミュレーション機能があるのを良いことに、FreeBSD からも印刷できるように設定を行おうと思う。

TS8630 で CUPS から印刷する

プリンターの設定

以下の手順でプリンター前面のパネルから IPP を有効にする。

設定(歯車アイコン)→本体設定→LAN設定→Wi-Fi→詳細設定(右下のボタン)→IPP設定→有効をタッチ

Canon の配布する Linux 版ソフトウェアの入手

CanonHome からサポートのページを介して PIXUS TS8630機種別サポート詳細 ページへ行き、 そこから、ソフトウェアダウンロード→OS選択でLinuxを選択 で、 PIXUS TS8630Linuxソフトウエア選択 のページになる。 FreeBSD ports の提供する Linux 環境は現時点では CentOS 7 ベースなので、 「IJ Printer Driver Ver. 6.50 (rpmパッケージアーカイブ)」を選んでダウンロードする。

ダウンロードした cnijfilter2-6.50-1-rpm.tar.gz を展開すると、packages ディレクトリ内に i386x86_64、aarch64、mips64el それぞれの rpm があるので適したものを使うこと。 他のプラットフォームの方は残念でした。

依存するソフトウェアの導入

FreeBSD版の CUPS のほか、IJ Printer Driver Ver. 6.50 が依存する Linux ライブラリをパッケージから導入する。

# pkg install cups
# pkg install linux_base-c7
# pkg install linux-c7-cups-libs
# pkg install linux-c7-libxml2

/etc/rc.conf に次の行を追加して Linux エミュレーションを有効にする。

linux_enable="YES"

エミュレーションを開始する。

# service linux start

IJ Printer Driver Ver. 6.50 の導入

/compat/linux 以下に rpm を展開し(私の場合は FreeBSD/amd64 を使っているので x86_64 を選択)、 実行ファイルとライブラリに brandelf でラベルをつける。

# cd /compat/linux
# tar xvf /どっか/cnijfilter2-6.50-1.x86_64.rpm
# brandelf -t Linux usr/bin/cnijlgmon3
# brandelf -t Linux usr/bin/tocanonij
# brandelf -t Linux usr/bin/tocnpwg
…
# brandelf -t Linux usr/lib/cups/filter/cmdtocanonij3
# brandelf -t Linux usr/lib/cups/filter/rastertocanonij
…
# brandelf -t Linux usr/lib/libcnbpnet30.so.1.0.0
# brandelf -t Linux usr/lib/libcnnet2.so.1.2.5

brandelf -t Linux を重ね掛けしても問題ないので、面倒なら以下で十分かもしれない。

# brandelf -t Linux /compat/linux/usr/bin/*
# brandelf -t Linux /compat/linux/usr/lib/*
# brandelf -t Linux /compat/linux/usr/lib/cups/backend/*
# brandelf -t Linux /compat/linux/usr/lib/cups/filter/*

次に、FreeBSD 版の CUPS のフィルターフォルダにシンボリックリンクを作成して FreeBSD 版の CUPS から使えるようにする。

# cd /usr/local/libexec/cups/filter
# ln -s /compat/linux/usr/bin/tocanonij tocanonij
# ln -s /compat/linux/usr/bin/tocnpwg tocnpwg
# ln -s /compat/linux/lib/cups/filter/cmdtocanonij3 cmdtocanonij3
# ln -s /compat/linux/lib/cups/filter/rastertocanonij rastertocanonij

CUPS の設定

/etc/rc.conf に cupsd と(お好みで) avahi-daemon の設定を入れて、サービスを開始する。

cupsd_enable="YES"
avahi_daemon_enable="yes"
# service cupsd start
# service avahi-daemon start

localhost:631 で cupsd の管理ページに入れるので、「管理」タブを選択する。 アクセス制限がかかっているが、wheel グループに入っているユーザーのユーザーIDとパスワードで入れる。

「プリンターの追加」を選択し、「発見されたネットワークプリンター」に出ていればそれを、 出ていなければ「インターネット印刷プロトコル (ipps)」を選択し「続ける」を押す。 後者の場合は URL の入力が求められるので、設定してあればホスト名を、なければ IPアドレスを入力する。例えば、

ipps://192.168.0.100/

プリンター名、説明、場所を入力する。プリンター名は -P オプションに指定する名称になる。例えば

  • プリンター名: TS8630
  • 説明: Canon PIXUS TS8630 Series
  • 場所: Cugel の部屋

という感じで。最後に、このPCを経由してほかのPCから印刷したい場合 (ほかの FreeBSD マシンで同じ手間を踏みたくないとか)は、「このプリンターを共有する」をチェックする。

「続ける」で機種を選択する画面になるが、ここでは「または PPDファイルを提供」の「ファイルを選択」を選択し、 /compat/linux/usr/share/cups/model/canonts8630.ppd を選択し、 「プリンターの追加」を押す。

「プリンター TS8630 は正しく追加されました」と出てくればOK。

テスト印刷

% lpr-cups -P TS8630 なんかてきとーなファイル

で印刷されれば成功です。お疲れさまでした。 失敗したら、/usr/local/etc/cups/cupsd.conf でログレベルを LogLevel debug に設定して、 service cupsd restart して、 /var/log/cups/error_log を見ながら解決しましょう。頑張って。

納豆の発泡スチロール容器はリサイクル対象ではない

とあるスーパーにて

先日行ったスーパーの発泡スチロールトレイ回収箱に次のような注意書きがありました。

お願い。洗浄していないトレーや納豆やカップラーメンの容器、きのこのトレーたまごや豆腐、弁当等のプラスティック容器は再利用出来ませんので、当店従業員やトレー回収業者さんが選別してゴミとして捨てております。回収ルールをお守りください。回収できないものは、お持ち帰り下さい。ご協力よろしくお願いいたします。
とあるスーパーの発泡スチロールトレイ回収ボックスの注意書き

少し気になったのは、納豆の容器が回収できないとなっていることです。ほかのものは、色がついていたり、発泡スチロール以外のものと組み合わさった複合材料だったり、そもそも発泡スチロールではなかったりしますが、納豆の容器は白色の発泡スチロールなので、リサイクル対象でもよさそうに思います。

世の中のルールはどうなっているのか

回収拠点

私の家の近くだと発泡スチロールの回収拠点があるのはスーパーと自治体の施設ですが、どちらも「納豆の容器は回収対象外」である旨注意書きがあります。 スーパーの方は、「これこれは回収しない」という注意書きが増えた挙句、ある時から「肉、魚などの販売に使われた白または木目調の発泡スチロールトレイしか回収しない」ということになってしまいました。 自治体の回収拠点には、今度は「食品用トレイしか回収しない」旨の注意書きがあります。家電などの梱包材に使われている発泡スチロールもリサイクルできるならして欲しいですが、残念ながらそういうわけにはいかないようです。

納豆メーカー

タカノフーズのFAQ には、以前は洗ってリサイクルへと書いてあったような気がするのですが、現在は臭いや納豆菌を十分洗い落とすのが難しくリサイクルできない場合があると記述されています。

人々の認識

検索してみると、どう分別すればよいか分からなくてQ&Aサイトなどで聞いている人、 それに対して自分の住む自治体ではリサイクル対象でないと回答している人、 中にはリサイクル対象ではないと書いてあるけど洗ってあればいいと思って出しちゃっているなんて人もいます。

食品用発泡スチロールトレイをリサイクルしている会社に問い合わせてみた

はじめ発泡スチロール協会に問い合わせたのですが、食品用発泡スチロールを扱っている企業の団体ではないということでした。しかし、食品用発泡スチロールのリサイクル大手のエフピコさんなら何か答えられるのではと示唆いただきました。ありがとうございました。

そういうわけで、株式会社エフピコさんに問い合わせたところ、サステナビリティ推進室の方からお答えいただくことができました。ありがとうございました。

エフピコさんからの回答の要約

できるかできないかで言えば洗って十分納豆菌を落としてあればリサイクル自体は可能ですが、現実的には無理なので納豆容器は対象外にしているということです。

つまるところ、「洗ってあればOK」としてしまうと、どうしても「洗っていないもの」「洗い方が不十分なもの」が少なからず混入してくるという問題があって、リサイクルできなくなったり、臭いなどで作業者の不快が大きいため、納豆容器は全面的にリサイクルの対象外とせざるをえないということのようです。

「洗ってあればいいんでしょ」と入れてしまうと、リサイクルのどこかの段階で誰かが手で取り除くことになるので、発泡スチロールの納豆容器は食品用発泡スチロールのリサイクルには出さず、プラスチックごみとして捨てましょう。

続きを読む

mergemaster をやめて etcupdate を使おう

最近はリリースを使って freebsd-update 一本という人も多いとは思いますが、buildworld している人向けの情報です。 2021 年には bug 252417 で mergemaster の削除が提案されています。理由としては、

  1. メンテナがいない
  2. もう開発されていない
  3. svn から git への移行に伴って $FreeBSD$ tag が更新されなくなったのでうまく動かなくなっている可能性が高い

ということで、1、2 はまあ動いていればいいじゃんという話ですが、3 はちょっとよろしくない。 公式には /etc や /boot の更新は etcupdate(8) が推奨されているので、 まだ移行していない人はそちらに移行しましょう。

ただ、使ってはいるけど etcupdate の正しい使い方ってよく分からないのですよね。 特に、一番最初に etcupdate extract すればよいのか etcupdate だけでよいのかよく分からない。 ここでは指針が示せないので、マニュアルを熟読して頑張ってください。

FreeBSD と trim

trimの作法 で紹介されている FreeBSD forum の投稿 によれば、

  • TRIM コマンドはストレージデバイスに対するヒントであって、1Mbytes未満だと無視されることがある
  • TRIM コマンドは non-queueable であって、全ての I/O 要求が処理されてからでないと実行されないし、実行中はほかの I/O 要求が処理できない

という問題があって、ファイルシステムで TRIM 対応を有効にするのは効率がよくないことがある。 nda(4) だと kern.cam.nda.max_trim という sysctl があって、その辺対応されていたりするみたいだけど。

ではどうすればよいかということだけれども、cron とか /etc/periodic.{daily,weekly,monthly} とかを利用して、時々 TRIM をまとめて発行してくれるプログラムを実行するということになる。その場合に実行すべきコマンドは、以下の通りになる。

  • FFS では fsck_ffs -E dev
  • ZFS では zpool trim pool

なお、最初に紹介したスライドに出てくる trim(8) については、

All erased data is lost.

とか書いてあるので、データをまるごと消してしまうよう。気をつけて。

PostgreSQL のデータベースのロジカルレプリケーションを設定する

FreeBSD に PowerDNS をインストールする で権威DNSサーバーの primary の設定をしたわけですが、PowerDNS の設定としては Native で、secondary への反映はデータベースのレプリケーションで行う必要があります。その設定を行っていきます。

primary 側の設定

/var/db/postgres/data14/postgresql.conf でレプリケーションの設定をロジカルに変更するとともに、ほかのホストから接続できるようにします。

listen_address = '*'
wal_level = logical

/var/db/postgres/data14/pg_hba.conf に secondary 側から SSL で接続できるように設定します。

hostssl    pdns    all    2001:0db8:0:0:3456:3456:3456:3456/128    trust

postgresql server の再起動が必要です。

# service postgresql restart

postgres role でデータベースに接続して、pdns role に REPLICATION 権限を設定します。

$ psql -U postgres -d pdns
pdns=# ALTER ROLE pdns REPLICATION;

次に、pdns role で pdns データベースのテーブルに対して PUBLICATION を設定します。 下の2つは PUBLICATION が設定されていることの確認です。

$ psql -U pdns -d pdns
pdns=> CREATE PUBLICATION pdns FOR TABLE comments, cryptokeys, domainmetadata, domains, records, supermasters, tsigkeys;
pdns=> SELECT * FROM pg_publication;
pdns=> SELECT * FROM pg_publication_tables;

secondary 側の設定

先程のページの「PostgreSQLの設定」の項にある、 roleの作成、データベースの作成、スキーマの適用までは同じことを順に行います。

次からは primary と異なるところですが、pdns データベースに対して postgres role で SUBSCRIPTION を設定します。

$ psql -U postgres -p pdns
pdns=# CREATE SUBSCRIPTION pdns CONNECTION 'host=2001:0db8:0:0:1234:1234:1234:1234 port=5432 dbname=pdns sslmode=require' PUBLICATION pdns;

補足

SSL 関連の設定については述べませんが、このあたりを参照してください。

動作確認

FreeBSD に PowerDNSAdmin をインストールする で設定した PowerDNS Admin で primary 側でレコードを設定し、secondary サーバーで引けるかどうか確認します。

$ drill host.example.jp @2001:0db8:0:0:3456:3456:3456:3456

vnet jail に関してちょっと気になる話

FreeBSD forum に "Huge downgrade in iperf3 speed when a jail is active" というちょっと気になる話が出ていた。

Promox VMFreeBSD を動かしていて、Promox host との間の通信速度を iperf3 で測定すると、jail を立ち上げていない場合は 24Gbit/s 出るのに、vnet jail を立ち上げると 4Gbit/s くらいに落ちてしまうのだという。

10Gのネットワークを組んでいたりする人にはちょっと気になる話かもしれない。