ディスクイメージファイルを拡張する

KVM仮想マシンのディスクイメージを raw format で作成して運用していたんだけど、容量が不足してきたので拡張しようとしたら色々と厄介だったので備忘録代わりに手順をメモっておく。

前提

  • ディスクイメージは raw format。
  • ディスクは /boot + LVM という構成。

大まかな手順

  1. ファイルサイズを増やす
  2. パーティションを切り直す
  3. LVM の Physical Volume をリサイズ
  4. LVM の Logical Volume をリサイズ
  5. ファイルシステムをリサイズ
  6. 後始末

手順

ファイルサイズを増やす

増やしたいサイズの分(今回は 10GB)のゼロデータを後ろに追加する。(ddseek= を使わなかったのは、sparse ファイルにしたくなかったから)

 # dd if=/dev/zero bs=1M count=$((10 * 1024)) >> disk.img
パーティションを切り直す

これが厄介だった。
まず、parted で resize しようとしたら "Error: Could not detect file system." と言われて怒られた。どうやら parted は LVM を完全にサポートしている訳ではないらしい。
仕方なく fdisk/sfdisk/cfdisk コマンドを色々いじった結果、sfdisk を以下のような手順で使えばうまくいくことが分かった。
まず、ディスクの CHS 情報(シリンダ、ヘッド、セクタ数)をメモる。

 $ sudo sfdisk -l disk.img 
Disk disk.img: cannot get geometry

Disk disk.img: 2610 cylinders, 255 heads, 63 sectors/track
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
disk.img1          0+     15      16-    128488+  83  Linux
disk.img2         16    1304    1289   10353892+  8e  Linux LVM
disk.img3          0       -       0          0    0  Empty
disk.img4          0       -       0          0    0  Empty

今回の場合は (2610, 255, 63) だったので、どこかにメモしておく。
次に、パーティション情報を dump して保存する。

 $ sudo sfdisk -d disk.img > partitions.dump
 $ cat partitions.dump 
# partition table of disk.img
unit: sectors

disk.img1 : start=       63, size=   256977, Id=83
disk.img2 : start=   257040, size= 20707785, Id=8e
disk.img3 : start=        0, size=        0, Id= 0
disk.img4 : start=        0, size=        0, Id= 0

dump したファイルを編集し、一番最後のパーティションの size を増やす。値は (セクタ数 - スタート位置) で求まる。セクタ数は先ほどメモった「シリンダ数 × ヘッド数 × トラックあたりセクタ数」から計算する。(今回の場合は 2610 * 255 * 63 - 257040 = 41672610)

 $ cat partitions.dump
# partition table of disk.img
unit: sectors

disk.img1 : start=       63, size=   256977, Id=83
disk.img2 : start=   257040, size= 41672610, Id=8e
disk.img3 : start=        0, size=        0, Id= 0
disk.img4 : start=        0, size=        0, Id= 0

で、編集した内容をディスクに反映させる。

 $ sudo sfdisk disk.img < partitions.dump 
Warning: disk.img is not a block device
Disk disk.img: cannot get geometry

Disk disk.img: 2610 cylinders, 255 heads, 63 sectors/track
Old situation:
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
disk.img1          0+     15      16-    128488+  83  Linux
disk.img2         16    1304    1289   10353892+  8e  Linux LVM
disk.img3          0       -       0          0    0  Empty
disk.img4          0       -       0          0    0  Empty
New situation:
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
disk.img1            63    257039     256977  83  Linux
disk.img2        257040  41929649   41672610  8e  Linux LVM
disk.img3             0         -          0   0  Empty
disk.img4             0         -          0   0  Empty
Warning: no primary partition is marked bootable (active)
This does not matter for LILO, but the DOS MBR will not boot this disk.
Successfully wrote the new partition table

Re-reading the partition table ...
BLKRRPART: Inappropriate ioctl for device

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

