10.3. 在 NFS 中使用缓存
除非明确指示,否则 NFS 将不会使用缓存。要将 NFS 挂载配置为使用 FS-Cache,请在 mount 命令中包含 -o fsc 选项:
# mount nfs-share:/ /mount/point -o fsc
对 /mount/point 下文件的所有访问都将通过缓存,除非打开该文件以进行直接 I/O 或写入。如需更多信息,请参阅 第 10.3.2 节 “使用 NFS 的缓存限制”。NFS 使用 NFS 文件句柄 而不是 文件名来索引缓存内容,这意味着硬链接的文件可以正确共享缓存。
NFS 版本2、3 和 4 支持缓存。但是,每个版本使用不同的分支进行缓存。
10.3.1. 缓存共享
与 NFS 缓存共享相关的一些潜在问题。因为缓存是持久的,所以缓存中的数据块会根据由四个键组成的序列来索引的:
- 第 1 级:服务器详情
- 第 2 级:一些挂载选项;安全类型;FSID;uniquifier
- 第 3 级:文件处理
- 第 4 级:文件中的页号
为避免超级块之间一致性管理问题,希望缓存数据的所有 NFS 超级块都具有唯一的第 2 级密钥。通常,两个 NFS 挂载使用相同的源卷和选项共享超级块,因此共享缓存,即使它们在该卷中挂载不同的目录。
例 10.1. 缓存共享
使用以下两个 mount 命令:
mount home0:/disk0/fred /home/fred -o fsc
mount home0:/disk0/jim /home/jim -o fsc
在这里,
/home/fred
和 /home/jim
可能会共享超级块,因为它们具有相同的选项,特别是当它们来自 NFS 服务器(home
0)上的相同卷/分区时。现在,考虑接下来的两个挂载命令:
mount home0:/disk0/fred /home/fred -o fsc,rsize=230
mount home0:/disk0/jim /home/jim -o fsc,rsize=231
在这种情况下,
/home/fred
和 /home/jim
不会共享超级块,因为它们具有不同的网络访问参数,这些参数是第 2 级密钥的一部分。以下的挂载序列也是如此:
mount home0:/disk0/fred /home/fred1 -o fsc,rsize=230
mount home0:/disk0/fred /home/fred2 -o fsc,rsize=231
此处,两个子树的内容(
/home/fred1
和 /home/fred2)
将缓存 两次。
避免超级块共享的另一种方法是使用 nosharecache 参数显式阻止它。使用相同的示例:
mount home0:/disk0/fred /home/fred -o nosharecache,fsc
mount home0:/disk0/jim /home/jim -o nosharecache,fsc
然而,在这种情况下,只允许其中一个超级块使用缓存,因为无法区分
home0:/disk0/fred
和 home0:/disk0/jim
的第 2 级密钥。要解决这个问题,请在至少一个挂载上添加一个 唯一标识符,即 fsc=unique-identifier。例如:
mount home0:/disk0/fred /home/fred -o nosharecache,fsc
mount home0:/disk0/jim /home/jim -o nosharecache,fsc=jim
在这里,唯一标识符 jim 添加到
/home/jim
缓存中使用的第 2 级键中。
10.3.2. 使用 NFS 的缓存限制
- 为直接 I/O 打开共享文件系统的文件将自动绕过缓存。这是因为这种访问类型必须与服务器直接进行。
- 打开共享文件系统的文件进行写入不适用于 NFS 版本 2 和 3。这些版本的协议无法为客户端提供足够的一致性管理信息,来检测另一客户端对同一文件的并发写入。
- 从共享文件系统打开一个文件直接 I/O 或写入清除文件缓存的副本。FS-Cache 不会再次缓存文件,直到它不再为直接 I/O 或写操作而打开。
- 另外,FS-Cache 的这个发行版本只缓存常规 NFS 文件。FS-Cache 不会 缓存目录、符号链接、设备文件、FIFO 和套接字。