IBM 的日志文件系统

作者:Steve Best

新功能不断添加到 Linux 内核中;其中之一是对日志文件系统的支持。IBM 的 JFS 是现在可用于 Linux 的众多日志文件系统之一。本文解释了 JFS 的内部结构和特性,如何在 Linux 服务器上安装和配置它,以及 JFS 在蒙特利尔爱立信研究实验室的运行经验。

文件系统用于在磁盘驱动器上存储和管理用户数据。它确保写入磁盘的数据的完整性与读回的数据相同。除了在文件中存储数据外,文件系统还创建和管理关于文件系统自身的信息,例如可用空间和 inodes。文件系统结构通常被称为元数据,它指的是关于文件的所有信息,除了文件内的实际数据。文件的元素,例如其物理位置和大小,都由元数据跟踪。

日志文件系统与非日志文件系统

日志文件系统提供改进的结构一致性和可恢复性。与非日志文件系统相比,它还具有更快的重启时间。

非日志文件系统在系统故障时容易损坏。这是因为一个逻辑文件操作通常需要多次媒体 I/O 才能完成,并且在任何给定时间点可能无法完全反映在媒体上。例如,将数据写入文件的简单任务可能涉及多个步骤

  • 分配块以保存数据。

  • 更新块指针。

  • 更新文件的大小。

  • 写入实际数据。

如果系统在这些操作未完全完成时中断,则非日志文件系统最终会处于不一致状态。在这种情况下,这些文件系统依赖于它们的 fsck 实用程序来检查文件系统的所有元数据(例如,目录和磁盘寻址结构),以检测和修复结构完整性问题,然后再重新启动。 fsck 可能相当耗时,时间长短取决于分区的大小、目录的数量以及每个目录中文件的数量。对于大型文件系统,日志记录变得至关重要。另一方面,日志文件系统可以在不到一秒的时间内重新启动。

JFS 简介

JFS 旨在支持从系统中断中快速恢复、大型文件和分区以及大量目录和文件。为了满足这些要求,JFS 提供了亚秒级的文件系统恢复时间,这通过仅记录元数据来实现。JFS 还提供 64 位可扩展性,文件和分区范围达到拍字节级别。此外,所有文件系统磁盘结构都使用 B+ 树索引。为了获得更好的性能,B+ 树被广泛用于替代传统的线性文件系统结构。

文件系统

文件以 extent 序列分配。Extent 是分配给 JFS 对象作为单元的连续聚合块序列。一个 extent 完全包含在一个聚合内(因此,也包含在一个分区内)。但是,大型 extent 可能跨越多个分配组。Extent 的大小范围可以从 1 到 224 - 1 个块。例如,JFS 对 extent 的长度使用 24 位值。如果块大小为 4K,则最大 extent 将为 4K * 224 - 1 字节,等于 (~64G)。请注意,此限制仅适用于单个 extent;它绝不限制整体文件大小。Extent 在 B+ 树中索引,以便在插入新 extent、定位特定 extent 等方面获得更好的性能。

通常,JFS 的分配策略试图通过分配最少数量的 extent 来最大化连续分配,每个 extent 尽可能大且连续。这允许更大的 I/O 传输,从而提高性能。

JFS 历史

IBM 在 AIX 3.1 版本的初始版本中推出了其 UNIX 文件系统,称为日志文件系统 (JFS)。此文件系统现在在 AIX 上称为 JFS1。在过去的十年中,它一直是 AIX 的首要文件系统,并已安装在数百万客户的 AIX 系统中。1995 年,开始致力于使文件系统更具可扩展性,并支持具有多个处理器的机器。另一个目标是拥有一个更便携的文件系统,能够在多个操作系统上运行。

从历史上看,JFS1 文件系统与 AIX 的内存管理器紧密相关。这种设计是闭源操作系统或仅支持一个操作系统的文件系统的典型特征。

新的日志文件系统(Linux 端口基于此文件系统)在经过多年的设计、编码和测试后,于 1999 年 4 月作为 OS/2 Warp Server for eBusiness 的一部分首次发布。它还在 2000 年 10 月与 OS/2 Warp Client 一起发布。与此同时,JFS 开发团队的一些成员于 1997 年返回 AIX 操作系统开发组,并开始将这个新的 JFS 源代码库迁移到 AIX 操作系统。2001 年 5 月,第二个日志文件系统,增强型日志文件系统 (JFS2),可用于 AIX 5L。同时,在 1999 年 12 月,获取了 OS/2 JFS 源代码的快照,并开始将 JFS 移植到 Linux。

