如果文件系统使用完全镜像的 Vinum 配置, 有时也会希望根文件系统也作了镜像。 这种配置要比镜像其它文件系统麻烦一些, 因为:
根文件系统在引导过程中很早的时候就必须处于可用状态, 因此 Vinum 的基础设施在这一时刻就应该可用了。
包含根文件系统的卷, 同时也保存了系统的引导程序和内核, 因此它们必须能够被宿主系统的内建工具 (例如 PC 机的 BIOS) 识别, 而通常是没办法让它们了解 Vinum 的细节的。
下面几节中, 术语 “根卷” 标识包含根文件系统的 Vinum 卷。 把这个卷命名为 "root" 可能是个不错的主意, 不过从技术上说, 并不严格地要求这样做。 不过, 接下来的命令例子都使用这个名字。
有许多关于它的尺度:
Vinum 必须在启动时可以被内核使用。 因此, 在 第 19.8.1.1 节 中所介绍的方法, 也就无法适应这一任务的需要了。 在接下来的配置中, 也 不能 设置 start_vinum 参数。 第一种方法是通过将 Vinum 静态联编到内核中来实现, 这样, 它就在任何时候都可用了, 虽然一般并不需要这样。 另一种方法是通过 /boot/loader (第 12.3.3 节) 来尽早加载 vinum 内核模块, 这一操作发生在内核加载之前。 这可以通过将下面的配置:
geom_vinum_load="YES"
加入到 /boot/loader.conf 文件中来实现。
注意: 对 Gvinum 而言, 所有的启动过程都是在内核模块加载时自动进行的, 因此上面的操作, 也就是所要进行的全部工作了。 下面的文字介绍的是旧式的 Vinum 系统, 保留它们的主要是为了方便那些使用旧版系统的用户。
Vinum 必须尽早初始化, 因为需要由它来提供根文件系统的卷。 默认情况下, Vinum 的内核部分并不主动地查找可能包含 Vinum 卷信息的驱动器, 而会等待管理员 (或者某个启动脚本) 来执行 vinum start 命令。
注意: 下面介绍的是 FreeBSD 5.X 和更高版本所需的配置。 对于 FreeBSD 4.X 的配置方法与此不同, 在 第 19.9.5 节 中有所描述。
通过将下面的配置:
vinum.autostart="YES"
加入 /boot/loader.conf, Vinum 将在内核部分初始化的过程中, 自动地扫描所有的驱动器以查找 Vinum 信息。
需要说明的是, 并不需要指定内核到什么地方去找根文件系统。 /boot/loader 会在 /etc/fstab 中查找根文件系统的设备名, 并将这一信息转交给内核。 当需要挂接根文件系统时, 内核会根据设备名来知道它由哪个驱动提供, 并将其转译为内部设备 ID (major/minor 编号)。
因为目前的 FreeBSD 引导程序只有 7.5 KB 的代码, 并且已经承担了从 UFS 文件系统中读取文件 (例如 /boot/loader) 的重任, 因此完全没有办法再让它去分析 Vinum 配置数据中的 Vinum 结构, 并找到引导卷本身的信息。 因此, 需要一些技巧来为引导代码提供标准的 "a" 分区, 而它则包含了根文件系统。
要让这些得以实现, 根卷需要满足下面的条件:
根卷不能是条带卷或 RAID-5 卷。
根卷 plex 不能包含连接的子盘。
需要说明的是, 使用多个 plex, 每个 plex 都复制一份根文件系统的副本, 是需要而且是可行的。 然而, 引导过程只能使用这些副本中的一个来引导系统, 直到内核最终自行挂接根文件系统为止。 这些 plex 中的每个子盘, 在这之后会有它们自己的 "a" 分区, 以表达每一个可以引导的设备。 每一个 "a" 分区, 尽管并不需要和其它包含根卷的 plex 处于各自驱动器的同一位置。 但是, 这样创建 Vinum 卷使得镜像卷相互对称, 从而能够避免了混淆。
为了创建每一个根卷的 "a" 分区, 需要完成下面的操作:
使用下面的命令来了解根卷成员子盘的位置 (从设备开始的偏移量) 和尺寸:
# gvinum l -rv root
需要注意的是, Vinum 偏移量和尺寸的单位是字节。 它们必须是 512 的整数倍, 才能得到 bsdlabel 命令所需的块号。
在每一个根卷成员设备上, 执行命令:
# bsdlabel -e devname
这其中, 对于没有 slice (也就是 fdisk) 表的磁盘, devname 必须是磁盘的名字 (例如 da0), 或者是 slice 的名字 (例如 ad0s1)。
如果设备上已经有了 "a" 分区 (比如说, 包含 Vinum 之前的根文件系统), 则应改为其它的名字, 以便继续访问 (如果需要的话), 但它并不会继续用于启动系统。 注意, 活动的分区 (类似正挂接的根文件系统) 不能被改名, 因此, 要完成这项工作, 必须从 “Fixit” 盘启动, 或者分两步操作, 并 (在镜像情形中) 首先操作那些非引导盘。
然后, 设备上 Vinum 分区的偏移 (如果有的话) 必须加到这个设备上根卷对应的子盘上。 其结果值, 将成为新的 "a" 分区的 "offset" 值。 这个分区的 "size" 值, 可以根据前面的配置计算得出。 "fstype" 应该是 4.2BSD。 "fsize"、 "bsize", 以及 "cpg" 值, 则应与文件系统的实际情况匹配, 尽管在配置 Vinum 时并不重要。
这样, 新的 "a" 分区, 将创建并覆盖这一设备上的 Vinum 分区的范围。 注意, bsdlabel 只有在 Vinum 分区的 fstype 被标记为 "vinum" 时, 才允许这样做。
这就成了! 所有的 "a" 分区现在都已存在, 而且是根卷的一份副本。 强烈建议您再次验证其结果, 方法是:
# fsck -n /dev/devnamea
务必注意, 所有包含控制信息的文件, 都必须放到 Vinum 卷上的根文件系统。 在启动新的 Vinum 根卷时, 它们可能和实际在用的根文件系统不匹配。 因此, /etc/fstab 和 /boot/loader.conf 这两个文件需要特别地注意。
在下次重启时, 引导程序需要从新的基于 Vinum 的根文件系统中获取适当的控制信息, 并据此工作。 在内核初始化过程的结尾部分, 在所有的设备都被宣示之后, 如果显示了下面的信息, 则表示配置成功:
Mounting root from ufs:/dev/gvinum/root
在 Vinum 根卷配置好之后, gvinum l -rv root 的输出可能类似下面的样子:
... Subdisk root.p0.s0: Size: 125829120 bytes (120 MB) State: up Plex root.p0 at offset 0 (0 B) Drive disk0 (/dev/da0h) at offset 135680 (132 kB) Subdisk root.p1.s0: Size: 125829120 bytes (120 MB) State: up Plex root.p1 at offset 0 (0 B) Drive disk1 (/dev/da1h) at offset 135680 (132 kB)
需要注意的值是 135680, 也就是偏移量 (相对于 /dev/da0h 分区)。 这相当于 bsdlabel 记法中的 265 个 512-字节的磁盘块。 类似地, 根卷的尺寸是 245760 个 512-字节的磁盘块。 /dev/da1h 中, 包含了根卷的第二个副本, 采用了同样的配置。
这些设备的 bsdlabel 类似下面的样子:
... 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 245760 281 4.2BSD 2048 16384 0 # (Cyl. 0*- 15*) c: 71771688 0 unused 0 0 # (Cyl. 0 - 4467*) h: 71771672 16 vinum # (Cyl. 0*- 4467*)
可以看到, 伪装的 "a" 分区的 "size" 参数和前面的一样, 而 "offset" 参数则是 Vinum 分区 "h", 以及设备中这一分区 (或 slice) 的偏移量之和。 这是一种典型的配置, 它能够避免在 第 19.9.4.3 节 中介绍的问题。 此外, 我们也看到整个 "a" 分区完全处于设备上包含了 Vinum 数据的 "h" 分区之中。
注意, 在上面的配置中, 整个设备都是 Vinum 专用的, 而且没有留下 Vinum 之前的根分区, 因为它永久性地成为了新建的 Vinum 配置中的一个子盘。
如果遇到了问题, 则需要从中恢复的办法。 下面列出了一些常见的缺陷, 及其解决方法。
如果由于某种原因系统不再继续启动, 引导程序可以在 10-秒 倒计时的时候, 按 space 键来停止。 加载器变量 (例如 vinum.autostart) 可以通过使用 show 命令来查看, 并使用 set 和 unset 命令来设置。
如果遇到的问题是由于 Vinum 的内核模块没有列入预加载的列表, 而没有正确加载, 则简单使用 load geom_vinum 会有所帮助。
此后, 可以使用 boot -as 来继续启动过程。 选项 -as
会要求内核询问所挂接的根文件系统 (-a
), 并使引导过程在单用户模式停止 (-s
), 此时根文件系统是以只读方式挂接的。 这样, 即使只挂接了多 plex
卷中的一个 plex, 也不会引致 plex 之间数据不一致的问题。
当提示输入要挂接的根文件系统时, 可以输入任何一个包含根文件系统的设备。 如果正确地配置了 /etc/fstab, 则默认的应该是类似 ufs:/dev/gvinum/root。 一般可以使用类似 ufs:da0d 这样的设备来代替它, 因为它通常包括了 Vinum 之前的根文件系统。 需要注意的是, 如果在这里输入了 "a" 分区, 则它可能表达的实际上是 Vinum 根设备的一个子盘, 而在镜像式配置中, 这只会挂接镜像的根设备中的一个。 如果之后将这个文件系统以读写方式挂接, 则需要从 Vinum 根卷中删去其他的 plex, 否则这些卷中可能会包含不一致的数据。
如果 /boot/loader 加载失败, 而主引导程序加载正常 (在启动时, 屏幕最左边一列有一个旋转的线), 则可以尝试在此时中断主引导程序的过程, 方法是按 space 键。 这将在引导的第二阶段暂停, 具体可以参见 第 12.3.2 节。 此时, 可以尝试从另一个分区, 例如原先包含根文件系统, 并不再叫作 "a" 的那个分区, 启动。
这种情况一般是由于 Vinum 安装过程中破坏了引导程序造成的。 不幸的是, Vinum 目前只在分区开始的地方保留了 4 KB 的空间, 之后就开始写 Vinum 头信息了。 然而, 目前第一阶段和第二阶段的引导程序, 加上 bsdlabel 嵌入的内容则需要 8 KB。 因此, 如果 Vinum 分区从偏移量 0 开始, 而这个 slice 或磁盘能够启动, 则 Vinum 的安装将毁掉引导程序。
类似地, 如果从上述情形中恢复, 例如, 从 “Fixit” 盘启动, 并通过 bsdlabel -B 按照 第 12.3.2 节 中介绍的方法来恢复引导程序, 则引导程序会覆盖掉 Vinum 头, 这样 Vinum 也就找不到它的磁盘了。 尽管这并不会真的毁掉 Vinum 的配置数据, 或者 Vinum 卷上的数据, 并且可以通过输入一模一样的 Vinum 配置数据来恢复, 但从这种状况中完全恢复是非常困难的。 要真正解决问题, 必须将整个 Vinum 分区向后移动至少 4 KB, 以便使 Vinum 头和系统的引导程序不再冲突。
在 FreeBSD 4.X 中, 由于缺少那些让 Vinum 自动扫描所有磁盘所需的内部函数, 而检测根设备的内部 ID 的代码不够智能, 以至于无法自动处理类似 /dev/vinum/root 这样的名字。 因此, 会有一些小差异。
必须明确地告诉 Vinum 要扫描哪些磁盘, 方法是在 /boot/loader.conf 中加入:
vinum.drives="/dev/da0 /dev/da1"
所有可能包含 Vinum 数据的盘在这里都应提及。 基本原则是, 宁多毋缺。 此外, 也无需明确指定 slice 或分区, 因为 Vinum 在指定的驱动器上的所有 slice 和分区上扫描 Vinum 头。
由于用以分析根文件系统名字, 并产生设备 ID (major/minor 编号) 的程序, 只能够处理 “传统的” 类似 /dev/ad0s1a 这样的设备名, 因此它们不可能处理类似 /dev/vinum/root 这样的根卷名。 因此, Vinum 本身需要预先配置内核的一些内部参数, 以便在初始化时能够保持根设备的 ID。 这可以通过加载器变量 vinum.root 来配置, 对应的 /boot/loader.conf 设置是:
vinum.root="root"
现在, 当内核初始化过程尝试找到要挂接的 root 设备时, 它将能看到是否已经有某个内核模块预先初始化了所需要的内核参数。 这种情况下, 并且 所指定的根设备和来自加载器的根设备 (也就是我们的 "vinum" ) 的 major 编号相符, 则就是用预先分配的设备 ID, 而不是自己去找一个。 这样, 在通常的自动启动过程中, 它就能够继续挂接 Vinum 根卷来作为根文件系统了。
但是, 当指定了 boot -a 来要求在启动时手工选择根设备时, 仍然是无法自动地分析 Vinum 卷名的。 如果输入的设备名与 Vinum 设备不匹配, 则 major 编号的不匹配会使这个过程采用普通的分析过程, 这样, 输入 ufs:da0d 就能够正常工作了。 注意, 一旦这个过程失败, 则再输入 ufs:vinum/root 将不能正常工作, 因为它无法再被解析了。 唯一的解决办法是, 重新启动并从头开始 (在 “askroot” 提示处, 可以省略 /dev/。)
本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<[email protected]>.
关于本文档的问题请发信联系 <[email protected]>.