Linux VFS (3)

create:创建inode,由open(2)和creat(2)调用。只有当需要支持常规文件时,才实现该函数。入参dentry必须没有指向任何inode的,最后需要调用d_instantiate()将新创建的inode加入到这个dentry中。

lookup:查找inode。

需要查找的inode的名字记录在dentry中。如果找到了则需要调用d_add()将inode加入到dentry中,并且inode的引用计数要加1。如果inode不存在,则需要将NULL加入到dentry,代表dentry是无效的。

当错误发生时,必须返回错误。如果只是将dentry指向NULL,VFS会执行create(2), mknod(2), mkdir(2)去创建inode,但这些函数还是会因为lookup失败的原因而再次失败。

如果需要重新设置dentry的操作函数,可以给d_dop赋值。这些函数被调用时,会使用目录inode的信号量。

link:创建硬链接。和create一样,该函数中需要调用d_instantiate()。

unlink:支持删除inode。

symlink:创建符号链接。

mkdir:创建目录。该函数中也需要调用d_instantiate()。

rmdir:删除目录。

mknod:创建设备inode、命名管道或socket。该函数中也需要调用d_instantiate()

rename:重命名。当文件系统不支持某些方法和flag时,必须返回-EINVAL。当前以下flag已经实现

RENAME_NOREPLACE:如果新文件名已经存在,则应当返回-EEXIST。但是目前VFS已经检查了新文件名是否存在。

RENAME_EXCHANGE:两个文件必须都存在,只是交换一下文件名。

get_link:获取符号链接所指向的inode。

readlink:读取符号链接所指向的inode的文件名。正常情况下,文件系统只需要实现get_link。

permission:检查类POSIX文件系统的访问权限。可能会在rcu-walk模式下调用。如果在rcu-walk模式下,文件系统必须在不阻塞或者不存储inode的情况下检查权限。如果在rcu-walk模式下,发生一个无法处理的情况,则返回-ECHILD,此后会在ref-walk模式下再尝试一次。

setattr:设置文件属性,由chmod(2)和相关的系统调用触发。

getattr:获取文件属性,由stat(2)和相关的系统调用触发。

listxattr:由VFS调用列出一个文件的所有扩展属性,由listxattr(2)触发。

update_time:更新inode的时间(atime、ctime、mtime)或i_version。如果该方法未定义,那么VFS会自行更新inode,然后调用mark_inode_dirty_sync()标记该inode为脏inode。

atomic_open:在open操作的最后调用。使用这个可选的方法,文件系统可以原子性地查找、创建、打开一个文件。如果该方法想让调用者去打开文件,则应当通过finish_no_open()通知调用者。该方法只在最后一步是无效或者需要lookup时才调用。缓存有效的dentry需要在f_op->open()中完成。如果文件创建成功了,则需要在file->f_mode设置FMODE_CREATED。如果指定了O_EXCL,该方法需要在文件存在时返回失败。返回成功就设置FMODE_CREATED。

tmpfile:在open(O_TMPFILE)的最后被调用。这是一个可选的方法,等同于在一个指定的目录下,原子性地创建、打开、删除一个文件。

The Address Space Object

address space对象用于组织和管理page cache中的page。它可以追踪一个文件使用的page以及一个文件被映射到进程空间的page。它可以根据地址查找page,追踪被标记为Dirty或Writeback的page。

VM可以调用writepage()来清理脏页,或者设置PagePrivate后调用releasepage()来释放干净的页以便重新使用。如果干净的页没有设置PagePrivate或者没有外部引用,就会在没有通知address space的情况下被释放掉。为了实现这些功能,page需要通过lru_cache_add()方法放到LRU中,当page被使用时需要调用mark_page_active()。

page使用一个基数树(radix tree)来保存。这棵树维护了所有page的PG_Diry和PG_Writeback状态,因此这些页能被快速找到。

mpage_writepages()是默认的writepages,它使用Dirty标记查找脏页并写回。如果没有使用mpage_writepages()(可能是address space提供了自己的writepage),那么PAGECACHE_TAG_DIRTY标记就不会被使用。write_inode_now()和sync_inode()使用PAGECACHE_TAG_DIRTY来检查writepages是否将整个address space写回到存储中。

filemap*wait*和sync_page*会使用Writeback标记,并通过filemap_fdatawait_range()等待所有写回操作完成。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzddjg.html