同样,如果没有特别说明,则所有操作都在没有锁持有的情况下调用。
file_operations里大部分函数跟POSIX文件系统接口语义一样,就不单独列出了。
dcache(dentry cache)用于缓存dentry,每个dentry用于索引filename和inode number。dentry也有一套操作合集dentry operations用于管理dentry。底层文件系统可以选择实现自己的dentry operations来替换默认的operations。
struct dentry_operationsstruct dentry_operations的定义如下:
struct dentry_operations { int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, const struct inode *, struct qstr *); int (*d_compare)(const struct dentry *, const struct inode *, const struct dentry *, const struct inode *, unsigned int, const char *, const struct qstr *); int (*d_delete)(const struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); char *(*d_dname)(struct dentry *, char *, int); struct vfsmount *(*d_automount)(struct path *); int (*d_manage)(struct dentry *, bool); };d_revalidate:VFS用于检查在dcache里找到的dentry是否有效。通常设置为NULL,则只要在dcache找到即认为是有效的。但对网络文件系统如NFS来说,dentry可能在一段时间之后就会失效,因此需要实现该函数用于检查是否有效。如果有效,函数需要返回一个正数。
d_revalidate可能在rcu-walk模式(flags & LOOKUP_RCU)下被调用。此时该函数里不能阻塞也不能写入数据到dentry,并且d_parent和d_inode不能使用,因为他们可能瞬间就可能被修改。如果在rcu-walk模式遇到困难,则返回-ECHILD,将在ref-walk模式下重新调用。
d_weak_revalidate:用于检查\'jumped\'的dentry,即那些不是通过lookup获取的dentry,如\'\', \'.\'或者\'..\'。这种场景只需要检查dentry对应inode是否OK即可。该函数不会在rcu-walk模式下调用,所以可以放心的使用inode。
d_hash:用于VFS将dentry放入HASH列表。并不清楚HASH表用来做啥,通常不需要设置它,使用VFS默认的即可。
d_compare:用于比较dentry name和指定的name。该函数必须是可重入的,即每次的返回结果一样。
d_delete:用于引用计数递减为0时调用,返回1则dcache立即删除dentry,返回0则继续缓存该dentry。默认为NULL,则总是将dentry进行缓存。该函数必须是可重入的,即每次的返回结果一样。
d_release:用于释放dentry资源。
d_iput:用于释放dentry对应inode引用计数。该函数在释放dentry之前调用。如果为NULL,则VFS默认调用iput()。
d_dname:用于生成dentry的pathname,主要是一些伪文件系统(sockfs, pipefs等)用于延迟生成pathname。一般文件系统不实现该函数,因为其dentry存在于dcache的hash表里(通过pathname做hash),所以并不希望pathname变化。
d_automount:可选函数,用于穿越到一个自动挂载的dentry。它会创建一个新的vfsmount记录,并将其返回,成功后调用者将根据vfsmount去尝试mount它到挂载点。
d_manage:可选函数,用于管理从dentry进行transition。
以下函数是VFS提供给文件系统参与维护和管理的dentry cache的API接口。
dget:用于增加dentry引用计数。
dput:递减引用计数,如果减为0,则调用d_delete判断是否留在缓存里。如果判断为否,或者该dentry已经不在其父目录hash列表里,则将其删除。如果判断为是,则dentry放入LRU链表,并在触发内存回收时删除。
d_drop:将dentry从其父目录的hash列表里删除。随后如果引用计数减为0,该dentry将被删除。
d_delete:将dentry删除。如果引用计数不为0,则调用d_drop。如果为0,则调用d_iput将dentry搞成nagtive dentry。注意该函数不是dentry operations->d_delete函数指针,而是VFS提供的API接口。