收缩EXT4文件系统

警告

磁盘分区收缩是高风险操作,非必要不要执行

虽然我的实践是成功的,但是对于 Raspbery Pi OS(Raspbian) 我还是采用 disable_auto_resize ,然后采用手工 在线扩展 EXT4 根文件系统 实现指定容量扩展。这样扩展分区指定大小后无需计算文件系统扩展的大小,并且EXT4文件系统扩展比收缩难度和风险要低,更安全一些。

我在 树莓派(Raspberry Pi)快速起步 实践中发现,当 Raspbery Pi OS(Raspbian) 首次启动时,会自动将原本 dd 创建的启动盘的小分区自动扩展到占用整个磁盘。这在使用SD/TF卡的时候没有什么影响,因为原本SD/TF卡空间就很小,扩展占用整个SD/TF卡正好也满足需求。

但是,我在构建 树莓派4 USB存储启动Ubuntu Server 20.04 方案时,是希望将磁盘的大部分空间用于独立的存储服务,例如构建 ZFS 或者分布式存储 Ceph Atlas ,此时我需要收缩默认占用整个磁盘空间的EXT4文件系统。

备注

EXT4文件系统只支持 在线扩展 EXT4 根文件系统 ,但是不能在线收缩。所以本文采用的是离线方式,也就是 umount 状态下收缩EXT4文件系统。

原理

  • 在离线状态(umount)时,使用 resize2fs 命令可以收缩EXT4文件系统

  • 收缩完EXT4文件系统后,再使用 fdisk 将分区改小(分区结束位置前移)

实践操作

/dev/sda2 分区已扩展到整个磁盘,待收缩
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ssport          
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x527a830f

Device     Boot   Start        End    Sectors  Size Id Type
/dev/sda1          8192    1056767    1048576  512M  c W95 FAT32 (LBA)
/dev/sda2       1056768 1953525167 1952468400  931G 83 Linux
  • 执行 fsck :

/dev/sda2 分区执行 fsck
# 执行 resize2fs 会提示 e2fsck 需要使用 -f 参数
e2fsck -f /dev/sda2
/dev/sda2 分区执行 fsck 的输出信息
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Inode 1403 extent tree (at level 2) could be narrower.  Optimize<y>? yes
Inode 58312 extent tree (at level 2) could be narrower.  Optimize<y>? yes
Inode 58316 extent tree (at level 1) could be narrower.  Optimize<y>? yes
Inode 58383 extent tree (at level 1) could be narrower.  Optimize<y>? yes
Inode 58385 extent tree (at level 1) could be narrower.  Optimize<y>? yes
Inode 58387 extent tree (at level 2) could be narrower.  Optimize<y>? yes
Inode 58389 extent tree (at level 2) could be narrower.  Optimize<y>? yes
Inode 58392 extent tree (at level 2) could be narrower.  Optimize<y>? yes
Inode 58927 extent tree (at level 1) could be narrower.  Optimize<y>? yes
Pass 1E: Optimizing extent trees
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information

rootfs: ***** FILE SYSTEM WAS MODIFIED *****
rootfs: 60775/59592000 files (0.2% non-contiguous), 4195072/244058550 blocks
  • 收缩分区到128G空间:

执行 resize2fs 收缩EXT4文件系统
resize2fs /dev/sda2 128G
执行 resize2fs 收缩EXT4文件系统时输出信息
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/sda2 to 33554432 (4k) blocks.
The filesystem on /dev/sda2 is now 33554432 (4k) blocks long.
  • 按照上述文件系统收缩以后,就可以使用fdisk调整分区大小来匹配已经收缩的文件系统:

收缩前分区
# fdisk /dev/sda

Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ssport          
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x527a830f

Device     Boot   Start        End    Sectors  Size Id Type
/dev/sda1          8192    1056767    1048576  512M  c W95 FAT32 (LBA)
/dev/sda2       1056768 1953525167 1952468400  931G 83 Linux

Command (m for help): 

执行以下操作交互命令(高亮),注意实际输入只有交互中的单个操作命令字符,例如 n 表示添加分区, p 表示打印分区:

收缩分区操作
Command (m for help): d
Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Command (m for help): p
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ssport          
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x527a830f

Device     Boot Start     End Sectors  Size Id Type
/dev/sda1        8192 1056767 1048576  512M  c W95 FAT32 (LBA)

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-1953525167, default 2048): 1056768
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1056768-1953525167, default 1953525167): +268435456

Created a new partition 2 of type 'Linux' and of size 128 GiB.
Partition #2 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: y

The signature will be removed by a write command.

Command (m for help): p
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ssport          
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x527a830f

Device     Boot   Start       End   Sectors  Size Id Type
/dev/sda1          8192   1056767   1048576  512M  c W95 FAT32 (LBA)
/dev/sda2       1056768 269492224 268435457  128G 83 Linux

Filesystem/RAID signature on partition 2 will be wiped.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

备注

这里输入分区的起始扇区是 1056768 ,这个值和调整扇区之前的 /dev/sda2 分区起始位置一致(这样可以避免错位)

输入分区的终止扇区值是 +268435456 ,这个值实际上是之前 resize2fs 结果值 33554432 乘以 8 : 因为 resize2fs 输出结果的值是以 4k 为单位,而 fdisk 操作命令的扇区 sector512字节

  • 如果一切没有出错的话,将调整(shrink)分区挂载进行检查

挂载 /dev/sda2 分区进行检查
mount /dev/sda2 /mnt

此时我遇到一个报错:

挂载 /dev/sda2 分区报错
这里的错误显示是文件系统supperblock错误,或者是其他错误,待补充

怎么办?

  • 执行一次 e2fsck/dev/sda2 进行修复:

/dev/sda2 分区执行 fsck
# 执行 resize2fs 会提示 e2fsck 需要使用 -f 参数
e2fsck -f /dev/sda2

此时会提示大量的 块位图不一致 ( Block bitmap differences ),则按照提示进行 fix 修复

fsck检查 /dev/sda2 分区可以看到大量的 Block bitmap differences ,按提示修复
e2fsck 1.47.0 (5-Feb-2023)
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
Block bitmap differences:  -3731424 -3731426 -(3731428--3731429) -3731431 -3731435 -(3731437--3731442)...
...
Fix<y>? yes
...
Padding at end of inode bitmap is not set. Fix<y>? yes

rootfs: ***** FILE SYSTEM WAS MODIFIED *****
rootfs: 60775/8192000 files (0.2% non-contiguous), 969186/33554432 blocks

修复完成后,再次执行磁盘挂载就能够成功。

参考