/* Inode state bits.. */ #define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ #define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ #define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ #define I_LOCK 8 涉及到的索引节点处于I/O传输中 #define I_FREEING 16 索引节点对象正在被释放 #define I_CLEAR 32 索引节点对象内容不再有意义
I_NEW 索引节点对象已经分配,但还没有用从磁盘索引节点读取的数据来填充
inode_unused
inode_in_use
s_dirty(sb)
s_inodes(sb)
inode_hashtabel
destroy_inode 释放inode内存对象
put_inode 减少索引节点引用计数时调用 drop_inode delete_inode 删除索引节点在硬盘上的数据(包括修改所在块组的位图) clear_inode 重置inode内存对象中的数据,重置状态,解除和buffer_head的关联等等。 iput-->put_inode -->(drop_inode 2.4内核没找到) -->delete_inode | clear_inode -->destroy_inode ext2_delete_inode-->ext2_truncate,在这里释放文件的所有数据块 dget_locked __dget_locked dget 增加dentry使用数 dput 减少dentry使用数 iget 增加inode中的使用数(usecount) iput 减少inode中的使用数(usecount),当usecount为0且link数为0时可以释放内存 pathwalk的过程中,dget和dput是成对调用的,最后返回的结果dentry只调用了dget,由使用此dentry的函数,在使用完成后调用dput。 open时也要获取dentry,这个dentry调用dget把使用数增加,在close时调用dput(fput->dput)减少使用数。 unlink时,调用op->unlink和d_delete,最后调用dput,op_unlink是各文件系统自己实现,主要是减少node中link数,并修改硬盘中名字空间和文件记录。d_delete判断dentry的使用数是否为1,如果为1,减少dentry中inode记录的使用数(负状态?),如果大于1,说明有人还在使用此dentry, 重置d_hash,让其他人再无法查询到该dentry。调用dput,如果没有人在使用,并且不能通过d_hash查到该dentry时,释放该dentry,如果还可以通过d_hash查到该dentry,把dentry加入freelist中(未使用状态?)。 疑问:为什么不在d_delete函数中直接重置d_hash,这样在dput时就可以释放dentry了? /** * d_invalidate - invalidate a dentry * @dentry: dentry to invalidate * * Try to invalidate the dentry if it turns out to be * possible. If there are other dentries that can be * reached through this one we can't delete it and we * return -EBUSY. On success we return 0. * * no dcache lock. */ int d_invalidate(struct dentry * dentry) /* * This is dput * * This is complicated by the fact that we do not want to put * dentries that are no longer on any hash chain on the unused * list: we'd much rather just get rid of them immediately. * * However, that implies that we have to traverse the dentry * tree upwards to the parents which might _also_ now be * scheduled for deletion (it may have been only waiting for * its last child to go away). * * This tail recursion is done by hand as we don't want to depend * on the compiler to always get this right (gcc generally doesn't). * Real recursion would eat up our stack space. */ /* * dput - release a dentry * @dentry: dentry to release * * Release a dentry. This will drop the usage count and if appropriate * call the dentry unlink method as well as removing it from the queues and * releasing its resources. If the parent dentries were scheduled for release * they too may now get deleted. * * no dcache lock, please. */ void dput(struct dentry *dentry) 空闲状态 未使用状态 正在使用状态 负状态shrink_slab-->shrinker->shrink(shrink_icache_memory)-->prune_icache会将不在使用的inode释放