第 21 章 文件系统 Support

This translation may be out of date. To help with the translations please access the FreeBSD translations instance.

21.1. 概述

文件系统对于任何操作系统来说都是一个不可缺的部分。 它们允许用户上载和存储文件,提供对数据的访问,当然, 是使硬盘能具有实际的用途。不同的操作系统通常都有一个共同的主要方面, 那就是它们原生的文件系统。在 FreeBSD 上这个文件系统通常被称为快速文件系统或者 FFS, 这是基于原来的 Unix™ 文件系统,通常也被称为 UFS。 这是 FreeBSD 用于在磁盘上访问数据的原生的文件系统。

FreeBSD 也支持数量繁多的不同的文件系统, 用于提供本地从其他操作系统上访问数据的支持, 那些就是指存放在本地挂载的 USB 存储设备,闪存设备和硬盘上的数据。还支持一些非原生的文件系统。 这些文件系统是在其他的操作系统上开发的,像 Linux® 的扩展文件系统 (EXT),和 Sun™ 的 Z 文件系统 (ZFS)。

FreeBSD 上对于各种文件系统的支持分成不同的层次。 一些要求加载内核模块,另外的可能要求安装一系列的工具。 这一章节旨在帮助 FreeBSD 用户在他们的系统上访问其他的文件系统, 由 Sun™ 的 Z 文件系统开始。

在阅读了这一章节之后,你将了解:

  • 原生与被支持的文件系统之间的区别。

  • FreeBSD 支持哪些文件系统。

  • 如何起用,配置,访问和使用非原生的文件系统。

在阅读这章以前,你应该:

21.2. Z 文件系统 (ZFS)

Z 文件系统是由 Sun™ 开发使用存储池方法的新技术。 这就是说只有在需要存储数据的时候空间才会被使用。 它也为保护数据最大完整性而设计的,支持数据快照, 多份拷贝和数据校验。增加了被称为 RAID-Z 的新的数据复制类型。RAID-Z 是种类似于 RAID5类型, 但被设计成防止写入漏洞。

21.2.1. 调整 ZFS

ZFS 子系统需利用到大量的系统资源, 所以可能需要一些调校来为日常应用提供最大化的效能。 作为 FreeBSD 的一项试验性的特性,这可能在不久的将来有所变化; 无论如何,下面的这些步骤是我们推荐的:

21.2.1.1. 内存

总共的系统内存至少应有 1GB,推荐 2GB 或者更多。 在此处所有的例子中,我们使用了 1GB 内存的系统并配合了一些恰当的调校。

有些人在少于 1GB 内存的环境有幸正常使用, 但是在这样有限的物理内存的条件下,当系统的负载很高时, FreeBSD 极有可能因于内存耗尽而崩溃。

21.2.1.2. 内核配置

我们建议把未使用的驱动和选项从内核配置文件中去除。 既然大部份的驱动都有以模块的形式存在,它们就可以很容易的通过 /boot/loader.conf 加载。

i386™ 构架的用户应在内核配置文件中加入以下的选项, 重新编译内核并重启机器:

options 	KVA_PAGES=512

这个选项将扩展内核的地址空间, 因而允许 vm.kvm_size 能够超越 1 GB 的限制(PAE为 2 GB)。 为了找出这个选项最合适的值, 把以兆(MB)为单位所需的地址空间除以 4 得到。 在这个例子中,512 则为 2 GB。

21.2.1.3. Loader 可调参数

所有构架上 FreeBSD 都应该加大 kmem 地址空间。在有 1GB 物理内存的测试系统上,在 /boot/loader.conf 中加入如下的参数并且重启后通过了测试。

vm.kmem_size="330M"
vm.kmem_size_max="330M"
vfs.zfs.arc_max="40M"
vfs.zfs.vdev.cache.size="5M"

更多 ZFS 相关推荐调校的细节请参阅 http://wiki.freebsd.org/ZFSTuningGuide.

