Xilinx の FPGA ボードではYocto Linux をベースにしたPetaLinuxが採用されています。このLinuxを使用するためにはRaspberry Piと同じようにSDカードにイメージを書き込んで、そのSDカードを基板に挿して使用します。
このイメージは2つのパーティションからなります。1つ目はFATでフォーマットされたブートローダなどが格納されるパーティションで、もう1つはext4でフォーマットされたルートファイルシステムのパーティションです。これは下記のマクニカ社のサイトの説明がわかりやすいです。
通常利用するときには、ルートファイルシステムはSDカードの容量を最大限まで使えるようにしておけば良いですが、SDカードのイメージをまるごとバックアップしようとした場合に、使用していない領域までバックアップを取るのは時間がかかってしまいます。
そこで今回は未使用領域部分を削減してルートファイルシステムのパーティションのサイズを小さくします。また、小さくしたあとで最大サイズに戻す方法も説明します。
試してはいませんがおそらくRaspberry Piでも同じ手順で行けると思います。
イメージの容量を削減する
まずPetaLinuxのイメージサイズを削減する方法を説明します。
ホストマシンでSDカードを認識させる
動作している基板上でパーティションサイズを小さくさせることはできないので、別のマシンにて作業します。ここではUbuntu22.04を使用します。Linuxならたいてい使えると思います。
今回の例では下記のように/dev/sdbがSDカードに割り当てられました。
パーティション sdb1 はFATのブートローダなど、sdb2 はext4のルートファイルシステムです。64GBのSDカードで最大限までルートファイルシステムのパーティションを広げている状態です。
$ sudo fdisk -l (略) デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ /dev/sdb1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/sdb2 4194312 124735487 120541176 57.5G 83 Linux
現状のパーティション情報を確認する
sdb2がPetaLinuxのルートファイルシステムだとわかったので、次にファイルシステムの最小サイズを調べます。コマンドresize2fsに大文字のPをオプションとして渡せば最小サイズを表示してくれます。ここで注意ですが、表示されるのはByte数でなくブロック数です。下記の例では3199265ブロックとなります。
$ umount /dev/sdb2 $ sudo resize2fs -P /dev/sdb2 resize2fs 1.46.5 (30-Dec-2021) Estimated minimum size of the filesystem: 3199265
ブロックサイズは下記のコマンドで確認できます。4KBですね。
$ sudo /sbin/tune2fs -l /dev/sdb2 | grep 'Block size' Block size: 4096
パーティションションサイズを小さくする
まずはじめにファイルシステムのチェックから行います。これを先に実行しないとパーティション変更時にコマンドがはじかれます。
$ sudo e2fsck -p -f /dev/sdb2
先程調べたブロック数とブロックサイズは3199264 × 4KBで、これはおよそ12.5GBなので、ここでは少し大きめの13GBにしておきます。サイズ変更のオプションは小文字のpです。
$ sudo resize2fs -p /dev/sdb2 13G
これでファイルシステムを13GBに縮小できました。
パーティションサイズの縮小
ファイルシステムは縮小できましたが、まだ肝心のパーティションを縮小していません。パーティション縮小にはfdiskを使います。対話的コマンドです。
まず最初にFAT側のパーティションもアンマウントします(こっちは変更しません)。
$ umount /dev/sdb2
いよいよパーティションを修正します。対話的コマンドなので、入力するところで「★」をつけて説明を入れておきます。
やることはext4パーティションを一旦削除して、再度作り直してパーティションサイズを再設定することです。このときパーティションサイズは、さっきおこなったファイルシステムのサイズ変更で指定したサイズより大きくする必要があります(パーティションサイズ>ファイルシステムサイズにする)。ここでは13GBより大きい14GBにしています。
$ sudo fdisk /dev/sdb fdisk (util-linux 2.37.2) へようこそ。 ここで設定した内容は、書き込みコマンドを実行するまでメモリのみに保持されます。 書き込みコマンドを使用する際は、注意して実行してください。 コマンド (m でヘルプ): m ★ ヘルプを表示 ヘルプ: DOS (MBR) a 起動可能フラグを切り替えます b 入れ子の BSD ディスクラベルを編集します c DOS 互換フラグを切り替えます 一般 d パーティションを削除します F パーティションのない領域を一覧表示します l 既知のパーティションタイプを一覧表示します n 新しいパーティションを追加します p パーティション情報を表示します t パーティションタイプを変更します v パーティション情報を検証します i パーティションの情報を表示します その他 m このメニューを表示します u 表示項目の単位を変更します x 特殊機能に移動します (熟練者向け機能) スクリプト I ディスクのレイアウトを sfdisk 互換のスクリプトから読み込みます O ディスクのレイアウトを sfdisk 互換のスクリプトに書き出します 保存と終了 w パーティション情報をディスクに書き込んで終了します q 変更点を保存せずに終了します 新しいラベルを作成します g 新しい (何もない) GPT パーティションテーブルを作成します G 新しい (何もない) SGI (IRIX) パーティションテーブルを作成します o 新しい (何もない) DOS パーティションテーブルを作成します s 新しい (何もない) Sun パーティションテーブルを作成します コマンド (m でヘルプ): p ★ いまのパーティション情報を確認。sdb2の開始位置を覚えておくこと! ディスク /dev/sdb: 59.48 GiB, 63864569856 バイト, 124735488 セクタ Disk model: SD/MMC 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0x07e7b6bb デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ /dev/sdb1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/sdb2 4194312 124735487 120541176 57.5G 83 Linux コマンド (m でヘルプ): d ★パーティション削除 パーティション番号 (1,2, 既定値 2): 2 ★間違ってFATのほうの1を消さないように。 パーティション 2 を削除しました。 コマンド (m でヘルプ): p ★ extのほうのパーティションが消えているか確認する ディスク /dev/sdb: 59.48 GiB, 63864569856 バイト, 124735488 セクタ Disk model: SD/MMC 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0x07e7b6bb デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ /dev/sdb1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) コマンド (m でヘルプ): n ★ 消したパーティションを再作成 パーティションタイプ p 基本パーティション (1 primary, 0 extended, 3 free) e 拡張領域 (論理パーティションが入ります) 選択 (既定値 p): p ★ プライマリでOK パーティション番号 (2-4, 既定値 2): 2 ★ 消した方のパーティション番号を指定 最初のセクタ (4194312-124735487, 既定値 4196352): 4194312 ★さっき控えておいた開始位置を入力する Last sector, +/-sectors or +/-size{K,M,G,T,P} (4194312-124735487, 既定値 124735487): +14G ★プラスに続けて確保したいサイズを入力する 新しいパーティション 2 をタイプ Linux、サイズ 14 GiB で作成しました。 パーティション #2 には ext4 署名が書き込まれています。 署名を削除しますか? [Y]es/[N]o: N ★変更する必要ないのでNoにする コマンド (m でヘルプ): w ★ このw入力したら初めて変更が反映される、言い換えればここでwを入力しなければ何も変更されない パーティション情報が変更されました。 ioctl() を呼び出してパーティション情報を再読み込みします。 ディスクを同期しています。
これでパーティションサイズを14GBに減らせました。
動作確認
パーティションサイズの確認
念の為実機でパーティション情報を確認しておきます。さきほどのSDカードを基板に挿してLinuxを起動させます。そして基板上で df でファイルシステムを確認します、期待通り13GBだけ見えています。
$ df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 1.5G 4.0K 1.5G 1% /dev /dev/mmcblk1p2 13G 12G 690M 95% / tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 787M 18M 769M 3% /run tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup tmpfs 2.0G 0 2.0G 0% /tmp tmpfs 2.0G 204K 2.0G 1% /var/volatile /dev/mmcblk1p1 2.0G 44M 2.0G 3% /boot tmpfs 394M 0 394M 0% /run/user/0
つぎにパーティション情報を書くにします。期待通り14GBになっていますね。
$ sudo disk -l 略 Disk /dev/mmcblk1: 59.48 GiB, 63864569856 bytes, 124735488 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x07e7b6bb Device Boot Start End Sectors Size Id Type /dev/mmcblk1p1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/mmcblk1p2 4194312 33554431 29360120 14G 83 Linux
パーティションサイズ削減したイメージのバックアップ
SDカードのLinuxイメージをバックアップするときは下記のようにddコマンドで抽出します。
$ sudo dd if=/dev/sdb of=petalinux.bin bs=1M status=progress
しかしこれだとSDカード全体を読み込むので、サイズ削減した意味がないです。どこまで読み込むかを指定する必要があります。
どこまで読み込めばいいかは、fdisk の情報から計算できます。下記のように表示された場合、データの末尾は 29360120セクターです。
$ sudo fdisk -l 略 ディスク /dev/sdb: 59.48 GiB, 63864569856 バイト, 124735488 セクタ Disk model: SD/MMC 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 0x07e7b6bb デバイス 起動 開始位置 最後から セクタ サイズ Id タイプ /dev/sdb1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/sdb2 4194312 33554431 29360120 14G 83 Linux
1セクタは512Byteなので、
29,360,120 * 512 = 15,032,381,440 Byte ≒ 14,336 MByte
です。
dd の bs オプションに 1MBを指定しているので結局この場合は下記のように指定すればOKです。
$ sudo dd if=/dev/sdb of=petalinux-14GB.bin bs=1M count=14336 status=progress
ループバックデバイスにマウントして確認
上記で取得したバックアップイメージの確認をしておきましょう。一番確実なのはSDカードにイメージを書き込んで起動させてみることです。
SDカードに書くときはcount入らないですね、ファイルサイズ末尾まで書き込めばいいので。
$ sudo dd of=/dev/sdb if=petalinux-14GB.bin bs=1M status=progress
ただこれは結構時間がかかるかと思うので、別の方法でやってみます。
ループバックデバイスにマウントしてみるのが手っ取り早いかと思います。ループバックデバイスを使うことで下記のようにイメージファイルをそのままマウントできます。
オプションにloopをつけ、offsetオプションにパーティションの開始位置を指定します。マウントできたらルートファイルシステムの中のファイルが見れるはずです。
$ sudo mkdir /media/shinya/petalinux-14GB/ $ sudo mount -o loop,offset=$((512 * 4194312)) ./petalinux-14GB.bin /media/shinya/petalinux-14GB/ $ ls /media/shinya/petalinux-14GB/ bin boot configfs dev etc home lib lost+found media mnt proc run sbin srv sys tmp usr var
パーティションサイズを大きくする
さきほどはパーティションサイズを小さくしましたが、実際に基板を動かすときはパーティションサイズをSDカード容量いっぱいまで大きくしたいこともあるかと思います。
パーティションを大きくするには、小さくすときと違って、基板上のLinuxでそのまま実行できます。
Zilinx は resize-part というコマンド(シェルスクリプト)を用意してくれているのでそれを使えば一発です。fdiskでデバイスファイルを確認して、それを引数に渡すだけです。これでSDカード上限までサイズが拡大されます。
# fdisk -l 略 Disk /dev/mmcblk1: 59.48 GiB, 63864569856 bytes, 124735488 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x07e7b6bb Device Boot Start End Sectors Size Id Type /dev/mmcblk1p1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/mmcblk1p2 4194312 33554431 29360120 14G 83 Linux # resize-part /dev/mmcblk1p2 # reboot
もし resize-part がなければ手動で下記のように実行すればOKです。
$ sudo bash -c 'echo -e "Yes" | parted /dev/mmcblk1 ---pretend-input-tty resizepart 2 100%' Warning: Partition /dev/mmcblk1p2 is being used. Are you sure you want to continue? Yes/No? Yes Information: You may need to update /etc/fstab. $ sudo resize2fs /dev/mmcblk1p2 $ reboot
再起動後に下記のようにパーティションとファイルシステムサイズが最大化されているはずです。
$ sudo fdisk -l 略 Disk /dev/mmcblk1: 59.48 GiB, 63864569856 bytes, 124735488 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x07e7b6bb Device Boot Start End Sectors Size Id Type /dev/mmcblk1p1 * 8 4194311 4194304 2G c W95 FAT32 (LBA) /dev/mmcblk1p2 4194312 124735487 120541176 57.5G 83 Linux $ df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 1.5G 4.0K 1.5G 1% /dev /dev/mmcblk1p2 57G 13G 42G 24% / tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 787M 10M 777M 2% /run tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup tmpfs 2.0G 0 2.0G 0% /tmp tmpfs 2.0G 200K 2.0G 1% /var/volatile /dev/mmcblk1p1 2.0G 44M 2.0G 3% /boot tmpfs 394M 0 394M 0% /run/user/0
まとめ
今回はPetaLinuxのSDカード内のイメージのサイズを削減する方法を説明しました。また、動作確認を簡単にするためループバックマウントの方法も説明しました。さらに、パーティションサイズを最大解する方法も説明しました。
SDカードをまるっとバックアップするのは結構時間がかかるので、これらの方法を利用してみてください。
コメント