# 23.3 UFS 文件系统

UFS（Unix File System）作为传统 UNIX 系统的标准文件系统，在 FreeBSD 中以 UFS2 版本继续发挥重要作用。UFS2 是 UFS 的改进版本，支持更大的文件系统容量、更好的性能和增强的可靠性。本节聚焦于 UFS2 文件系统的磁盘扩容技术，这是系统管理中的常见操作场景。

## UFS 文件系统概述

UFS 全称为 Unix File System（UNIX 文件系统），其起源可追溯至 UNIX v7 版本。历史上，macOS 也曾使用该文件系统作为根文件系统。目前 FreeBSD 采用的是 UFS2 版本，UFS2 相比 UFS1 支持更大的文件和文件系统尺寸，增加了对 64 位指针的支持，并改进了元数据的组织方式。值得注意的是，Linux 对 UFS 的读写支持尚不完整。

需要特别区分的是，此处所述的 UFS 文件系统与手机等设备中使用的 UFS 存储属于完全不同的技术范畴。后者全称为 Universal Flash Storage（通用闪存存储），是一种硬件存储标准，目前已发展至 4.0 版本（FreeBSD 在 10.4 版本中支持 eMMC；而 UFS 存储硬件在 FreeBSD 15.0 的开发计划中，尚未得到支持）。作为文件系统的 UFS，其当前版本号为 2。此外，基于 Linux 的 Android 系统不支持 UFS 文件系统，此类设备的根文件系统通常为 ext4（部分新设备采用 F2FS）。

> **警告**
>
> UFS 文件系统只能扩大，不能缩小。

## 磁盘扩容操作

> **注意**
>
> 此方案仅适用于向后扩展；若 freebsd-ufs 分区前方存在空余空间，则无法使用此方法进行扩展。

首先，使用 `gpart show` 命令显示系统中所有磁盘的分区布局：

```sh
# gpart show
=>       3  41943035  da0  GPT  (20G)
         3       122    1  freebsd-boot  (61K)
       125     66584    2  efi  (33M)
     66709   2097152    3  freebsd-swap  (1.0G)
   2163861  10486633    4  freebsd-ufs  (5.0G)
  12650494  29292544       - free -  (14G)
```

系统盘初始大小为 5 G，输出显示 `da0` 磁盘仅包含此一个 UFS 分区。

### 执行扩容命令序列

> **警告**
>
> 若使用的是 GPT 分区表，此处的扩容操作在虚拟机或云服务器环境中可能会破坏 GPT 分区表，这是因为虚拟机或云平台在调整磁盘大小时可能未正确更新 GPT 分区表的备份副本。因此需首先恢复 `da0` 磁盘的分区表：
>
> ```sh
> # gpart recover da0
> ```
>
> 执行上述操作后，后续步骤保持一致。

调整 da0 磁盘上编号为 4 的 `freebsd-ufs` 分区大小：

```sh
# gpart resize -i 4 da0
da0p4 resized
```

选项 `i` 用于指定要扩容的分区编号，此处指扩展 `freebsd-ufs` 分区。

### 扩展文件系统

使用 growfs 服务扩展文件系统（该操作仅需执行一次，完成后无需重复运行）：

```sh
# service growfs onestart
Growing root partition to fill device
da0 recovering is not needed
da0p4 resized
growfs: no room to allocate last cylinder group; leaving 7.7MB unused
super-block backups (for fsck_ffs -b #) at:
 11544384, 12827072, 14109760, 15392448, 16675136, 17957824, 19240512, 20523200, 21805888, 23088576, 24371264,
 25653952, 26936640, 28219328, 29502016, 30784704, 32067392, 33350080, 34632768, 35915456, 37198144, 38480832
```

growfs 是 FreeBSD 用于扩展 UFS 文件系统的工具，它通过调整文件系统的柱面组和超级块，使文件系统能够利用新增加的分区空间。

### 验证扩容结果

显示已挂载文件系统的磁盘使用情况：

```sh
# df -hl
Filesystem         Size    Used   Avail Capacity  Mounted on
/dev/gpt/rootfs     18G    4.8G     12G    29%    /
devfs              1.0K      0B    1.0K     0%    /dev
/dev/gpt/efiesp     32M    651K     31M     2%    /boot/efi
tmpfs               20M    4.0K     20M     0%    /tmp
tmpfs               32M    156K     32M     0%    /var
```

参数说明：

* `-h`：以人类可读格式显示（单位为 KB、MB、GB 等）
* `-l`：仅显示本地文件系统

上述输出表明，分区扩展操作已完成，且文件系统已成功调整至新的大小。

## 课后习题

1. 在虚拟机环境中模拟 UFS2 分区扩容，先通过 gpart recover 恢复 GPT 分区表，再执行 gpart resize 和 growfs 操作，验证扩容前后的磁盘使用情况变化。
2. 分析 UFS2 文件系统为什么只能扩大而不能缩小，并尝试解决。
3. 对比使用 growfs 服务和手动执行 growfs 命令的差异，尝试不使用 service growfs onestart 而直接调用 growfs，验证其行为变化。
