【linux3.10】【nfs】使文件系统可导出
2021/9/6 7:08:32
本文主要是介绍【linux3.10】【nfs】使文件系统可导出,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
原文链接:
Exporting
概述
所有的文件系统操作都需要一个dentry(或者两个)作为起始点。本地应用程序通过打开的文件描述符或 cwd/root 对合适的 dentry 进行引用计数保留。然而,通过远程文件系统协议(如 NFS)访问文件系统的远程应用程序可能无法保存这样的引用,因此需要一种不同的方式来引用特定的 dentry。由于替代的引用形式需要在重命名、截断和服务器重启时保持稳定(除其他外,尽管这些往往是最有问题的),因此没有像“文件名”这样的简单答案。
此处讨论的机制允许每个文件系统实现指定如何为任何 dentry 生成不透明(文件系统之外)字节字符串,以及如何为任何给定的不透明字节字符串找到合适的 dentry。
这个字节串将被称为“文件句柄片段”,因为它对应于 NFS 文件句柄的一部分。
支持文件句柄片段和 dentries 之间映射的文件系统将被称为“可导出”。
dcache问题
dcache 通常包含任何给定文件系统树的适当前缀。 这意味着如果任何文件系统对象在 dcache 中,那么该文件系统对象的所有祖先也在 dcache 中。 由于正常访问是通过文件名,这个前缀是自然创建的并且很容易维护(通过每个对象在其父对象上维护一个引用计数)。
但是,当通过解释文件句柄片段将对象包含到 dcache 中时,不会自动为对象创建路径前缀。 这导致了dcache两个相关但不同的功能,而这是正常访问文件系统所不需要的。
- dcache 有时必须包含不属于正确前缀的对象。 即没有连接到根。
- dcache 必须为新发现的(通过 ->lookup)目录准备好(未连接的)dentry,并且必须能够将该 dentry 移动到位(基于 ->lookup 中的父级和名称) . 这对于目录尤其需要,因为目录只有一个 dentry 是 dcache 不变的。
为了实现这额功能,dcache需要:
- 一个 dentry 标志 DCACHE_DISCONNECTED,它被设置在任何可能不是正确前缀的一部分的 dentry 上。这在创建匿名 dentry 时设置,并在知道 dentry 是正确前缀中的 dentry 的子项时清除。 如果设置了此标志的 dentry 上的 refcount 变为零,则立即丢弃该 dentry,而不是保留在 dcache 中。 如果文件句柄重复访问不在 dcache 中的 dentry(如 NFSD 可能会这样做),则将为每次访问分配一个新的 dentry,并在访问结束时丢弃。
请注意,这样的 dentry 可以在不清除 DCACHE_DISCONNECTED 的情况下获取children、name、parent等 - 只有当子树成功重新连接到根时才会清除该标志。 在此之前,只有在存在引用时才会保留此类子树中的 dentry; refcount 达到零意味着立即清理,与未散列的 dentry 相同。 这保证了我们不需要在 umount 上定位它们。 - 用于创建次根的原语 - d_obtain_root(inode)。那些不设置DCACHE_DISCONNECTED。 它们被放置在 per-superblock 列表 (->s_roots) 中,因此它们可以在 umount 时定位以进行驱逐。
- 帮助程序分配匿名目录,并帮助在查找时附加松散的目录项。 他们是:
d_obtain_alias(inode) 将返回给定 inode 的 dentry。 如果 inode 已经有一个 dentry,则返回其中一个。如果没有,则会分配并附加一个新的匿名(IS_ROOT 和 DCACHE_DISCONNECTED)dentry。如果是目录,注意只能附加一个 dentry。
d_splice_alias(inode, dentry) 将在树中引入一个新的 dentry; 或是给定的 dentry ,或是给定 inode 的已经存在的别名(例如由 d_obtain_alias 创建的匿名别名)。 当使用给定的 dentry 时,它返回 NULL,遵循 ->lookup 的调用约定。
文件系统问题
对一个需要可导出的文件系统,它必须:
- 提供下方描述的文件句柄片段的程序
- 当调用lookup为一个给定的parent和name寻找inode时,需要保证使用d_splice_alias 而不是d_add。如果inode时NULL,d_splice_alias(inode, dentry) 等同于d_add(dentry, inode), NULL。类似地,d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err)。通常,lookuop程序将简单地用
return d_splice_alias(inode, dentry);
来结束。
文件系统实现通过在 struct super_block
中设置 s_export_op
字段来声明文件系统的实例是可导出的。 此字段必须指向具有以下成员的“struct export_operations”结构:
encode_fh (可选)
获取一个 dentry 并创建一个文件句柄片段,稍后可用于为同一对象查找或创建一个 dentry。默认实现会创建一个文件句柄片段,该片段会根据 32 位 inode 和已编码的 inode 的生成编号进行编码,并在必要时为父级提供相同的信息。
fh_to_dentry (必选)
给定一个文件句柄片段,这应该找到隐含的对象并为其创建一个 dentry(可能使用 d_obtain_alias)。
fh_to_parent (可选但强烈推荐)
给定一个文件句柄片段,这应该找到隐含对象的父级并为其创建一个 dentry(可能使用 d_obtain_alias)。 如果文件句柄片段太小,可能会失败。
get_parent (可选但强烈推荐)
当给定一个目录的 dentry 时,这应该返回父目录的 dentry。 很可能父 dentry 已由 d_alloc_anon 分配。 默认的 get_parent 函数只返回一个错误,因此任何需要查找父级的文件句柄查找都将失败。
->lookup("…") 不用作默认值,因为它可以在 dcache 中留下“…”条目,这些条目太混乱而无法使用。
get_name (可选)
当给定一个父 dentry 和一个子 dentry 时,这应该在由父 dentry 标识的目录中找到一个名称,这会找到由子 dentry 标识的对象。 如果未提供 get_name 函数,则提供默认实现,该实现使用 vfs_readdir 查找潜在名称,并匹配 inode 编号以查找正确匹配项。
文件句柄片段由 1 个或多个 4 字节字的数组以及一个 1 字节的“类型”组成。
decode_fh 例程不应依赖于传递给它的规定大小。 这个大小可能比encode_fh 生成的原始文件句柄大,在这种情况下,它将用空值填充。 相反,encode_fh 例程应该选择一个“类型”,它指示 decode_fh 文件句柄有多少是有效的,以及应该如何解释它。
这篇关于【linux3.10】【nfs】使文件系统可导出的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-18git仓库有更新,jenkins 自动触发拉代码怎么配置的?-icode9专业技术文章分享
- 2024-12-18Jenkins webhook 方式怎么配置指定的分支?-icode9专业技术文章分享
- 2024-12-13Linux C++项目实战入门教程
- 2024-12-13Linux C++编程项目实战入门教程
- 2024-12-11Linux部署Scrapy教程:新手入门指南
- 2024-12-11怎么将在本地创建的 Maven 仓库迁移到 Linux 服务器上?-icode9专业技术文章分享
- 2024-12-10Linux常用命令
- 2024-12-06谁看谁服! Linux 创始人对于进程和线程的理解是…
- 2024-12-04操作系统教程:新手入门及初级技巧详解
- 2024-12-04操作系统入门:新手必学指南