Tom Rhodes 原作 GEOM: 模块化磁盘变换框架 概述 GEOM GEOM 磁盘框架 GEOM 本章将介绍以 &os; GEOM 框架来使用磁盘。 这包括了使用这一框架来配置的主要的 RAID 控制工具。 这一章不会深入讨论 GEOM 如何处理或控制 I/O、 其下层的子系统或代码。 您可以从 &man.geom.4; 联机手册及其众多 SEE ALSO 参考文献中得到这些信息。 这一章也不是对 RAID 配置的权威介绍, 它只介绍由 支持GEOM 的 RAID 级别。 读完这章, 您将了解: 通过 GEOM 支持的 RAID 类型。 如何使用基本工具来配置和管理不同的 RAID 级别。 如何通过 GEOM 使用镜像、 条带、 加密和挂接在远程的磁盘设备。 如何排除挂接在 GEOM 框架上的磁盘设备的问题。 阅读这章之前, 您应: 理解 &os; 如何处理磁盘设备 ()。 了解如何配置和安装新的 &os; 内核 ()。 GEOM 介绍 GEOM 允许访问和控制类 (classes) — 主引导记录、 BSD 标签 (label), 等等 — 通过使用 provider, 或在 /dev 中的特殊文件。 它支持许多软件 RAID 配置, GEOM 能够向操作系统, 以及在其上运行的工具提供透明的访问方式。 Tom Rhodes 原作 Murray Stokely RAID0 - 条带 GEOM 条带 条带是一种将多个磁盘驱动器合并为一个卷的方法。 许多情况下, 这是通过硬件控制器来完成的。 GEOM 磁盘子系统提供了 RAID0 的软件支持, 它也成为磁盘条带。 RAID0 系统中, 数据被分为多个块, 这些块将分别写入阵列的所有磁盘。 与先前需要等待系统将 256k 数据写到一块磁盘上不同, RAID0 系统, 能够同时分别将打碎的 64k 写到四块磁盘上, 从而提供更好的 I/O 性能。 这一性能提升还能够通过使用多个磁盘控制器来进一步改进。 RAID0 条带中的每一个盘的尺寸必须一样, 因为 I/O 请求是分散到多个盘上的, 以便让这些盘上的读写并行完成。 磁盘条带图 在未格式化的 ATA 磁盘上建立条带 加载 geom_stripe 模块: &prompt.root; kldload geom_stripe 确信存在合适的挂接点 (mount point)。 如果这个卷将成为根分区, 那么暂时把它挂接到其他位置i, 如 /mnt &prompt.root; mkdir /mnt 确定将被做成条带卷的磁盘的设备名, 并创建新的条带设备。 举例而言, 要将两个未用的、 尚未分区的 ATA 磁盘 /dev/ad2/dev/ad3 做成一个条带设备: &prompt.root; gstripe label -v st0 /dev/ad2 /dev/ad3 接着需要写标准的 label, 也就是通常所说的分区表到新卷上, 并安装标准的引导代码: &prompt.root; bsdlabel -wB /dev/stripe/st0 上述过程将在 /dev/stripe 目录中的 st0 设备基础上建立两个新设备。 这包括 st0ast0c。 这时, 就可以在 st0a 设备上用下述 newfs 命令来建立文件系统了: &prompt.root; newfs -U /dev/stripe/st0a 在屏幕上将滚过一些数字, 整个操作应该能在数秒内完成。 现在可以挂接刚刚做好的卷了。 要挂接刚创建的条带盘: &prompt.root; mount /dev/stripe/st0a /mnt 要在启动过程中自动挂接这个条带上的文件系统, 需要把关于卷的信息放到 /etc/fstab 文件中: &prompt.root; echo "/dev/stripe/st0a /mnt ufs rw 2 2" \ >> /etc/fstab 此外, geom_stripe 模块也必须通过在 /boot/loader.conf 中增加下述设置, 以便在系统初始化过程中自动加载。 &prompt.root; echo 'geom_stripe_load="YES"' >> /boot/loader.conf RAID1 - 镜像 GEOM 磁盘镜像 镜像是一种许多公司和家庭用户使用的不需中断的备份技术。 当存在镜像时, 它的意思是说 磁盘B 简单地复制 磁盘A。 或者, 也可能是 磁盘C+D 复制 磁盘A+B。 无论磁盘如何配置, 共同的特征, 都是磁盘或卷的信息会被复制。 随后,在无需中断服务或访问的情况下, 可以很容易地复原和备份这些信息, 甚至把它们存储到其他更安全的地方。 要开始做这件事, 首先要确保系统中有两个同样大的磁盘驱动器, 下面的例子假定使用直接访问方式 (Direct Access, &man.da.4;) SCSI 的磁盘。 首先需要把 &os; 安装到第一块磁盘上, 并建立两个分区。 第一个分区将成为交换区, 其尺寸应该是两倍的 RAM 尺寸, 而余下的空间, 则作为根 (/) 文件系统来使用。 当然, 也可以为其他挂接点划分不同的分区; 但是, 这将使难度提高一个量级, 因为您将不得不手工修改 &man.bsdlabel.8; 和 &man.fdisk.8; 的设置。 重新启动系统, 并等待其完全初始化完。 当这个过程完成之后, 以 root 用户的身份登录。 创建 /dev/mirror/gm 设备, 并将其连接到 /dev/da1 &prompt.root; gmirror label -vnb round-robin gm0 /dev/da1 系统应会给出下列回应: Metadata value stored on /dev/da1. Done. 初始化 GEOM, 这将加载 /boot/kernel/geom_mirror.ko 内核模块: &prompt.root; gmirror load 这个命令应该会在 /dev/mirror 目录中创建 gm0 设备节点。 在刚创建的 gm0 设备上安装通用的 fdisk 标签以及引导区代码: &prompt.root; fdisk -vBI /dev/mirror/gm0 接下来安装通用的 bsdlabel 信息: &prompt.root; bsdlabel -wB /dev/mirror/gm0s1 如果存在多个区段 (slice) 或分区 (partition), 则需要修改一部分上面命令的参数。 它们必须与另一个盘上对应的区段和分区匹配。 使用 &man.newfs.8; 工具来在 gm0s1a 设备上建立默认的 UFS 文件系统: &prompt.root; newfs -U /dev/mirror/gm0s1a 这将让系统输出很多信息和一系列数字。 不必为此担心, 只需看看是否有错误提示就可以了, 如果没问题, 接下来把它挂到 /mnt 挂接点上面: &prompt.root; mount /dev/mirror/gm0s1a /mnt 现在需要把所有引导盘上的数据迁移到新的文件系统上了。 下面的例子使用了 &man.dump.8; 和 &man.restore.8; 这两个命令; 不过, 用 &man.dd.1; 在这里也可以达到完全一样的目的。 &prompt.root; dump -L -0 -f- / |(cd /mnt && restore -r -v -f-) 这个操作必须在所有文件系统上都作一遍。 您可以将前述命令中的文件系统, 改为所希望的文件系统的位置。 接下来应该编辑复制出来的 /mnt/etc/fstab 文件, 并删去或注释掉交换文件 需要注意的是, 在 fstab 注释掉交换文件, 通常会需要您以其他方式重建交换空间。 请参见 以了解进一步的细节。 。 修改其他文件系统对应的信息, 以便让它们使用新盘。 参考下面的例子: # Device Mountpoint FStype Options Dump Pass# #/dev/da0s2b none swap sw 0 0 /dev/mirror/gm0s1a / ufs rw 1 1 用下面的命令来确保系统引导时会加载 geom_mirror.ko &prompt.root; echo 'geom_mirror_load="YES"' >> /mnt/boot/loader.conf &prompt.root; echo 'geom_mirror_load="YES"' >> /boot/loader.conf 最后重新启动系统: &prompt.root; shutdown -r now 在启动时选择第 4 个选项进入单用户模式。 在控制台, 可以通过 &man.df.1; 的输出来确认系统是从 gm0s1a 启动的。 如果一切顺利,系统将从 gm0s1a 设备启动。 现在可以使用以下命令清除主磁盘并插入镜像中: &prompt.root; dd if=/dev/zero of=/dev/da0 bs=512 count=79 &prompt.root; gmirror configure -a gm0 &prompt.root; gmirror insert gm0 /dev/da0 此处 告诉 &man.gmirror.8; 采用自动同步, 或换言之: 自动地将磁盘的写操作做镜像处理。 联机手册中详细解释了如何重建, 以及替换磁盘, 只不过它用 data 表示这里的 gm0 在镜像建立后,可以用如下命令检查镜像的状态: &prompt.root; gmirror status 故障排除 系统拒绝引导 如果系统引导时出现类似下面的提示: ffs_mountroot: can't find rootvp Root mount failed: 6 mountroot> 这种情况应使用电源或复位按钮重启机器。 在引导菜单中, 选择第六 (6) 个选项。 这将让系统进入 &man.loader.8; 提示符。 在此处手工加载内核模块: OK? load geom_mirror OK? boot 如果这样做能解决问题, 则说明由于某种原因模块没有被正确加载。 可以通过在内核配置文件中加入: options GEOM_MIRROR 然后重新编译和安装内核来解决这个问题。 GEOM Gate 网络设备 通过 gate 工具, GEOM 支持以远程方式使用设备, 例如磁盘、 CD-ROM、 文件等等。 这和 NFS 类似。 在开始工作之前, 首先要创建一个导出文件。 这个文件的作用是指定谁可以访问导出的资源, 以及提供何种级别的访问授权。 例如, 要把第一块 SCSI 盘的第四个 slice 导出, 对应的 /etc/gg.exports 会是类似下面的样子: 192.168.1.0/24 RW /dev/da0s4d 这表示允许同属私有子网的所有机器访问 da0s4d 分区上的文件系统。 要导出这个设备, 首先请确认它没有被挂接, 然后是启动 &man.ggated.8; 服务: &prompt.root; ggated 现在我们将在客户机上 mount 该设备, 使用下面的命令: &prompt.root; ggatec create -o rw 192.168.1.1 /dev/da0s4d ggate0 &prompt.root; mount /dev/ggate0 /mnt 到此为止, 设备应该已经可以通过挂接点 /mnt 访问了。 请注意, 如果设备已经被服务器或网络上的任何其他机器挂接, 则前述操作将会失败。 如果不再需要使用这个设备, 就可以使用 &man.umount.8; 命令来安全地将其卸下了, 这一点和其他磁盘设备类似。 为磁盘设备添加卷标 GEOM 磁盘卷标 在系统初始化的过程中, &os; 内核会为检测到的设备创建设备节点。 这种检测方式存在一些问题, 例如, 在通过 USB 添加设备时应如何处理? 很可能有闪存盘设备最初被识别为 da0 而在这之后, 则由 da0 变成了 da1。 而这则会在挂接 /etc/fstab 中的文件系统时造成问题, 这些问题, 还可能在系统引导时导致无法正常启动。 解决这个问题的一个方法是以连接拓扑方式链式地进行 SCSI 设备命名, 这样, 当在 SCSI 卡上增加新设备时, 这些设备将使用一个未用的编号。 但如果 USB 设备取代了主 SCSI 磁盘的位置呢? 由于 USB 通常会在 SCSI 卡之前检测到, 因此很可能出现这种现象。 当然, 可以通过在系统引导之后再插入这些设备来绕过这个问题。 另一种绕过这个问题的方法, 则是只使用 ATA 驱动器, 并避免在 /etc/fstab 中列出 SCSI 设备。 还有一种更好的解决方法。 通过使用 glabel 工具, 管理员或用户可以为磁盘设备打上标签, 并在 /etc/fstab 中使用这些标签。 由于 glabel 会将标签保存在对应 provider 的最后一个扇区, 在系统重启之后, 它仍会持续存在。 因此, 通过将具体的设备替换为使用标签表示, 无论设备节点变成什么, 文件系统都能够顺利地完成挂接。 这并不是说标签一定是永久性的。 glabel 工具既可以创建永久性标签, 也可以创建临时性标签。 在重启时, 只有永久性标签会保持。 请参见联机手册 &man.glabel.8; 以了解两者之间的差异。 标签类型和使用示范 有两种类型的标签, 一种是普通标签, 另一种是文件系统标签。 两者的差异体现在是否能够自动检测, 以及是否在重启后保持。 这些标签会放到 /dev 中的特殊目录中, 这些目录的名字取决于文件系统类型。 例如, UFS2 文件系统的标签会创建到 /dev/ufs 目录中。 普通标签在系统下次重启时会消失, 这些标签会创建到 /dev/label 目录中, 很适合测试之用。 永久性标签可以使用 tunefsnewfs 工具来创建。 要为 UFS2 文件系统创建标签, 而不破坏其上的数据, 可以使用下面的命令: &prompt.root; tunefs -L home /dev/da3 如果文件系统满了, 这可能会导致数据损坏; 不过, 如果文件系统快满了, 此时应首先删除一些无用的文件, 而不是增加标签。 现在, 您应可以在 /dev/ufs 目录中看到标签, 并将其加入 /etc/fstab /dev/ufs/home /home ufs rw 2 2 当运行 tunefs 时, 应首先卸下文件系统。 现在可以像平时一样挂接文件系统了: &prompt.root; mount /home 现在, 只要在系统引导时通过 /boot/loader.conf 配置加载了内核模块 geom_label.ko, 或在联编内核时指定了 GEOM_LABEL 选项, 设备节点由于增删设备而顺序发生变化时, 就不会影响文件系统的挂接了。 通过使用 newfs 命令的 参数, 可以在创建文件系统时为其添加默认的标签。 请参见联机手册 &man.newfs.8; 以了解进一步的详情。 下列命令可以清除标签: &prompt.root; glabel destroy home 通过 GEOM 实现 UFS 日志 GEOM 日志 随着 &os; 7.0 的发布, 实现了长期为人们所期待的 UFS 日志。 这个实现采用了 GEOM 子系统, 可以很容易地使用 &man.gjournal.8; 工具来进行配置。 日志是什么? 日志的作用是保存文件系统事务的记录, 换言之, 完成一次完整的磁盘写入操作所需的变动, 这些记录会在元数据以及文件数据写盘之前, 写入到磁盘中。 这种事务日志可以在随后用于重放并完成文件系统事务, 以避免文件系统出现不一致的问题。 这种方法是另一种阻止文件系统丢失数据并发生不一致的方法。 与 Soft Updates 追踪并确保元数据更新顺序这种方法不同, 它会实际地将日志保存到磁盘最后的扇区, 或另外一块磁盘上。 与其他文件系统的日志实现不同, gjournal 采用的是基于块, 而不是作为文件系统的一部分的方式 - 它只是作为一种 GEOM 扩展实现。 如果希望启用 gjournal, &os; 内核需要下列选项 - 这是 7.X 系统上的默认配置: options UFS_GJOURNAL 现在, 可以为空闲的文件系统创建日志了。 对于新增的 SCSI 磁盘 da4, 具体的操作步骤为: &prompt.root; gjournal label /dev/da4 &prompt.root; gjournal load 这样, 就会出现一个与 /dev/da4 设备节点对应的 /dev/da4.journal 设备节点。 接下来, 可以在这个设备上建立文件系统: &prompt.root; newfs -O 2 -J /dev/da4.journal 这个命令将建立一个包含日志的 UFS2 文件系统。 然后就可以用 mount 命令来挂接设备了: &prompt.root; mount /dev/da4.journal /mnt 当磁盘包含多个 slice 时, 每个 slice 上都会建立日志。 例如, 如果有 ad4s1ad4s2 这两个 slice, 则 gjournal 会建立 ad4s1.journalad4s2.journal。 如果连续运行两次这个命令, 则会建立 多层日志 在某些情况下, 可能会希望在其他磁盘上保存日志。 对于这些情形, 日志提供者或存储设备, 应在启用日志的设备后给出。 在暨存的文件系统上, 可以用 tunefs 来启用日志; 不过, 在尝试修改文件系统之前, 您应对其进行备份。 多数情况下, gjournal 会因为无法建立日志而失败, 在误用 tunefs 时, 这可能导致失败。