系统管理指南:网络服务

NFS 版本 4 的功能

NFS 版本 4 已进行了许多更改。本节提供了这些新增功能的说明。


注 –

从 Solaris 10 发行版开始,NFS 版本 4 不支持 LIPKEY/SPKM 安全特性。另外,NFS 版本 4 也不会使用 mountdnfslogdstatd 守护进程。


有关与使用 NFS 版本 4 相关的过程信息,请参阅设置 NFS 服务

在 NFS 版本 4 中取消共享和重新共享文件系统

如果同时使用 NFS 版本 3 和版本 4,则客户机尝试访问一个已经取消共享的文件系统时,服务器会以错误代码响应。但是,如果使用 NFS 版本 3,则服务器会保留客户机在取消共享文件系统之前所获取的任何锁定。 这样,重新共享文件系统时,NFS 版本 3 客户机即可访问此文件系统,就好像从未取消共享此文件系统一样。

如果使用 NFS 版本 4,则取消共享文件系统时,将破坏此文件系统中任何打开的文件或文件锁定的所有状态。如果客户机尝试访问这些文件或锁定,则会收到一条错误消息。通常会将此错误消息作为 I/O 错误报告给应用程序。但是请注意,通过重新共享当前共享的文件系统来更改选项不会破坏服务器上的任何状态。

有关信息,请参阅NFS 版本 4 中的客户机恢复或参见 unshare_nfs(1M) 手册页。

NFS 版本 4 中的文件系统名称空间

NFS 版本 4 服务器可创建并维护一个伪文件系统,此系统使客户机能够对服务器上所有导出的对象进行无缝访问。在 NFS 版本 4 之前,不存在伪文件系统。那时的客户机会强制挂载每个共享服务器文件系统来进行访问。请参考以下示例。

图 6–2 服务器文件系统和客户机文件系统的视图

文中对该图形进行了说明。

请注意,客户机无法看到 payroll 目录和 nfs4x 目录,因为这些目录未被导出,也没有通向导出目录。但是,客户机可以看到 local 目录,因为 local 是一个导出的目录。客户机还可看到 projects 目录,因为 projects 通向导出目录 nfs4。因此,未显式导出的服务器名称空间部分会与伪文件系统桥接,该系统仅显示导出目录和那些通向服务器导出目录的目录。

伪文件系统是服务器创建的仅包含目录的结构。 伪文件系统允许客户机浏览导出文件系统的分层结构。因此,客户机的伪文件系统视图限制为仅显示通向导出文件系统的路径。

以前的 NFS 版本不允许客户机在未挂载每个文件系统的情况下遍历服务器文件系统。 但是,在 NFS 版本 4 中,服务器名称空间可进行以下操作:

由于与 POSIX 相关的原因,Solaris NFS 版本 4 客户机不会跨越服务器的文件系统边界。如果尝试进行这类操作,则客户机会使目录显示为空。要修正这种情况,必须针对每个服务器的文件系统执行挂载。

NFS 版本 4 中的可变文件句柄

文件句柄是在服务器上创建的,其中包含唯一标识文件和目录的信息。在 NFS 版本 2 和 3 中,服务器会返回持久性文件句柄。这样,客户机即可确保服务器会生成始终引用同一文件的文件句柄。例如:

因此,当服务器从客户机收到包括文件句柄的请求时,解决方案会非常简单,并且文件句柄会始终引用正确的文件。

这种为 NFS 操作标识文件和目录的方法对大多数基于 UNIX 的服务器都很有效。但是,此方法不能在依赖其他标识方法(如文件的路径名)的服务器上实现。为了解决此问题,NFS 版本 4 协议允许服务器声明其文件句柄为可变句柄。这样,即可更改文件句柄。如果文件句柄确实已更改,则客户机必须找到新的文件句柄。

与 NFS 版本 2 和 3 一样,Solaris NFS 版本 4 服务器始终提供持久性文件句柄。但是,访问非 Solaris NFS 版本 4 服务器的 Solaris NFS 版本 4 客户机必须在服务器使用可变文件句柄时支持这些句柄。具体来说,当服务器通知客户机文件句柄可变时,客户机必须高速缓存路径名和文件句柄之间的映射。客户机会一直使用可变文件句柄,直到句柄过期为止。句柄过期后,客户机会执行以下操作:


注 –

服务器会始终通知客户机哪些文件句柄为持久性句柄,哪些文件句柄为可变句柄。


可变文件句柄可能会由于以下任一原因过期:

请注意,如果客户机无法找到新的文件句柄,则会在 syslog 文件中放入一条错误消息。进一步尝试访问此文件会失败,并显示 I/O 错误。

NFS 版本 4 中的客户机恢复

NFS 版本 4 协议为有状态协议。如果客户机和服务器都保留有关以下内容的当前信息,协议即为有状态协议。

出现故障(如服务器崩溃)时,客户机和服务器会协同工作,以重新建立故障之前已存在的打开状态和锁定状态。