作为开源项目的经验

1999 年 12 月,三个潜在的日志文件系统开始或正在开发或移植到 Linux。Ext2 正在其文件系统中添加日志记录,名称为 ext3。SGI 开始将其 XFS 文件系统从 IRIX 移植过来。第三个文件系统由 Hans Reiser 开发,后来被称为 ReiserFS。但是,这些文件系统在 1999 年在 Linux 上均未完全正常运行。IBM 认为 JFS 是一项强大的技术,可以为 Linux 操作系统增加价值。

与顶级的 Linux 文件系统开发人员进行了联系,并探讨了添加另一个日志文件系统的可能性。Linux 的基本底层哲学之一是选择是好的,因此接受了另一个日志文件系统的想法。

IBM 于 1999 年 12 月开始将 JFS 迁移到 Linux,到 2000 年 2 月,他们发布了第一个源代码。此初始版本包含参考源代码、mount/unmount 函数以及对 JFS 分区上 ls 命令的支持。

在单独分区上安装 JFS

JFS 已并入 2.5.6 Linux 内核,并且也包含在 Alan Cox 的 2.4.X-ac 内核中,从 2002 年 2 月发布的 2.4.18-pre9-ac4 开始。Alan 的 2.4.x 系列补丁可从 kernel.org 获取。您也可以下载 2.4 内核源代码树并将 JFS 补丁添加到此树中。JFS 作为几个 2.4.x 内核的补丁提供,因此请从 kernel.org 获取最新的内核。

在撰写本文时,最新的内核是 2.4.18,最新的 JFS 版本是 1.0.20。我们在以下部分中使用它们。JFS 补丁可从 JFS 网站获得。您还需要实用程序 (jfsutils-1.0.20.tar.gz) 和文件系统 (jfs-2.4.18-patch 和 jfs-2.4-1.0.20.tar.gz) 补丁。一些 Linux 发行版已经发布了 JFS:Turbolinux、Mandrake、SuSE、Red Hat 和 Slackware 都在其最新版本中发布了 JFS。

修补内核以支持 JFS

如果您使用任何先前命名的发行版,则无需为 JFS 代码修补内核。您只需要编译内核以支持 JFS(内置或作为模块)。

首先,下载标准 Linux 内核。如果您有 /usr/src/linux 目录,请移动它,以免被 linux-2.4.18 源代码树替换。下载内核后,命名为 linux-2.4.18.tar.gz,将其保存在 /usr/src 下并解压。此操作将创建一个新的 /usr/src/linux 目录。

下一步是获取 JFS 实用程序和内核 2.4.18 的适当补丁。为 JFS 源代码创建一个目录 /usr/src/jfs1020,并将 JFS 内核补丁 jfs-2.4-18-patch 和 JFS 补丁 jfs-2.4-1.0.20.tar.gz 下载到该目录。此时,您已拥有修补内核所需的所有文件。

接下来,更改到内核 2.4.18 源代码树的目录以应用 JFS 内核补丁

% cd /usr/src/linux
% patch -p1 < /usr/src/jfs1020/jfs-2.4-18-patch
% cp /usr/src/jfs1020/jfs-2.4-1.0.20.tar.gz .
% tar zxvf jfs-2.4-1.0.20.tar.gz

配置内核并通过转到配置菜单的“文件系统”部分并启用 JFS 支持 CONFIG_JFS_FS=y 来启用 JFS。您还可以选择将 JFS 配置为模块。在这种情况下,您只需要重新编译并重新安装内核模块

% make modules && make install_modules
否则,如果您将 JFS 选项配置为内核内置,则需要重新编译内核(在 /usr/src/linux 中)
% make dep && make clean && make bzImage
然后,重新编译并安装模块(仅当您添加了其他选项作为模块时)
% make modules && make modules_install
最后,安装新内核
% cp arch/i386/boot/bzImage /boot/bzImage-jfs
% cp System.map /boot/System.map-jfs
% ln -s /boot/System.map-jfs /boot/System.map
不要忘记运行 lilo。(如果您从未重新编译过内核,请阅读 Kernel-HOWTO 以了解如何操作。)