21.2.2. 使用 ZFS

FreeBSD 有一种启动机制能在系统初始化时挂载 ZFS 存储池。 可以通过以下的命令设置:

# echo 'zfs_enable="YES"' >> /etc/rc.conf
# /etc/rc.d/zfs start

这份文档剩余的部分假定系统中有 3 块 SCSI 磁盘可用, 它们的设备名分别为 da0da1da2。 IDE 硬件的用户可以使用 ad 代替 SCSI。

21.2.2.1. 单个磁盘存储池

在单个磁盘上创建一个简单, 非冗余的 ZFS, 使用 zpool 命令:

# zpool create example /dev/da0

可以通过 df 的输出查看新的存储池:

# df
Filesystem  1K-blocks    Used    Avail Capacity  Mounted on
/dev/ad0s1a   2026030  235230  1628718    13    /
devfs               1       1        0   100    /dev
/dev/ad0s1d  54098308 1032846 48737598     2    /usr
example      17547136       0 17547136     0    /example

这份输出清楚的表明了 example 存储池不仅创建成功而且被 挂载 了。 我们能像访问普通的文件系统那样访问它, 就像以下例子中演示的那样,用户能够在上面创建文件并浏览:

# cd /example
# ls
# touch testfile
# ls -al
total 4
drwxr-xr-x   2 root  wheel    3 Aug 29 23:15 .
drwxr-xr-x  21 root  wheel  512 Aug 29 23:12 ..
-rw-r--r--   1 root  wheel    0 Aug 29 23:15 testfile

遗憾的是这个存储池并没有利用到 ZFS 的任何特性。 在这个存储池上创建一个文件系统,并启用压缩:

# zfs create example/compressed
# zfs set compression=gzip example/compressed

现在 example/compressed 是一个启用了压缩的 ZFS 文件系统了。 可以尝试复制一些大的文件到 /example/compressed

使用这个命令可以禁用压缩:

# zfs set compression=off example/compressed

使用如下的命令卸载这个文件系统,并用 df 工具确认:

# zfs umount example/compressed
# df
Filesystem  1K-blocks    Used    Avail Capacity  Mounted on
/dev/ad0s1a   2026030  235232  1628716    13    /
devfs               1       1        0   100    /dev
/dev/ad0s1d  54098308 1032864 48737580     2    /usr
example      17547008       0 17547008     0    /example

重新挂在这个文件系统使之能被访问, 并用 df 确认:

# zfs mount example/compressed
# df
Filesystem         1K-blocks    Used    Avail Capacity  Mounted on
/dev/ad0s1a          2026030  235234  1628714    13    /
devfs                      1       1        0   100    /dev
/dev/ad0s1d         54098308 1032864 48737580     2    /usr
example             17547008       0 17547008     0    /example
example/compressed  17547008       0 17547008     0    /example/compressed

存储池与文件系统也可通过 mount 的输出查看:

# mount
/dev/ad0s1a on / (ufs, local)
devfs on /dev (devfs, local)
/dev/ad0s1d on /usr (ufs, local, soft-updates)
example on /example (zfs, local)
example/data on /example/data (zfs, local)
example/compressed on /example/compressed (zfs, local)

正如前面所提到的,ZFS 文件系统, 在创建之后就能像普通的文件系统那样使用。然而, 还有很多其他的特性是可用的。在下面的例子中, 我们将创建一个新的文件系统,data。 并要在上面存储些重要的文件, 所以文件系统需要被设置成把每一个数据块都保存两份拷贝:

# zfs create example/data
# zfs set copies=2 example/data

现在可以再次使用 df 查看数据和空间的使用状况:

# df
Filesystem         1K-blocks    Used    Avail Capacity  Mounted on
/dev/ad0s1a          2026030  235234  1628714    13    /
devfs                      1       1        0   100    /dev
/dev/ad0s1d         54098308 1032864 48737580     2    /usr
example             17547008       0 17547008     0    /example
example/compressed  17547008       0 17547008     0    /example/compressed
example/data        17547008       0 17547008     0    /example/data