服务器崩溃并重新引导时,会丢失其状态。客户机检测到服务器已经重新引导后,将启动帮助服务器重建其状态的进程。此进程称为客户机恢复,因为它是由客户机引导执行的。

客户机发现服务器已经重新引导后,便会立即暂停其当前活动并启动客户机恢复进程。启动恢复进程时,系统错误日志 /var/adm/messages 中会显示如下消息。


NOTICE: Starting recovery server basil.example.company.com

在恢复进程中,客户机会向服务器发送有关客户机以前状态的信息。但是请注意,在此期间,客户机不会向服务器发送任何新请求。 任何打开文件或设置文件锁定的新请求都必须等到服务器完成其恢复期之后才能继续进行。

客户机恢复进程完成时,系统错误日志 /var/adm/messages 中会显示以下消息。


NOTICE: Recovery done for server basil.example.company.com

现在,客户机已经成功地将其状态信息发送给服务器。 不过,尽管此客户机已经完成了此进程,但是其他客户机可能尚未完成将其状态信息发送给服务器的进程。 因此,在一段时间内,服务器不会接受任何打开或锁定请求。指定这段时间(称为宽延期)旨在允许所有客户机完成其恢复。

在宽延期内,如果客户机尝试打开任何新文件或建立任何新锁定,服务器都会拒绝请求并显示 GRACE 错误代码。收到此错误后,客户机必须等到宽延期结束,然后才能向服务器重新发送请求。 在宽延期内,会显示以下消息。


NFS server recovering

请注意,在宽延期内,可以继续执行不打开文件或设置文件锁定的命令。 例如,命令 lscd 不会打开文件或设置文件锁定。因此,这些命令不会暂停执行。但是,cat 之类可打开文件的命令会暂停执行,直到宽延期结束为止。

宽延期结束后,会显示以下消息。


NFS server recovery ok.

现在,客户机即可向服务器发送新的打开和锁定请求。

客户机恢复会因为各种原因而失败。例如,如果服务器重新引导后存在网络分区,则客户机可能无法在宽延期结束之前在服务器上重新建立其状态。 宽延期结束后,服务器不允许客户机重新建立其状态,因为新的状态操作可能会产生冲突。例如,新的文件锁定可能会与客户机尝试恢复的旧的文件锁定发生冲突。发生这种情况时,服务器会将 NO_GRACE 错误代码返回到客户机。

如果恢复某个特定文件的打开操作失败,客户机会将此文件标记为不可用,并显示以下消息。


WARNING: The following NFS file could not be recovered and was marked dead 

