本页目录
NFS (Network File System)
覆盖: NFSv3/v4 协议 → SUNRPC 层 → client/server 架构 → caching (attribute/delegation) → pNFS → Kerberos 安全 → nfsd 内核版本: 2.6 ~ 6.x
概述
NFS 是 Unix/Linux 最传统的网络文件系统。NFSv4 (2003) 是对 v3 的重大重写:引入了状态 (locking + delegation)、复合操作 (compound RPC)、伪文件系统 (pseudo-fs) 和更好的安全模型。
Linux NFS 实现分为两个独立模块:
- nfsd (server,
fs/nfsd/): 导出本地文件系统到网络 - nfs (client,
fs/nfs/): 挂载远程文件系统
SUNRPC 层
NFS 使用 SUNRPC (ONC RPC) 作为传输层:
// net/sunrpc/
// RPC 客户端: 发送请求 → 等待应答
;
// RPC 传输:
// TCP (默认): 可靠, 内建流量控制
// UDP: 轻量但有丢包风险 (v3 only)
// RDMA: 高性能 (InfiniBand/RoCE)
NFS Client
挂载与伪文件系统
NFSv3 mount:
mount -t nfs server:/export/path /mnt
→ MOUNT protocol (portmapper) 获取初始 filehandle
→ 后续操作用 NFS protocol (port 2049)
NFSv4 mount:
mount -t nfs4 server:/ /mnt
→ 伪文件系统: 服务端导出根, 客户端通过遍历到达子导出
→ 不需要辅助的 MOUNT 协议
→ /etc/exports 的 fsid=0 标记 root export
Attribute Cache
// NFS 客户端缓存文件属性 (stat, permission 等)
// 属性缓存时间由 acregmin/acregmax/acdirmin/acdirmax 控制
// close-to-open consistency:
// 这是 NFS 的默认一致性模型:
// 1. open() → 强制重新验证属性 (GETATTR)
// 2. 未打开的文件: 属性在缓存期内复用
// 3. close() → 回写所有修改
// 4. 另一个客户端 open 同一个文件 → 看到完整的修改
// NFSv4 delegation (委托):
// 服务端可以把文件的读写权"委托"给客户端
// 客户端独占读/写 → 本地缓存属性 + 数据 → 零 RPC!
// 另一个客户端想访问 → 服务端先 revoke 委托 → 第一个客户端刷新回服务端
// 类似分布式系统中的 lease 机制
Page Cache 与回写
NFS 客户端的 page cache:
读: page cache 命中 → 不发起 RPC → 本地服务
写: 先写 page cache → 异步 WRITE RPC → 后台回写
NFS COMMIT:
fsync → COMMIT RPC → 服务端确保写入稳定存储
→ 服务端可能用 NFS write delegation 加速
NFSv4.1+ pNFS (Parallel NFS):
元数据走 MDS (Metadata Server)
数据直接走 DS (Data Server)
→ 绕过 MDS 的带宽瓶颈
NFS Server (nfsd)
// fs/nfsd/
// 内核 NFS server: nfsd 内核线程池
// 导出文件系统:
// /etc/exports:
// /export *(rw,sync,no_subtree_check)
// exportfs -a → 通知内核
// nfsd 线程:
// 每个 CPU 有一个 nfsd 内核线程
// nfsd 循环: 取 RPC 请求 → 执行 NFS 操作 → 返回应答
// 线程数: /proc/fs/nfsd/threads
// NFSv4 state:
// 服务端维护 client 状态 (open files, locks, delegations)
// 状态存储: 在 /var/lib/nfs/nfsdcltrack (或 v4.2+ 基于文件系统)
// 客户端崩溃 → state 在 lease 时间后自动回收
安全模型
NFSv3:
基于 AUTH_SYS (UNIX credential: uid/gid/aux gids)
→ 信任客户端提供的 uid/gid (不安全!)
→ root_squash 缓解 (把 root 映射为 nobody)
→ sec=sys (默认), sec=krb5 (可选)
NFSv4:
支持 Kerberos 5 (RPCSEC_GSS)
sec=krb5: 仅认证
sec=krb5i: 认证 + 完整性 (防止篡改, 签名)
sec=krb5p: 认证 + 完整性 + 隐私 (加密数据)
强制要求: NFSv4.2+ 服务器支持 sec=krb5
TASK_KILLABLE 与 NFS
// NFS 是 TASK_KILLABLE 引入的主要动机之一
// 经典问题: 挂载了 NFS 但服务器不可达
// → 进程访问 NFS 挂载点 → 进入 TASK_UNINTERRUPTIBLE (D 状态)
// → SIGKILL 无效 (D 状态不响应信号!)
// → 只能重启
//
// TASK_KILLABLE 的解决 (5.x+):
// 某些等待路径使用 wait_event_killable()
// → 等待时检查 fatal_signal_pending()
// → SIGKILL 可以打断
// 但不是所有 NFS 路径都改成了 KILLABLE
调试
# NFS client 统计
# NFS server 统计
# 查看 NFS 挂载选项
|
|
# 追踪 NFS RPC
参考与延伸
- 内核文档:
Documentation/filesystems/nfs/ - RFC: RFC 7530 (NFSv4), RFC 5661 (NFSv4.1/pNFS), RFC 7862 (NFSv4.2)
- 源码:
fs/nfs/— client 实现fs/nfsd/— server 实现net/sunrpc/— RPC 层include/linux/sunrpc/— RPC 类型定义
关键词: NFSv4, SUNRPC, delegation, close-to-open, pNFS, nfsd, TASK_KILLABLE, Kerberos, RPCSEC_GSS