请注意存储池上的每一个文件系统都有着相同数量的可用空间。 这就是我们在这些例子中使用 df 的原因, 是为了文件系统都是从相同的存储池取得它们所需的空间。 ZFS 去掉了诸如卷和分区此类的概念, 并允许多个文件系统占用同一个存储池。 不再需要文件系统与存储池的时候能像这样销毁它们:

# zfs destroy example/compressed
# zfs destroy example/data
# zpool destroy example

磁盘无法避免的会坏掉和停止运转。 当这块磁盘坏掉的时候,上面的数据都将丢失。 一个避免因磁盘损坏而丢失数据的方法是使用 RAID。ZFS 在它的存储池设计中支持这样的特性, 这便是下一节将探讨的。

21.2.2.2. ZFS RAID-Z

正如前文中所提到的,这一章节将假设存在 3 个 SCSI 设备, da0da1da2 (或者 ad0 和超出此例使用了 IDE 磁盘)。 使用如下的命令创建一个 RAID-Z 存储池:

# zpool create storage raidz da0 da1 da2

Sun™ 推荐在一个 RAID-Z 配置中使用的磁盘数量为 3 至 9 块。 如果你要求在单独的一个存储池中使用 10 块或更多的磁盘, 请考虑分拆成更小 RAID-z 组。 如果你只有 2 块磁盘, 并仍然需要冗余, 请考虑使用 ZFS 的 mirror 特性。 更多细节请参考 zpool(8) 手册页。

zpool storage 至此就创建好了。 可以如前文提到的那样使用 mount(8)df(1) 确认。 如需配给更多的磁盘设备则把它们加这个列表的后面。 在存储池上创建一个叫 home 的文件系统, 用户的文件最终都将被保存在上面:

# zfs create storage/home

像前文中提到的那样,用户的目录与文件也可启用压缩并保存多份拷贝, 可通过如下的命令完成:

# zfs set copies=2 storage/home
# zfs set compression=gzip storage/home

把用户的数据都拷贝过来并创建一个符号链接, 让他们开始使用这个新的目录:

# cp -rp /home/* /storage/home
# rm -rf /home /usr/home
# ln -s /storage/home /home
# ln -s /storage/home /usr/home

现在用户的数据应该都保存在新创建的 /storage/home 上了。 测试添加一个新用户并以这个身份登录。

尝试创建一个可日后用来回退的快照:

# zfs snapshot storage/home@08-30-08

请注意快照选项将只会抓取一个真实的文件系统, 而不是某个用户目录或文件。@ 字符为文件系统名或卷名的分隔符。 当用户目录被损坏时,可用如下命令恢复:

# zfs rollback storage/home@08-30-08

获得所有可用快照的列表,可使用 ls 命令查看文件系统的 .zfs/snapshot 目录。例如,执行如下命令来查看之前抓取的快照:

# ls /storage/home/.zfs/snapshot

可以编写一个脚本来每月定期抓取用户数据的快照,久而久之, 快照可能消耗掉大量的磁盘空间。 之前创建的快照可用以下命令删除:

# zfs destroy storage/home@08-30-08

在所有这些测试之后,我们没有理由再把 /store/home 这样放置了。让它称为真正的 /home 文件系统:

# zfs set mountpoint=/home storage/home

使用 dfmount 命令将显示现在系统把我们的文件系统真正当作了 /home

# mount
/dev/ad0s1a on / (ufs, local)
devfs on /dev (devfs, local)
/dev/ad0s1d on /usr (ufs, local, soft-updates)
storage on /storage (zfs, local)
storage/home on /home (zfs, local)