编译并安装内核后,您应该编译并安装 JFS 实用程序。将 jfsutils-1.0.20.tar.gz 文件保存到 /usr/src/jfs1020,然后

% tar zxvf jfsutils-1.0.20.tar.gz
% cd jfsutils-1.0.20
% ./configure
% make && make install

构建并安装 JFS 实用程序后,下一步是创建 JFS 分区。在以下示例中,我们使用备用分区;下一节将演示如何将现有分区迁移到 JFS。

如果磁盘上有未分区空间,则可以使用 fdisk 创建分区。在我们的测试系统中,我们有 /dev/hdb3 作为备用分区,因此我们将其格式化为 JFS 分区。创建分区后,重新启动系统以确保新分区能够创建 JFS。

要创建 JFS,请应用以下命令

% mkfs.jfs /dev/hdb3

创建文件系统后,您需要挂载它。要获取挂载点,请创建一个新的空目录,例如 /mnt/jfs,并使用以下挂载命令

% mount -t jfs /dev/hdb3 /mnt/jfs
挂载文件系统后,您就可以试用 JFS 了。

要卸载 JFS,只需使用 umount 命令,使用与之前相同的挂载点

% umount /mnt/jfs
将分区从 ext2 迁移到 JFS

在上一节中,我们解释了如何使用现有备用分区创建 JFS 文件系统。现在,我们将演示如何将您当前的系统从另一个文件系统(例如 ext2)迁移到 JFS。我们将了解如何将 JFS 分区引入您的 Linux 配置。在第二步中,我们将使该分区成为根文件系统。

您需要什么分区方案来创建 JFS 根分区?迁移过程需要一个空分区。假设 /dev/hda5 是当前的根分区,并且它使用 ext2。我们使用 /dev/hda6(它是我们的空分区)作为我们的 JFS 根分区。此分区需要等于或大于当前根分区的大小。ext2 分区将被复制到 JFS 分区上。之后,如果您不想保留 ext2 分区,则可以重新格式化它而不会丢失您的 Linux 系统。

为了在 /dev/hda6 上创建根 JFS 分区,请按照前面提到的说明获取内核中对 JFS 的支持。为了使此分区成为 Linux 的可引导分区,您需要重现完整的 Linux 安装。一种简单的方法是将所有文件复制到 JFS 分区。首先,挂载文件系统

% mount -t jfs /dev/hda6 /jfs

然后,将所有文件从 ext2 文件系统复制到 JFS 分区

% cd /
% cp -a bin etc lib boot dev home usr var [...] /jfs
  You need special handling for /proc and /tmp:
        % mkdir /jfs/proc
        % chmod 555 /jfs/proc
        % mkdir /jfs/tmp
        % chmod 1777 /jfs/tmp
创建 /proc 和 /tmp 时,权限正确非常重要。权限 1777 意味着唯一可以重命名或删除该目录中任何文件的人是文件的所有者、目录的所有者和超级用户。最后一步涉及更改 /etc/lilo.conf 和 /etc/fstab。首先,我们更改 lilo.conf 以使用 JFS 分区上的内核启动。请注意,root 与我们制作的第一个条目以及标签都不同。因此,要引导的映像将不会在 /dev/hda5/boot 中找到,而是在 /dev/hda6/boot 中找到
image=/boot/vmlinuz-jfs
        label=jfs-kernel
        read-only
        root=/dev/hda6
最后,我们需要更改 /jfs/etc/fstab 以告诉 Linux 系统它正在使用的文件系统。更改以下行
LABEL=/         /       ext2    defaults        1 1
使其变为
/dev/hda6       /       jfs     defaults        1 1
现在,您可以重新启动并选择 jfs-kernel。这将使用 JFS 根文件系统启动 Linux。

崩溃后,日志重放会自动发生。您应该看到 JFS 日志消息,而不是通常的 fsck 消息。当文件系统变得不稳定时,重放日志是必要的。

JFS 在蒙特利尔爱立信研究实验室的经验

爱立信研究开放系统实验室的职责之一是设计、实施和基准测试运行电信应用的运营商级平台。这些运营商级平台对可扩展性、可靠性和高可用性有严格的要求。它们必须不间断运行,无论硬件或软件错误如何,并且它们必须允许运营商在运行期间升级硬件和软件,而不会干扰在其上运行的应用程序。因此,它们必须提供极高的可靠性和高可用性,通常称为五个九的可用性(99.999% 正常运行时间)。

