ext4 在 name_to_handle_at() 中会使用 i_generation 吗?
会。通过 name_to_handle_at() 为 ext4 文件生成句柄时,目标 inode 的 i_generation 会被编入句柄。以 Linux v6.6 为例,默认编码函数中有 fid->i32.gen = inode->i_generation 这一赋值。编码源码
i_generation 是在哪一步写入的?
name_to_handle_at() 解析路径后,通过 exportfs_encode_fh() 进入文件句柄编码流程。具体的字段布局由文件系统的导出操作和相关通用实现决定。系统调用源码
在 Linux v6.6 中,ext4 的 ext4_export_ops 没有提供 .encode_fh 回调,因此 exportfs_encode_inode_fh() 会使用默认的 export_encode_fh()。调用路径可以概括为:
name_to_handle_at()
-> do_sys_name_to_handle()
-> exportfs_encode_fh()
-> exportfs_encode_inode_fh()
-> export_encode_fh()
ext4 的回调定义可见 ext4 super.c,默认编码逻辑可见 exportfs expfs.c。
内核源码中的赋值如下:
fid->i32.ino = inode->i_ino;
fid->i32.gen = inode->i_generation;
句柄中因此包含 inode 编号和 generation。在该版本的默认格式中,不携带父目录信息的句柄类型为 FILEID_INO32_GEN,有效载荷是两个 32 位字段,共 8 字节。默认编码实现
为什么需要 generation?
inode 编号可能被重新分配。解码句柄时,generation 可以辅助判断找到的 inode 是否仍是句柄原先指向的对象。
Linux v6.6 的 ext4_nfs_get_inode() 会将传入的非零 generation 与当前 inode 的 i_generation 比较;如果两者不一致,就返回 -ESTALE。generation 为零时,代码会跳过这项比较,因此不能认为它在任何情况下都能保证标识的唯一性。ext4 解码校验源码
如何核对自己的内核版本?
要确认正在使用的内核如何处理,可以按以下顺序检查对应版本的源码:
- 在
fs/fhandle.c中找到name_to_handle_at()调用的编码入口。 - 检查 ext4 的
ext4_export_ops是否设置了.encode_fh。 - 跟踪实际编码函数,确认是否写入
inode->i_generation。
上述函数名和默认回退关系以 Linux v6.6 为例,其他版本可能调整代码组织。应用程序应将返回的文件句柄作为不透明数据保存和传递,不宜将这里展示的内部布局视为适用于所有文件系统和内核版本的解析格式。
备注:内容仅供参考。
