文件删除与sillyrename还有孤儿节点

本文探讨了NFS文件系统在面对文件删除时采用的sillyrename策略,解释了其原因和本地文件系统如ext3/4为何不使用此策略。文章还介绍了孤儿节点的概念和处理机制,以及ext4文件系统中孤儿inode的组织结构和管理流程。此外,提及了FUSE库中sillyrename策略的应用,但未深入讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NFS文件系统的unlink操作,当目标节点的目录下引用计数大于0时,则采用sillyrename策略,最后一个打开文件的进程关闭文件时候,会检测sillyrename的标志位,若置位,则将其删除。

×××××××××××××××××××××××××××××××××××

上文是我11年7月刚进入实验室看NFSv3代码时候,做的笔记,现在回头看,理解的连皮毛都算不上,着实汗颜。

最近看FUSE lib库的文件,又发现了FUSE也使用了silly rename策略就很好奇,为什么VFS层没有做一个统一的控制,而是交由具体的文件系统来处理,还有,为什么本地文件系统没有使用silly rename策略,现在略微懂了一些,把一些结论记录在此。

0.关于d_count,i_count,nlink

d_count描述有多少file结构指向这个dentry;

i_count描述有多少个dentry指向这个inode

nlink描述磁盘的硬链接数目。

filp_open filp_close会增加或减少d_count;

d_count减为0会递减i_count;

unlink会减少nlink;


1.nfs为什么要使用silly rename策略?

nfs v3是无状态的协议,在server端,就连基本的open- close的状态也没有,即客户的RPC中,是没有open和close 的操作的。

任何操作都是使用fh直接发请求,而fh的获取是最开始的lookup操作完成的。lookup操作会在server端建立起inode和dentry的数据结构,而一旦server端内存中有了dentry和inode结构,重复的lookup操作并不会增加引用计数d_count,这也就意味着,server端并不知道client端有多少个文件打开了同一个文件。

而在本地文件系统ext3中,d_count会随着open的调用而增加。

在nfs中,同一个客户端在执行unlink系统调用时候,若发现本机还有其他进程同时打开此文件时候,就会采用silly rename策略,否则server端就会简单粗暴的执行删除操作,而不去管是否还有其他进程也在使用同一个文件。


2.本地文件系统为何不必采用sillyrename 策略

当执行文件删除系统调用时,会调用vfs_unlink操作,此操作会将--nlink,然后尝试将对应dentry从哈希表中删掉,并递减i_count。由于本地文件系统,open时候会增加d_count,因此,不会导致dentry的错误删除。

而inode可能会成为孤儿节点。ext3和ext4都有专门的机制来处理。


orphan在英文中是孤儿的意思,在这里取被遗弃、被删除之意。
orphan inode是什么样的inode呢?这种inode是怎样产生的呢?
先介绍一个概念,文件的引用计数,准确地说应该是inode的引用计数,因为一般来说一个文件会对应一个inode。文件的引用计数,简单地说是表示有多少个文件指向该文件,准确地说是文件的硬链接的个数。
情况1:设想一个进程,open一个文件,然后unlink该文件,然后进行文件读写。这是允许的,并且在进程退出时,内核会自动将引用计数为0的文件删除。
但是如果该进程尚未退出之前,系统崩溃了,那么,内核就没有机会将已被unlink、并且引用计数为0的inode从磁盘上删除了。
情况2:设想我们正在截断一个大文件(系统调用truncate),但是操作尚未完成,系统就崩溃了。同样,内核也没有办法将该文件的所有数据块全部删除了。
ext3、ext4的orphan inode机制就是处理上述两种情况的。基本思想是这样的:如果要删除或截断一个inode,要先把这个inode记录到磁盘上的一个特殊的orphan inode链表上。如果删除或截断操作能够正常完成,那么,就从磁盘上的orphan inode链表上删除该inode;否则,如果删除或截断操作未完成之前,系统就发生崩溃了,那么,系统重启后,文件系统会遍历磁盘上的orphan inode链表,对链表上的每一个inode都重新进行一遍删除或截断操作,以此来保证这些inode真正在磁盘上被删除,维护文件系统的一致性。
内核版本:2.6.35

二、相关数据结构及之间的关系

先总体说一下orphan inode的组织。
orphan inode需要在两个地方组织,分别是在内存中和在磁盘上。不论在哪里,从抽象角度来看,orphan inode都被组织成一个单向链表。

1、ext4_inode

struct ext4_inode {

    __le32 i_dtime; /* Deletion Time */

    .........

}
这个是磁盘上的inode的结构,i_dtime本来表示该inode被删除的时间,在orphan inode机制中,因为此时该域的值并不重要,故借用一下,用于记录下一个被unlink/truncate的inode号。

2、ext4_super_block

struct ext4_super_block {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值