为了维持如此高的可用性,这些运营商级平台在设计时考虑了许多功能,允许在系统运行和提供服务时升级软件。这些功能包括在软件中实现的容错、处理灾难性情况(如地震)的网络冗余以及在线升级功能。

尽管已采取许多预防措施来保护系统,但处理器(或服务器节点)始终存在远程故障的可能性。因此,作为最后的手段,我们需要重新启动处理器。在这种极端情况下,我们需要能够重新启动处理器并使其恢复正常状态,尽快提供服务,并最大限度地减少停机时间。

我们对运营商级 Linux 平台的日志文件系统的兴趣来自于这些文件系统提供快速文件系统重启的事实。在系统崩溃的情况下,日志文件系统可以比其他文件系统更快、更可靠地将文件系统恢复到一致状态。

最初,我们在 2000 年初开始试验 IBM JFS。JFS 团队非常乐于助人和支持,他们的代表 Steve Best 于 2001 年 1 月访问了我们的实验室。从那时起,我们一直在密切关注 JFS 的开发,并将我们的服务器升级到支持最新版本。

IBM's Journaled Filesystem

图 1. 用于测试 JFS 的 1U 机架式单元

JFS 的首次安装是在 1U 机架式单元上完成的,这些单元配备了 Celeron 500MHz 处理器、256MB RAM 和 20GB IDE 磁盘。这些单元为我们提供了一个工作环境来测试 JFS,并使用我们的一些应用程序来试验其功能。自从 2001 年 6 月发布 JFS 1.0.0 版本以来,我们决定在我们的测试 Linux 平台上安装 JFS,如图 2 所示。

IBM's Journaled Filesystem

图 2. 用于在 Linux 上测试 JFS 的电信级硬件

我们的 Linux 系统旨在服务于基于短事务的请求。JFS 提供了一种基于日志的字节级文件系统,目标是面向事务的系统,这使其非常适合我们的系统类型。

从电信的角度来看,JFS 的优势在于它提供了改进的结构一致性、可恢复性以及比非日志文件系统(如传统 UNIX 文件系统)快得多的重启时间。在大多数情况下,其他文件系统在系统崩溃时容易损坏。它们依赖于重启时实用程序(如 fsck),这些实用程序检查文件系统的所有元数据以检测和修复结构完整性问题。这是一个耗时且容易出错的过程;在最坏的情况下,它可能会丢失或错放数据。电信平台无法承受延长系统停机时间的过程。

使用 JFS,在系统发生故障的情况下,可以通过重放日志并应用相应事务的日志记录,将文件系统恢复到一致状态。与基于日志的方法相关的恢复时间要快得多,因为重放实用程序仅检查最近文件系统活动生成的日志记录,而不是检查所有文件系统元数据。

日志文件系统的要求

结论

JFS 是服务器的关键技术,因为它在系统崩溃时提供快速的文件系统重启时间。JFS 团队最重要的目标是创建一个可靠、高性能的文件系统。JFS 团队在将 JFS 移植到 Linux 方面取得了巨大进展。从性能的角度来看,并且基于各种已发布的基准测试,JFS 脱颖而出。要参与其中,请访问 developerWorks 上的 JFS 项目页面。

致谢

感谢爱立信研究开放系统实验室对我们使用 Linux 和开源软件的工作的支持。

资源

Steve Best (sbest@us.ibm.com) 在德克萨斯州奥斯汀的 IBM Linux 技术中心工作。他目前正在从事 Linux 项目的日志文件系统。Steve 在操作系统开发方面做了大量工作,重点领域是文件系统、国际化和安全。

David Gordon (gordd00@dmi.usherb.ca) 即将完成他在加拿大魁北克省舍布鲁克大学的计算机科学学士学位。他是蒙特利尔爱立信研究实验室的合作学生。

Ibrahim Haddad (Ibrahim.Haddad@Ericsson.com) 是加拿大蒙特利尔爱立信公司研究部门的研究员。他参与了第三代无线 IP 网络的系统架构。Ibrahim 代表爱立信参加开源开发实验室 (OSDL) 的技术子组。他目前是康考迪亚大学的理学博士候选人。

加载 Disqus 评论