我如何获取 NFS 文件句柄并导出其完全限定路径并提取文件的属性?

How do I take an NFS file handle, and derive its fully-qualified path and extract the attributes of the file?

这开始于 a more general question in r/linux_programming,但看到那里没有回复我想问一个更基本的问题。

一旦我有了一个 NFS 文件句柄(为了讨论起见,我已经计算出即使在 NFSv4 中的易失性文件句柄下它也是一个有效的文件句柄),是否有一系列库调用来完全导出它-合格的路径? kernel documentation on just local filesystem path lookup, and an old paper on a proposed NFS path lookup scheme change 让我确信这不是我想要自己编写的代码。

通过文档和源代码,到目前为止,我怀疑代码必须位于 VFS 和 NFS 文件系统设备驱动程序代码库之一或两者之间。但我一定没有理解 VFS、NFS 和内核之间的相互关系,因为我一直无法找到如何弥合 NFS 文件句柄和我们在 shell 中习惯看到的路径之间的差距。关于用户空间中的 open(2) 调用转换为 VFS 中的 vnode,并从那里转换为 NFS 文件句柄的讨论,但我正在尝试相反的方向(因为 FS-Cache 将 NFS 文件句柄存储为正如我从阅读 NFS 源代码中得知的那样接近,而不是可以传递给 open(2)).

的路径值

与此相关的是如何获取文件属性,如所有权、权限、日期等,如果我有一个 NFS 文件句柄,并且该文件缓存在 FS-Cache 中。我想我可以获取 inode,然后以这种方式获取属性,但我试图避免必须访问 NFS 并留在 FS-Cache 中,尤其是避免对 inode 执行 find(1)。

tl;博士:nfs_fhget() -> d_obtain_alias() -> d_absolute_path().

您将需要 struct vfsmount 来描述已安装的文件系统。


免责声明:此处的假设是您从 fs-cache 获得文件句柄,即它是原始 NFS 文件句柄,而不是您从 name_to_handle_at(2) 之类的东西获得的 struct fid .

句柄来源

如果您从 handle fairy 那里得到这个 handle,即没有先前的上下文,那么客户端无法将它映射到路径。事实上,服务器可能也无法将其映射到没有 find(1).

的路径中

就像 inode 一样,它在文件系统中可以有多个路径,在挂载树中可以有多个该文件系统的挂载点。

但是假设您通过文件名查找获得了这个句柄,dcache 将包含指向一个 inode 的目录,其中将有一个 i_private 指向该文件句柄。 inode 还将在 i_dentry.

中包含其缓存的目录列表

同样,挂载树可能多次挂载相同的 NFS bind-mounted。

正在查找 VFS inode

因为你有一个原始的 NFS 文件句柄,我们从 NFS 层开始,使用 nfs_fhget().

将文件句柄映射到 inode。

如果 inode 不在缓存中,nfs_fhget() 将只是 return 一个空白的 NFS inode。这可以通过在 fattr 参数的内容中放置一些有趣的值来检测。

fattr 有一些要求,请参阅 nfs_find_actor()

但是一旦你成功了,你就完成了 NFS 层并且你有一个 VFS inode。

returned inode 还具有所有其他信息,如 inode 权限、所有权、日期等。

获取VFS dentry

有了 inode 后,您需要一个指向它的 dentry。

这是由 d_obtain_alias() 完成的。

nfs_fhget() 一样,如果缓存中没有 dentry,d_obtain_alias() 也不会失败。相反,它将创建一个“匿名 dentry”,即没有实际名称的 dentry。在这种情况下,它的名称,相对于挂载点,只是 /.

正在将 VFS 数据结构转换为路径

假设你有 struct vfsmount 并且现在你有 dentry,你可以构建一个你有一个 struct path.

有了 struct path,您现在可以调用 d_absolute_path(),最终 return 成为绝对路径。