(can't reopen:  NFS status 70):  file :  filename

请注意,数字 70 仅是一个示例。

如果在恢复过程中重新建立文件锁定失败,则会显示以下错误消息。


NOTICE: nfs4_send_siglost:  pid PROCESS-ID lost

lock on server SERVER-NAME

在这种情况下,会向进程发送 SIGLOST 信号。SIGLOST 信号的缺省操作是终止此进程。

要从此状态恢复,必须重新启动所有在失败时打开文件的应用程序。请注意,可能会出现以下情况。

因此,一些进程可以访问其他进程无法访问的特定文件。

NFS 版本 4 中的 OPEN 共享支持

NFS 版本 4 协议提供了几种文件共享模式,客户机可以使用这些模式控制其他客户机对文件的访问。客户机可以指定以下内容:

Solaris NFS 版本 4 服务器完全实现了这些文件共享模式。因此,如果客户机尝试打开文件的方式与当前共享模式冲突,则服务器会通过使操作失败来拒绝此尝试。如果这类尝试在打开或创建操作开始时失败,则 Solaris NFS 版本 4 客户机会接收到一条协议错误消息。此错误会映射为应用程序错误 EACCES

尽管此协议提供了几种共享模式,但目前 Solaris 中的打开操作不提供多种共享模式。打开文件时,Solaris NFS 版本 4 客户机只能使用 DENY_NONE 模式。

另外,尽管 Solaris fcntl 系统调用使用 F_SHARE 命令来控制文件共享,但是 fcntl 命令无法在 NFS 版本 4 中正常实现。如果在 NFS 版本 4 客户机上使用这些 fcntl 命令,则客户机会向应用程序返回一条 EAGAIN 错误消息。

NFS 版本 4 的委托

NFS 版本 4 为委托同时提供客户机支持和服务器支持。委托是服务器用于将文件管理委托给客户机的一种技术。例如,服务器可以授予客户机读取委托或写入委托。读取委托可以同时授予多台客户机,因为这些读取委托不会彼此冲突;写入委托只能授予一台客户机,因为写入委托会与其他任何客户机的任何文件访问相冲突。 虽然客户机拥有写入委托,但是它不会向服务器发送各种操作,因为客户机保证具有对文件的独占访问权限。同样,客户机在拥有读取委托时也不会向服务器发送各种操作。这是因为服务器保证任何客户机都不能以写入模式打开文件。通过委托,可显著减少服务器和客户机之间针对被委托文件的交互。因此,可降低网络通信量,并且提高客户机和服务器的性能。但是请注意,性能提高的程度取决于应用程序使用的文件交互的类型和网络和服务器的拥塞量。

是否授予委托完全由服务器决定。客户机不会请求委托。服务器可根据文件的访问模式来决定是否授予委托。如果几台不同的客户机最近以写入模式访问了文件,则服务器可能不会授予委托。原因是此访问模式表明将来可能会发生冲突。

当客户机访问文件的方式与当前授予此文件的委托不一致时,便会发生冲突。例如,如果一台客户机拥有对文件的写入委托,同时另一台客户机打开此文件来进行读取或写入访问,则服务器会撤销第一台客户机的写入委托。同样,如果一台客户机拥有读取委托,同时另一台客户机打开同一个文件进行写入,则服务器会撤销读取委托。请注意,在这两种情况下都不会将委托授予第二台客户机,因为此时存在冲突。发生冲突时,服务器会使用回叫机制来访问当前拥有委托的客户机。收到此回叫后,客户机会向服务器发送文件的更新状态并返回委托。如果客户机无法对回叫做出响应,则服务器会撤销委托。在这些情况下,服务器会拒绝客户机对此文件进行的所有操作,客户机将已请求的操作报告为失败。通常,这些失败作为 I/O 错误报告给应用程序。 要从这些错误中恢复,必须关闭文件,然后再重新打开。当客户机和服务器之间存在网络分区并且客户机拥有委托时,撤销委托会失败。

请注意,一台服务器不能解决对其他服务器上存储的文件的访问冲突。因此,NFS 服务器仅解决它自己存储的文件的冲突。此外,要响应由运行各种 NFS 版本的客户机导致的冲突,NFS 服务器只能对运行 NFS 版本 4 的客户机启动回叫机制。NFS 服务器不能对运行较早 NFS 版本的客户机启动回叫机制。

检测冲突的进程会有所变化。例如,与 NFS 版本 4 不同,因为版本 2 和版本 3 不包括打开过程,所以仅会在客户机尝试读取、写入或锁定文件之后检测冲突。服务器对这些冲突的响应也会有所不同。 例如:

解决了委托冲突之后,便不会存在这些情况。

缺省情况下,会启用服务器委托。可以通过修改 /etc/default/nfs 文件来禁用委托。有关过程信息,请参阅如何在服务器上选择不同版本的 NFS

客户机委托不需要任何关键字。NFS 版本 4 回叫守护进程 nfs4cbd 在客户机上提供了回叫服务。只要启用对 NFS 版本 4 的挂载,此守护进程就会自动启动。缺省情况下,客户机会针对 /etc/netconfig 系统文件中列出的所有 Internet 传输向服务器提供必需的回叫信息。请注意,如果在客户机上启用了 IPv6 并且可以确定客户机名称的 IPv6 地址,则回叫守护进程可接受 IPv6 连接。

回叫守护进程使用临时的程序编号以及动态指定的端口号。 此信息提供给服务器,服务器会在授予任何委托之前测试回叫路径。如果回叫路径测试不成功,则服务器不会授予委托,这是唯一可从外部看到的行为。

请注意,因为回叫信息嵌在 NFS 版本 4 请求中,所以服务器不能通过使用网络地址转换 (Network Address Translation, NAT) 的设备来访问客户机。 另外,回叫守护进程还会使用动态端口号。因此,即使防火墙在端口 2049 上启用了正常的 NFS 流量,服务器可能仍然无法穿越防火墙。在这种情况下,服务器不会授予委托。

NFS 版本 4 中的 ACL 和 nfsmapid

访问控制列表 (access control list, ACL) 通过使文件的属主可以为文件属主、组以及其他特定用户和组定义文件权限来提供更好的文件安全性。ACL 是使用 setfacl 命令在服务器和客户机上设置的。请参见 setfacl(1) 手册页。在 NFS 版本 4 中,ID 映射器 nfsmapid 用于将服务器上的 ACL 项中的用户 ID 或组 ID 映射为客户机上的 ACL 项中的用户 ID 或组 ID。反之也能实现。ACL 项中的用户 ID 和组 ID 必须同时存在于客户机和服务器上。

ID 映射失败的原因

以下情况可能导致 ID 映射失败:

避免 ACL 出现 ID 映射问题

为避免 ID 映射问题,请执行以下操作:

检查未映射的用户 ID 或组 ID

要确定是否有无法在服务器或客户机上映射的用户或组,请使用以下脚本:


#! /usr/sbin/dtrace -Fs



sdt:::nfs4-acl-nobody

{

     printf("validate_idmapping: (%s) in the ACL could not be mapped!", 

stringof(arg0));

}

注 –

此脚本中使用的探测器名称是一个接口,该接口以后可以更改。有关更多信息,请参见《Solaris 动态跟踪指南》中的“稳定性级别”


有关 ACL 或 nfsmapid 的其他信息

请参见以下内容: