options KVA_PAGES=512
第 21 章 文件系统 Support
This translation may be out of date. To help with the translations please access the FreeBSD translations instance.
Table of Contents
21.1. 概述
文件系统对于任何操作系统来说都是一个不可缺的部分。 它们允许用户上载和存储文件,提供对数据的访问,当然, 是使硬盘能具有实际的用途。不同的操作系统通常都有一个共同的主要方面, 那就是它们原生的文件系统。在 FreeBSD 上这个文件系统通常被称为快速文件系统或者 FFS, 这是基于原来的 Unix™ 文件系统,通常也被称为 UFS。 这是 FreeBSD 用于在磁盘上访问数据的原生的文件系统。
FreeBSD 也支持数量繁多的不同的文件系统, 用于提供本地从其他操作系统上访问数据的支持, 那些就是指存放在本地挂载的 USB 存储设备,闪存设备和硬盘上的数据。还支持一些非原生的文件系统。 这些文件系统是在其他的操作系统上开发的,像 Linux® 的扩展文件系统 (EXT),和 Sun™ 的 Z 文件系统 (ZFS)。
FreeBSD 上对于各种文件系统的支持分成不同的层次。 一些要求加载内核模块,另外的可能要求安装一系列的工具。 这一章节旨在帮助 FreeBSD 用户在他们的系统上访问其他的文件系统, 由 Sun™ 的 Z 文件系统开始。
在阅读了这一章节之后,你将了解:
原生与被支持的文件系统之间的区别。
FreeBSD 支持哪些文件系统。
如何起用,配置,访问和使用非原生的文件系统。
在阅读这章以前,你应该:
了解 UNIX® 和 FreeBSD 基本知识 (UNIX 基础)。
熟悉基本的内核配置/编译方法 (配置FreeBSD的内核)。
熟悉在 FreeBSD 上安装第三方软件 (安装应用程序. Packages 和 Ports)。
熟悉 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™ 构架的用户应在内核配置文件中加入以下的选项, 重新编译内核并重启机器:
这个选项将扩展内核的地址空间, 因而允许 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 磁盘可用, 它们的设备名分别为 da0, da1 和 da2。 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 设备, da0, da1 和 da2 (或者 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
使用 df
和 mount
命令将显示现在系统把我们的文件系统真正当作了 /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
这个例子中完成时间非常的清楚。 这个特性可以帮助你在很长的一段时间内确保数据的完整。
Last modified on: March 9, 2024 by Danilo G. Baio