PetaLinux のイメージサイズ削減&パーティションサイズ最大化

この記事は約17分で読めます。

Xilinx の FPGA ボードではYocto Linux をベースにしたPetaLinuxが採用されています。このLinuxを使用するためにはRaspberry Piと同じようにSDカードにイメージを書き込んで、そのSDカードを基板に挿して使用します。

このイメージは2つのパーティションからなります。1つ目はFATでフォーマットされたブートローダなどが格納されるパーティションで、もう1つはext4でフォーマットされたルートファイルシステムのパーティションです。これは下記のマクニカ社のサイトの説明がわかりやすいです。

Just a moment...

通常利用するときには、ルートファイルシステムは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カードをまるっとバックアップするのは結構時間がかかるので、これらの方法を利用してみてください。

コメント