# df
Filesystem   1K-blocks    Used    Avail Capacity  Mounted on
/dev/ad0s1a    2026030  235240  1628708    13    /
devfs                1       1        0   100    /dev
/dev/ad0s1d   54098308 1032826 48737618     2    /usr
storage       26320512       0 26320512     0    /storage
storage/home  26320512       0 26320512     0    /home

这样就基本完成了 RAID-Z 的配置了。使用夜间 periodic(8) 获取有关文件系统创建之类的状态更新, 执行如下的命令:

# echo 'daily_status_zfs_enable="YES"' >> /etc/periodic.conf

21.2.2.3. 修复 RAID-Z

每一种软 RAID 都有监测它们 状态 的方法。 ZFS 也不例外。 可以使用如下的命令查看 RAID-Z 设备:

# zpool status -x

如果所有的存储池处于健康状态并且一切正常的话, 将返回如下信息:

all pools are healthy

如果存在问题,可能是一个磁盘设备下线了, 那么返回的存储池的状态将看上去是类似这个样子的:

pool: storage
 state: DEGRADED
status: One or more devices has been taken offline by the administrator.
	Sufficient replicas exist for the pool to continue functioning in a
	degraded state.
action: Online the device using 'zpool online' or replace the device with
	'zpool replace'.
 scrub: none requested
config:

	NAME        STATE     READ WRITE CKSUM
	storage     DEGRADED     0     0     0
	  raidz1    DEGRADED     0     0     0
	    da0     ONLINE       0     0     0
	    da1     OFFLINE      0     0     0
	    da2     ONLINE       0     0     0

errors: No known data errors

在这个例子中,这是由管理员把此设备下线后的状态。 可以使用如下的命令将磁盘下线:

# zpool offline storage da1

现在切断系统电源之后就可以替换下 da1 了。 当系统再次上线时,使用如下的命令替换磁盘:

# zpool replace storage da1

至此可用不带 -x 标志的命令再次检查状态:

# zpool status storage
pool: storage
 state: ONLINE
 scrub: resilver completed with 0 errors on Sat Aug 30 19:44:11 2008
config:

	NAME        STATE     READ WRITE CKSUM
	storage     ONLINE       0     0     0
	  raidz1    ONLINE       0     0     0
	    da0     ONLINE       0     0     0
	    da1     ONLINE       0     0     0
	    da2     ONLINE       0     0     0

errors: No known data errors

在这个例子中,一切都显示正常。

21.2.2.4. 数据校验

正如前面所提到的,ZFS 使用 校验和(checksum) 来检查存储数据的完整性。 这时在文件系统创建时自动启用的,可使用以下的命令禁用:

# zfs set checksum=off storage/home

这不是个明智的选择,因为校验和 不仅非常有用而且只需占用少量的存储空间。 并且启用它们也不会明显的消耗过多资源。 启用后就可以让 ZFS 使用校验和校验来检查数据的完整。 这个过程通常称为 "scrubbing"。 可以使用以下的命令检查 storage 存储池里数据的完整性:

# zpool scrub storage

这个过程需花费相当长的时间,取决于存储的数据量。 而且 I/O 非常密集, 所以在任何时间只能执行一个这样的操作。 在 scrub 完成之后,状态就会被更新, 可使用如下的命令查看:

# zpool status storage
pool: storage
 state: ONLINE
 scrub: scrub completed with 0 errors on Sat Aug 30 19:57:37 2008
config:

	NAME        STATE     READ WRITE CKSUM
	storage     ONLINE       0     0     0
	  raidz1    ONLINE       0     0     0
	    da0     ONLINE       0     0     0
	    da1     ONLINE       0     0     0
	    da2     ONLINE       0     0     0

errors: No known data errors

这个例子中完成时间非常的清楚。 这个特性可以帮助你在很长的一段时间内确保数据的完整。

Z 文件系统有更多的选项,请参阅 zfs(8)zpool(8) 手册页。


Last modified on: March 9, 2024 by Danilo G. Baio