amd64 の FreeBSD 12.x の kernel は ifunc が必要2018年09月18日 11時39分15秒

FreeBSD 12.0-RELEASE も近付いてきている。ALPHA-6 に入り、既にテストを行なっている人、そこそろ試してみようかという人などがいるとは思う。11 系からの更新は幾つかの注意点がある。

まずは、ifunc。11 系から上げる人は、buildkernel 時に、CURRENT を追っていて、11 系のシステムに上書きインストールする人は installkernel 時に見掛けると思う。私は、NFS mount 越しの installkernel 時に出てきた。

$ uname -r
11.2-RELEASE-p2
$ mount -t nfs amd64-current:/usr/src /usr/src
$ mount -t nfs amd64-current:/usr/obj /usr/obj
$ make installkernel -C /usr/src
make[2]: "/usr/src/sys/conf/kern.pre.mk" line 126: amd64 kernel requires linker ifunc support
さて /usr/src/sys/conf/kern.pre.mk を覗いてみると、
.if (${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386") && \
    defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mifunc} == ""
.error amd64/i386 kernel requires linker ifunc support
.endif
.if ${MACHINE_CPUARCH} == "amd64"
LDFLAGS+=       -Wl,-z max-page-size=2097152 -Wl,-z common-page-size=4096 -Wl,-z -Wl,ifunc-noplt
.endif
の部分がこれに当たる。

コードを見るより、/usr/src/UPDATING を開く。

20180510:
        The amd64 kernel now requires a ld that supports ifunc to produce a
        working kernel, either lld or a newer binutils. lld is built by default
        on amd64, and the 'buildkernel' target uses it automatically. However,
        it is not the default linker, so building the kernel the traditional
        way requires LD=ld.lld on the command line (or LD=/usr/local/bin/ld for
        binutils port/package). lld will soon be default, and this requirement
        will go away.
該当部分を発見
$ make installkernel LD=ld.lld -C /usr/src
今度は問題なく installkernel が進んだ。

zfs の 簡単な分割は zfs create と mv2018年09月17日 13時29分10秒

先日に zfs を分割するのに zfs snapshot と zfs clone を使ったが、単純な方法であれば、zfs create で新しいファイルシステムを作り、mv ファイルを動かしても大丈夫な事に気がついた。

mv で動かしてしまうと、間違えた時に mv で戻すと、スナップショットとは別の複製が出来るのでディスクが追加で消費される。しかし、最終的には古いスナップショットは全部消すのが目的なので、mv の方が楽かも知れない。

zfs clone と zfs send で非ミラーファイルシステムを分割2018年09月15日 16時48分38秒

ZFS のファイルシステムを分割したかったのだが、zfs 自体には分割の機能は無い。zpool だと、ミラー型のプールは分割出来るが、こちらはプール単位になってしまい、全てのファイルシステムが複製される。

今回、分割したいと思った理由はバックアップ先の zpool の容量が足りなくなったから。バックアップをとらなくても何とかなるファイルを複製するのを止めたかったのだが、ファイルシステムに混ざっていたので単純な削除では無理だからだ。

zfs clone はファイルシステムを複製する機能だ。これは snapshot を作成し、そこからの差分を元にファイルシステムを利用する機能。これを使えば、元のファイルシステムを複数に分割して使うことが出来る。しかし、元のスナップショットがバックアップを止めたいファイルを保持したままになるので今回の意図には沿わない。

そこで、今回 zfs snapshot と zfs clone で一時的にファイルシステムを複製。そこから対象外のファイルを削除した後に、zfs send と zfs receive で全く別のファイルシステムとして作ることにした。

今回の例として、BSD 関連のファイルをダウンロードしてあった download/BSD ファイルシステムを各々に分けて download/FreeBSD と download/NetBSD の zfs ファイルシステムにする。

$ zfs list -t all
NAME           USED  AVAIL  REFER  MOUNTPOINT
download       421M   411M    23K  /mnt/download
download/BSD   421M   411M   421M  /mnt/download/B
$ ls /mnt/download/ZFS/*
BSD:
FreeBSD NetBSD

FreeBSD:
FreeBSD-11.2-RELEASE-i386.vmdk.xz

NetBSD:
netbsd-8.0-i386-boot-com.iso
実験用に小さめのプールを準備して、各々に一つずつファイルを置いた。
$ zfs snapshot download/BSD@today
$ zfs clone download/BSD@today download/freebsd
$ rm -rf /mnt/download/freebsd/NetBSD
$ zfs snapshot download/freebsd@only
$ zfs send download/freebsd@only | zfs receive download/FreeBSD@only
BSD ファイルシステムから snapshot と clone で freebsd とし、そこから NetBSD を削除。zfs send と receive で元の BSD ファイルシステムとの関係を切断する。

zfs send と receive で一つ目のファイルシステムを処理し終えた状態。

$ zfs list -t all
NAME                    USED  AVAIL  REFER  MOUNTPOINT
download                640M   192M    23K  /mnt/download
download/BSD            421M   192M   421M  /mnt/download/BSD
download/freebsd         13K   192M   219M  /mnt/download/freebsd
download/freebsd@only      0      -   219M  -
download/FreeBSD        219M   192M   219M  /mnt/download/FreeBSD
download/FreeBSD@only      0      -   219M  -

NetBSD の方は BSD ファイルシステムの名前の変更した後に、FreeBSD を消す。

$ zfs destroy download/BSD@today
$ zfs rename download/BSD download/NetBSD
$ rm -rf /mnt/download/NetBSD/FreeBSD
$ zfs list -t all
NAME                    USED  AVAIL  REFER  MOUNTPOINT
download                422M   409M    23K  /mnt/download
download/FreeBSD        219M   409M   219M  /mnt/download/FreeBSD
download/FreeBSD@only    13K      -   219M  -
download/NetBSD         202M   409M   202M  /mnt/download/NetBSD
これで download/BSD を download/FreeBSD と download/NetBSD に分割できた。

もっと手間の掛かるファイルの選別が必要なら clone と promote を用いて、もっと安全に操作することも出来る。NetBSD のファイルの選別も独立したファイルシステム上で行なって、最終確認が終った後に。古い BSD ファイルシステムを削除する手順にすれば、間違ってファイルを消してもやり直しが効く。

SQLite : DROP TABLE IF EXIST でテーブルが無い時のエラーを無視する2018年08月24日 22時25分17秒

CREATE TABLE の同じテーブル名が存在した時のエラーを無視出来る様に、DROP TABLE のテーブルの有無のエラーを抑制出来る。
DROP TABLE IF EXISTS テーブル名;

DROP TABLE の場合は、CREATE TABLE の場合と違って、エラーを無視した時には副作用は無い。

% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> DROP TABLE IF EXISTS integers;
sqlite> .exit

SQLite データベース - Top

DROP TABLE を存在しないテーブルに行なった時の SQLite のエラー2018年08月23日 13時45分54秒

DROP TABLE は作成されたテーブルを削除するコマンド。DROP TABLE を存在しないテーブルに行なうとエラーになる。
% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> DROP TABLE integers;
Error: no such table: integers
sqlite> .exit

SQLite データベース - Top

CREATE TABLE IF NOT EXIST で同じ名前のテーブルがある時のエラーを無視する2018年08月22日 11時56分24秒

CREATE TABLE を二回行なうとエラーになる。 CREATE TABLE 同じ名前のテーブルは作れない。CREATE TABLE に IF NOT EXISTS を付けると、このエラーを無視することが出来る。
CREATE TABLE IF NOT EXISTS テーブル名 ( コラム名 [、コラム名…] );

しかし、ただ単にエラーを無視しただけなので、違うコラムで CREATE TABLE を行なっても、元のテーブルのまま。

% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE integers ( number INTEGER );
sqlite> CREATE TABLE IF NOT EXISTS integers ( number1 INTEGER, number2 INTEGER );
sqlite> .schema integers
CREATE TABLE integers ( number INTEGER );
sqlite> .exit

本稼働のシステムで日常的に使うには、疑問のある IF NOT EXISTS だが、やっつけ仕事のテスト環境や実験での使い勝手は良い。

SQLite データベース - Top

CREATE TABLE を二回行なった時の SQLite のエラー2018年08月21日 13時54分37秒

CREATE TABLE で SQLite のテーブルが作れる。しかし、CREATE TABLE を二回行なうとエラーになる。同じ名前のテーブルは作れない。
% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE integers ( number INTEGER );
sqlite> CREATE TABLE integers ( number INTEGER );
Error: table integers already exists
sqlite> .exit

SQLite データベース - Top

SQLite : DROP TABLE でテーブルを削除2018年08月20日 03時55分16秒

CREATE TABLE で作成されたテーブルは DROP TABLE で消すことが出来る。
DROP TABLE テーブル名

テーブルを二つ作成する。

% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE table1 ( number INTEGER );
sqlite> CREATE TABLE table2 ( number INTEGER );
sqlite> .tables
table1  table2
そのうちの一つを DROP TABLE で削除。
sqlite> DROP TABLE table1;
sqlite> .tables
table2
sqlite> 
DROP TABLE はテーブル名を一つしか取らないので、複数のテーブルを削除するには複数回 DROP TABLE をする必要がある。

また、テーブルのデータはテーブルと共に全て失われる。

SQLite データベース - Top

CREATE TABLE で SQLite でもしっかりデータ型を指定してテーブルを作成2018年08月18日 13時27分24秒

SQLite では入力型が動的判定されるので、型の指定も省略出来てしまうが、そうすると他のデータベースとの互換性が下がる 。
CREATE TABLE テーブル名 ( コラム名 データ型 [、コラム名 データ型…] );

前回と同じく整数を羅列するテーブルを作成してみる。

% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE integers ( number INTEGER );
sqlite> INSERT INTO integers VALUES ( 1 ), (3), (2 );
sqlite> SELECT * FROM integers;
1
3
2
sqlite> .exit

SQLite データベース - Top

CREATE TABLE で SQLite の一番単純なテーブルを作成2018年08月17日 15時08分13秒

データベースでは CREATE TABLE でテーブルを作成する。データベースを使う上でのまず第一歩。SQLite では入力型が動的判定されるので、型の指定も省略出来てしまう。
CREATE TABLE テーブル名 ( コラム名 [、コラム名…] );

整数を羅列するテーブルを作成してみる。

% sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> CREATE TABLE integers ( number );
作成しただけでは、何があるのか見えないので、幾つかレコードを挿入して、表示をしてみる。
sqlite> INSERT INTO integers VALUES ( 1 ), (3), (2 );
sqlite> SELECT * FROM integers;
1
3
2
sqlite> .exit

SQLite データベース - Top