Warning が出てるけど、"Successfully wrote the new partition table" と出ているので成功しているはず。念のため、変更が反映されていることを確認する。

 $ sudo sfdisk -d disk.img 
# partition table of disk.img
unit: sectors

disk.img1 : start=       63, size=   256977, Id=83
disk.img2 : start=   257040, size= 41672610, Id=8e
disk.img3 : start=        0, size=        0, Id= 0
disk.img4 : start=        0, size=        0, Id= 0

大丈夫そうだ。

Physical Volume をリサイズする

loop device を設定し、各パーティションを見えるようにする。(losetup + kpartx)

 $ sudo losetup /dev/loop0 disk.img
 $ sudo kpartx -a /dev/loop0
 $ ls -l /dev/mapper/loop0*
lrwxrwxrwx 1 root root 7 Oct  8 04:01 /dev/mapper/loop0p1 -> ../dm-0
lrwxrwxrwx 1 root root 7 Oct  8 04:01 /dev/mapper/loop0p2 -> ../dm-1

そして pvresize を実行。

 $ sudo pvscan 
  PV /dev/dm-1   VG host01   lvm2 [9.87 GiB / 892.00 MiB free]
  Total: 1 [9.87 GiB] / in use: 1 [9.87 GiB] / in no VG: 0 [0   ]

 $ sudo pvresize /dev/dm-1 
  Physical volume "/dev/dm-1" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized

 $ sudo pvscan            
  PV /dev/dm-1   VG host01   lvm2 [19.87 GiB / 10.87 GiB free]
  Total: 1 [19.87 GiB] / in use: 1 [19.87 GiB] / in no VG: 0 [0   ]

PV の容量が増えた!

Logical Volume をリサイズする

まず Volume Group が存在することを確認する。

 $ sudo vgscan 
  Reading all physical volumes.  This may take a while...
  Found volume group "host01" using metadata type lvm2

"host01" という Volume Group が今回のターゲットなので、空き容量を確認する。

 $ sudo vgdisplay host01
  --- Volume group ---
  VG Name               host01
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               19.87 GiB
  PE Size               4.00 MiB
  Total PE              5086
  Alloc PE / Size       2304 / 9.00 GiB
  Free  PE / Size       2782 / 10.87 GiB
  VG UUID               Hxg0Yg-X0zs-U1p2-8PhR-4QVH-s1F1-O7m62X
   

先ほど増やした 10GB 分がまるまる空いていることが確認できたので、この Volume Group を active にする。

 $ sudo vgchange -a y host01
  2 logical volume(s) in volume group "host01" now active

Logical Volume の存在を確認する。

 $ sudo lvscan 
  ACTIVE            '/dev/host01/root' [8.00 GiB] inherit
  ACTIVE            '/dev/host01/swap' [1.00 GiB] inherit

今回は /dev/host01/root を増やすことにする。

 $ sudo lvresize -L +10G /dev/host01/root 
  Extending logical volume root to 18.00 GiB
  Logical volume root successfully resized

Logical Volume の容量が増えた!!

ファイルシステムをリサイズする

いつものやつ。(e2fsck + resize2fs)

 $ sudo e2fsck -f /dev/host01/root
e2fsck 1.41.12 (17-May-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/host01/root: 10242/524288 files (1.1% non-contiguous), 703204/2097152 blocks

 $ sudo resize2fs /dev/host01/root 
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/host01/root to 4718592 (4k) blocks.
The filesystem on /dev/host01/root is now 4718592 blocks long.

確認のために /dev/host01/root を mount してみた方が良さそうだけど、ここでは省略。

後始末

Volume Group を inactive にして、

 $ sudo vgchange -a n host01
  0 logical volume(s) in volume group "host01" now active

loop device の後始末をして、

 $ sudo kpartx -d /dev/loop0 
 $ sudo losetup -d /dev/loop0

完了!!!

感想

ディスクパーティションまわりは、CHS とかのレガシーな概念が残っていたり、ツールがいまいち洗練されてなかったりでなかなか面倒くさい。