背景
有一块 256GB 的硬盘,其上为 CentOS 操作系统以及数据,想全盘克隆至另一块 250GB 的硬盘上,由于目标盘容量不够,因此需要想办法。
在 Windows 下使用 DiskGenius 6.0 和 Acronic True Image 2017 执行克隆硬盘的任务都失败。联想到各自在界面中对分区状态的展示,推测失败原因似乎都与 XFS 文件系统相关。
在网络上搜索,遭到了 https://www.cnblogs.com/Jas0n0ss/p/16142457.html 这个实践,因此决定以它为主要参考教程,来实施缩小 XFS 分区的任务。
过程
到 Ubuntu 下,apt install xpsdump 后,参照前述教程亦步亦趋。
把源盘使用 USB 易驱线连接到电脑上,先看概况:
|
1 2 3 4 5 6 7 8 9 10 |
dandy@dandy-t450s-ubuntu:~$ df -Th Filesystem Type Size Used Avail Use% Mounted on tmpfs tmpfs 2.0G 2.5M 2.0G 1% /run /dev/sdc2 ext4 228G 118G 100G 55% / tmpfs tmpfs 9.8G 0 9.8G 0% /dev/shm tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs tmpfs 9.8G 216K 9.8G 1% /run/qemu /dev/sdc1 vfat 511M 15M 497M 3% /boot/efi tmpfs tmpfs 2.0G 1.7M 2.0G 1% /run/user/1000 /dev/sdd5 xfs 226G 88G 139G 39% /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 |
其中的 sdd5 即是欲调整的分区。接下来先备份整个分区的所有文件,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
dandy@dandy-t450s-ubuntu:~$ sudo xfsdump -f ~/centos.xfsdump /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 xfsdump: using file dump (drive_simple) strategy xfsdump: version 3.1.9 (dump format 3.0) - type ^C for status and control ============================= dump label dialog ============================== please enter label for this dump session (timeout in 300 sec) -> dump-centos session label entered: "dump-centos" --------------------------------- end dialog --------------------------------- xfsdump: level 0 dump of dandy-t450s-ubuntu:/media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 xfsdump: dump date: Fri Sep 26 21:23:57 2025 xfsdump: session id: dd3e04bc-50ed-42e1-80f0-4dfd31fa64b7 xfsdump: session label: "dump-centos" xfsdump: ino map phase 1: constructing initial dump list xfsdump: ino map phase 2: skipping (no pruning necessary) xfsdump: ino map phase 3: skipping (only one dump stream) xfsdump: ino map construction complete xfsdump: estimated dump size: 93745352000 bytes xfsdump: /var/lib/xfsdump/inventory created ============================= media label dialog ============================= please enter label for media in drive 0 (timeout in 300 sec) -> centos media label entered: "centos" --------------------------------- end dialog --------------------------------- xfsdump: creating dump session media file 0 (media 0, file 0) xfsdump: dumping ino map xfsdump: dumping directories xfsdump: dumping non-directory files xfsdump: ending media file xfsdump: media file size 93274618464 bytes xfsdump: dump size (non-dir files) : 93110991456 bytes xfsdump: dump complete: 1271 seconds elapsed xfsdump: Dump Summary: xfsdump: stream 0 /home/dandy/centos.xfsdump OK (success) xfsdump: Dump Status: SUCCESS |
查看备份,并确认源分区无人使用后卸下,
|
1 2 3 4 |
dandy@dandy-t450s-ubuntu:~$ ll -h ~/centos.xfsdump -rw-r--r-- 1 root root 87G 9月 26 21:44 /home/dandy/centos.xfsdump dandy@dandy-t450s-ubuntu:~$ fuser -km /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 dandy@dandy-t450s-ubuntu:~$ umount /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 |
接下来则与教程不同,因为源盘未启用逻辑卷管理。尝试使用 Disks 工具直接缩小 XFS 文件系统不可行,毕竟该文件系统原则上只能扩大。
那只好自行尝试现将 XFS 文件系统清除,再新创建一个小一点的。打开 GParted 工具,将 XFS 分区上的文件系统标记为 cleared,再用 Disks 把该分区的大小减小了 3GB。这样操作(即非要调整分区大小而非在扩展分区里将该子分区删除后再创建)是想看看能不能保住 UUID,结论是不行。
现在要重新创建 XFS 文件系统了,
|
1 2 3 4 5 6 7 8 9 10 11 12 |
dandy@dandy-t450s-ubuntu:~$ sudo mkfs.xfs /dev/sdd5 -f Swipe your right index finger across the fingerprint reader meta-data=/dev/sdd5 isize=512 agcount=4, agsize=14648448 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=0 inobtcount=0 data = bsize=4096 blocks=58593792, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=28610, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 |
在 Disks 里能看到 UUID 变了,想把它改回去(之前熟悉的 tune2fs -U {uuid} /dev/XXX 不行,因为那是用于 ext 文件系统的),
|
1 2 3 4 5 6 7 8 |
dandy@dandy-t450s-ubuntu:~$ sudo tune2fs -U 2c130885-88e9-4779-bc9b-52cac8b15605 /dev/sdd5 tune2fs 1.46.5 (30-Dec-2021) tune2fs: Bad magic number in super-block while trying to open /dev/sdd5 /dev/sdd5 contains a xfs file system dandy@dandy-t450s-ubuntu:~$ sudo xfs_admin -U 2c130885-88e9-4779-bc9b-52cac8b15605 /dev/sdd5 Clearing log and setting UUID writing all SBs new UUID = 2c130885-88e9-4779-bc9b-52cac8b15605 |
到 Disks 里一看,已经生效,直接把它 mount 上,现在就该恢复备份的文件了,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
dandy@dandy-t450s-ubuntu:~$ sudo xfsrestore -f ~/centos.xfsdump /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 xfsrestore: using file dump (drive_simple) strategy xfsrestore: version 3.1.9 (dump format 3.0) - type ^C for status and control xfsrestore: searching media for dump xfsrestore: examining media file 0 xfsrestore: dump description: xfsrestore: hostname: dandy-t450s-ubuntu xfsrestore: mount point: /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 xfsrestore: volume: /dev/sdd5 xfsrestore: session time: Fri Sep 26 21:23:57 2025 xfsrestore: level: 0 xfsrestore: session label: "dump-centos" xfsrestore: media label: "centos" xfsrestore: file system id: 2c130885-88e9-4779-bc9b-52cac8b15605 xfsrestore: session id: dd3e04bc-50ed-42e1-80f0-4dfd31fa64b7 xfsrestore: media id: cac5291e-94f5-4f9f-ba4c-6d6b7a07d9ad xfsrestore: using online session inventory xfsrestore: searching media for directory dump xfsrestore: reading directories xfsrestore: 180135 directories and 447251 entries processed xfsrestore: directory post-processing xfsrestore: restoring non-directory files xfsrestore: restore complete: 389 seconds elapsed xfsrestore: Restore Summary: xfsrestore: stream 0 /home/dandy/centos.xfsdump OK (success) xfsrestore: Restore Status: SUCCESS |
查看一下,
|
1 2 3 4 5 6 7 8 9 10 |
dandy@dandy-t450s-ubuntu:~$ df -Th Filesystem Type Size Used Avail Use% Mounted on tmpfs tmpfs 2.0G 2.5M 2.0G 1% /run /dev/sdc2 ext4 228G 204G 13G 95% / tmpfs tmpfs 9.8G 0 9.8G 0% /dev/shm tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs tmpfs 9.8G 216K 9.8G 1% /run/qemu /dev/sdc1 vfat 511M 15M 497M 3% /boot/efi tmpfs tmpfs 2.0G 1.7M 2.0G 1% /run/user/1000 /dev/sdd5 xfs 224G 89G 135G 40% /media/dandy/2c130885-88e9-4779-bc9b-52cac8b15605 |
看上去是成了。到 Disks 里,把 XFS 文件系统所处的扩展分区缩到了最小。这样,整个源盘上的所有分区就都处于目标盘的容量范围内了。
用 USB 易驱线把目标盘也接上,dd 两个磁盘顺利完成。
转过天来检查成果。把源盘插回原来的电脑上启动 CentOS,可以正常登录进入系统,但是却出现了一个提示:XFS (sda1): Superblock has unknown read-only compatible features (0x4) enabled. 一检查,果然,整个 / 根分区是以只读方式 mount 起来的。还换用克隆出的目标盘也启动了一把,问题一毛一样。这样可以放下一样心:至少不是克隆的问题。瞬间感觉到昨天还是小看了 XFS,竟然不知道在哪里偷偷摸摸就给藏了雷。
又经过一番资料检索,大致有了个约摸:大概率是 Ubuntu 下操作 XFS 的工具链包括驱动等,版本与 CentOS 自带的有出入,所以制作的文件系统存在兼容性上的问题。0x4 似乎是对应于一个叫做 Reflink 的特性,而且这个特性相当特:它在文件系统创建时一旦指定,之后的存续期间就无法修改。
昨天操作这两块盘的 Ubuntu 不在手边,这两块盘虽然都能正常启动,却都是只读的 / 分区。如何是好?一开始想到 /tmp 目录通常是 tmpfs,应该可以供 mount point 存身,但在其中 mkdir 时失败了。AI 提示了一句,说可以试试 /run 目录,一试还真行。于是开启了源盘和目标盘两兄弟穷帮穷的互助之旅。
要做的事是一样的,只不过你帮我做一遍,反过来我再帮你做一遍。这些事情有:
- 本盘正常启动 CentOS,登录进入;
- 把另一块盘接到电脑上,对其上的 / 分区强行重建 XFS 文件系统(其实也就是格式化):
mkfs.xfs -f /dev/sdb5;这两块盘是孪生兄弟,因此 XFS 相关物料和工具之间不会存在版本差异; mount /dev/sdb5 /run/destroot(这个 mount point 的目录名字随意,提前建好);- 把本盘 / 下的所有内容复制过去(跳过系统仅运行时使用到的目录):
rsync -a --exclude=/dev --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/run --exclude=/sys --exclude=/tmp --progress -v / /run/destroot; - 到 /run/destroot 下,手动创建上一步特意略过的几个目录:
mkdir dev media mnt proc run sys tmp;并设置正确的访问权限:chmod 555 proc sys,以及chmod 777 tmp;如果缺少这几个目录,系统会无法成功引导(别问是如何得知的); umount /run/destroot;- 这里有个问题,这两块盘是 dd 克隆出来的,各个分区的 UUID 都一样,而上面的步骤 2 重新创建文件系统时,UUID 会发生改变。两种办法,要么去把 fstab 中的 UUID 改成新的,要么像我一样,为了维持面上的 dd 原貌,恢复旧有的 UUID(可以用 blkid 查看引导盘的根分区得到),然后使用
xfs_admin -U ${uuid} /dev/sdb5这样的命令恢复;
两遍处理过后,源盘和备份盘均恢复正常,至此功成。
