# 21.7.为磁盘设备添加卷标

在系统初始化期间，FreeBSD 内核会随着设备的发现而创建设备节点。这种设备探测方法会引发一些问题。例如，如果通过 USB 添加了一个新的磁盘设备，可能会导致一个闪存设备被分配为 **da0**，而原来的 **da0** 被重新分配为 **da1**。如果文件系统已经列在 **/etc/fstab** 中，这将导致挂载问题，甚至可能会阻止系统启动。

一种解决方案是按顺序链接 SCSI 设备，这样添加到 SCSI 卡上的新设备将被分配未使用的设备号。但对于可能替代主 SCSI 磁盘的 USB 设备呢？这种情况发生是因为 USB 设备通常在 SCSI 卡之前进行探测。一个解决办法是仅在系统启动后插入这些设备。另一种方法是仅使用一个 ATA 硬盘，并且永远不要在 **/etc/fstab** 中列出 SCSI 设备。

一个更好的解决方案是使用 `glabel` 为磁盘设备打标签，并在 **/etc/fstab** 中使用标签。由于 `glabel` 将标签存储在给定提供者的最后一个扇区中，因此标签在重启后会保持持久。通过使用此标签作为设备，可以确保无论通过哪个设备节点访问，文件系统始终可以挂载。

> **注意**
>
> `glabel` 可以创建临时和永久标签。只有永久标签在重启后是一致的。有关标签之间差异的更多信息，请参阅 [glabel(8)](https://man.freebsd.org/cgi/man.cgi?query=glabel\&sektion=8\&format=html)。

## 21.7.1. 标签类型与示例

永久标签可以是通用标签或文件系统标签。永久文件系统标签可以使用 [tunefs(8)](https://man.freebsd.org/cgi/man.cgi?query=tunefs\&sektion=8\&format=html) 或 [newfs(8)](https://man.freebsd.org/cgi/man.cgi?query=newfs\&sektion=8\&format=html) 创建。这些类型的标签会在 **/dev** 的子目录中创建，并根据文件系统类型命名。例如，UFS2 文件系统标签将在 **/dev/ufs** 中创建。通用永久标签可以使用 `glabel label` 创建。这些标签不特定于文件系统，会在 **/dev/label** 中创建。

临时标签会在下次重启时销毁。这些标签创建在 **/dev/label** 中，适合实验用途。可以使用 `glabel create` 创建临时标签。

要为 UFS2 文件系统创建永久标签而不销毁任何数据，请执行以下命令：

```sh
# tunefs -L home /dev/da3
```

此时应在 **/dev/ufs** 中创建一个标签，可以将其添加到 **/etc/fstab** 中：

```sh
/dev/ufs/home		/home            ufs     rw              2      2
```

> **注意**
>
> 在运行 `tunefs` 时，文件系统不能被挂载。

现在，可以挂载该文件系统：

```sh
# mount /home
```

从此以后，只要 **geom\_label.ko** 内核模块在启动时加载（通过 **/boot/loader.conf** 或启用 `GEOM_LABEL` 内核选项），设备节点的变化不会对系统产生不良影响。

文件系统也可以通过在创建文件系统时使用 `newfs` 命令的 `-L` 选项来创建默认标签。有关更多信息，请参阅 [newfs(8)](https://man.freebsd.org/cgi/man.cgi?query=newfs\&sektion=8\&format=html)。

以下命令可以用于销毁标签：

```sh
# glabel destroy home
```

以下示例展示了如何标记引导磁盘的分区。

**示例 1. 标记引导磁盘上的分区**

通过永久标记引导磁盘上的分区，即使磁盘被移动到其他控制器或转移到不同的系统，系统仍应能够继续正常启动。此示例假设使用的是单个 ATA 硬盘，并且该硬盘目前被系统识别为 **ad0**。还假设使用的是标准 FreeBSD 分区方案，其中包括 **/**、**/var**、**/usr** 和 **/tmp**，以及一个交换分区。

重启系统，在 [loader(8)](https://man.freebsd.org/cgi/man.cgi?query=loader\&sektion=8\&format=html) 提示符下，按 4 进入单用户模式。然后输入以下命令：

```sh
# glabel label rootfs /dev/ad0s1a
GEOM_LABEL: Label for provider /dev/ad0s1a is label/rootfs
# glabel label var /dev/ad0s1d
GEOM_LABEL: Label for provider /dev/ad0s1d is label/var
# glabel label usr /dev/ad0s1f
GEOM_LABEL: Label for provider /dev/ad0s1f is label/usr
# glabel label tmp /dev/ad0s1e
GEOM_LABEL: Label for provider /dev/ad0s1e is label/tmp
# glabel label swap /dev/ad0s1b
GEOM_LABEL: Label for provider /dev/ad0s1b is label/swap
# exit
```

系统将继续进入多用户模式启动。启动完成后，编辑 **/etc/fstab**，将常规设备名称替换为其各自的标签。最终的 **/etc/fstab** 文件将如下所示：

```sh
# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/label/swap         none            swap    sw              0       0
/dev/label/rootfs       /               ufs     rw              1       1
/dev/label/tmp          /tmp            ufs     rw              2       2
/dev/label/usr          /usr            ufs     rw              2       2
/dev/label/var          /var            ufs     rw              2       2
```

现在可以重新启动系统。如果一切顺利，系统将正常启动，`mount` 命令将显示：

```sh
# mount
/dev/label/rootfs on / (ufs, local)
devfs on /dev (devfs, local)
/dev/label/tmp on /tmp (ufs, local, soft-updates)
/dev/label/usr on /usr (ufs, local, soft-updates)
/dev/label/var on /var (ufs, local, soft-updates)
```

[glabel(8)](https://man.freebsd.org/cgi/man.cgi?query=glabel\&sektion=8\&format=html) 类支持基于文件系统唯一标识符（`ufsid`）的 UFS 文件系统标签。这些标签可以在 **/dev/ufsid** 中找到，并在系统启动时自动创建。可以使用 `ufsid` 标签通过 **/etc/fstab** 挂载分区。使用 `glabel status` 获取文件系统及其对应的 `ufsid` 标签列表：

```sh
% glabel status
                  Name  Status  Components
ufsid/486b6fc38d330916     N/A  ad4s1d
ufsid/486b6fc16926168e     N/A  ad4s1f
```

在上述示例中，**ad4s1d** 代表 **/var**，而 **ad4s1f** 代表 **/usr**。使用显示的 `ufsid` 值，可以使用以下条目在 **/etc/fstab** 中挂载这些分区：

```sh
/dev/ufsid/486b6fc38d330916        /var        ufs        rw        2      2
/dev/ufsid/486b6fc16926168e        /usr        ufs        rw        2      2
```

所有带有 `ufsid` 标签的分区都可以以这种方式挂载，从而消除了手动创建永久标签的需要，同时仍享受设备名称独立挂载的好处。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/hanbook/di-21-zhang-geom-mo-kuai-hua-ci-pan-zhuan-huan-kuang-jia/21.7.-wei-ci-pan-she-bei-tian-jia-juan-biao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
