我发现在大多数情况下,i_data只是i_mapping的解引用数据,如下所示,为什么在一个inode结构中设置两个相同的值?
crash> struct inode ffffffc073c1f360 -o
struct inode {
...
[ffffffc073c1f4a8] struct file_lock *i_flock;
**[ffffffc073c1f4b0] struct address_space i_data;**
[ffffffc073c1f558] struct list_head i_devices;
...
crash> struct inode ffffffc073c1f360
struct inode {
...
i_op = 0xffffffc0007ad1c0 <ext4_file_inode_operations>,
i_sb = 0xffffffc002010000,
**i_mapping = 0xffffffc073c1f4b0,**
i_security = 0xffffffc07230d050,
...
答案 0 :(得分:4)
地址空间始终处理页面缓存。如果页面所有者是文件,则在页面缓存中访问页面时,address_space对象嵌入在VFS inode对象的i_data字段中。 inode的i_mapping字段始终指向包含inode数据的页面所有者的address_space对象。 address_space对象的host字段指向嵌入描述符的inode对象。
E.g。如果页面属于存储在ext4文件系统中的常规文件,则VFS inode的i_data指向该文件的inode,inode的i_mapping字段指向同一inode的i_data,address_space对象的host字段指向相同的inode。
然而事情总是那么简单。假设一个页面包含从块设备文件中读取的数据,该文件包含&#34; raw&#34;在块设备的数据中,address_space嵌入在&#34; master&#34; bdev中文件的inode,与块设备关联的特殊文件系统(由bd_inode引用)。因此,块设备文件的inode的i_mapping字段指向 嵌入在主索引节点中的address_space对象;相应地,address_space对象的主机字段指向主索引节点。以这种方式,包含从块设备读取的数据的所有页面具有相同的address_space对象,即使它们已经通过引用不同的块设备文件来访问。 因此,当它们来到页面属于常规文件或阻止设备专用文件时,它们之间存在细微的区别。
答案 1 :(得分:0)
来自http://lkml.iu.edu/hypermail/linux/kernel/0105.2/1363.html:
i_data是“此inode读取/写入的页面”
i_mapping是“我应该问谁?”
IOW,单个文件系统之外的所有文件都应使用后者。 当(且仅当)inode拥有数据时,它们相同。 CODA(或其他任何 在本地fs上缓存数据)将使i_mapping指向 它缓存到的inode。如果/当设备进入页面缓存时也是如此- 我们应该将pagecache与struct block_device关联,因为我们可以 具有相同的major:minor的许多inode。 IOW,-> i_mapping应该指向 所有人都放在同一个地方。
来自https://marc.info/?l=linux-fsdevel&m=99470104708354&w=2:
它由环绕现有文件系统的文件系统使用。 AFAIK Coda现为 树中唯一实际使用此功能的人。
所有VFS函数始终使用inode-> i_mapping-> a_ops。 Coda复制了 将基础索引节点的i_mapping映射到它自己的索引节点。这样我们使用 与容器文件具有相同的地址空间,并避免映射相同的文件 内存中不同位置的页面。
i_mapping是真实的页面缓存。 i_data是address_space所在的位置,并由inode分配和释放,通常是i_mapping指向的位置。但是文件系统可以将一个i节点的i_data保留为空,并将i_mapping指向另一个i节点的i_data,以避免多个页面缓存。