Linux kernel 自编虚拟fs中umount后忙inode/dentry

Linux kernel 自编虚拟fs中umount后忙inode/dentry,linux-kernel,vfs,Linux Kernel,Vfs,我编写了一个简单的FS,它应该只静态地包含一个名为hello的文件。这个文件应该包含字符串Hello,world。我这样做是为了教育目的。安装fs时,它的行为实际上与预期的一样。我能很好地读懂这个文件 然而,卸载后,我总是 VFS: Busy inodes after unmount of dummyfs. Self-destruct in 5 seconds. Have a nice day... 如果在装载fs时在rootdir上调用ls,则 BUG: Dentry (p

我编写了一个简单的FS,它应该只静态地包含一个名为
hello
的文件。这个文件应该包含字符串
Hello,world。我这样做是为了教育目的。安装fs时,它的行为实际上与预期的一样。我能很好地读懂这个文件

然而,卸载后,我总是

VFS: Busy inodes after unmount of dummyfs. Self-destruct in 5 seconds.  Have a nice day...
如果在装载fs时在rootdir上调用ls,则

BUG: Dentry         (ptrval){i=2,n=hello}  still in use (-1) [unmount of dummyfs dummyfs]
最重要的是

这在细节上意味着什么?我如何修复它

mount和kill_sb例程调用mount_nodev,并为包含FS使用的2个inode的结构分配空间

静态结构dentry*dummyfs\u挂载(结构文件\u系统\u类型*fs\u类型,
int标志、常量字符*dev_名称、void*数据)
{
结构修复*ret;
ret=mount_nodev(fs_类型、标志、数据、dummyfs_fill_super);
如果(是错误(返回)){
printk(KERN_ERR“dummyfs_mount failed”);
}
返回ret;
}
静态无效dummyfs\u kill\u sb(结构超级块*sb){
kfree(sb->s\U fs\U信息);
杀死垃圾超级(某人);
}
fill superblock方法创建2个索引节点并将它们保存在mount分配的结构中:

static int dummyfs\u fill\u super(struct super\u block*sb、void*data、int标志)
{
结构dummyfs_info*fsi;
sb->s_magic=DUMMYFS_magic;
sb->s_op=&dummyfs_SOP;
fsi=kzalloc(sizeof(struct dummyfs_info),GFP_内核);
sb->s_fs_info=fsi;
fsi->root=new\u inode(sb);
fsi->root->i_ino=1;
fsi->root->i_sb=sb;
fsi->root->i_op=&dummyfs_iops;
fsi->root->i\u fop=&dummyfs\u dops;
fsi->root->i_atime=fsi->root->i_mtime=fsi->root->i_ctime=current_time(fsi->root);
inode_init_owner(fsi->root,NULL,S_IFDIR);
fsi->file=new\u inode(sb);
fsi->file->i_ino=2;
fsi->file->i_sb=sb;
fsi->file->i_op=&dummyfs_iops;
fsi->file->i\u fop=&dummyfs\u fops;
fsi->file->i_atime=fsi->file->i_mtime=fsi->file->i_ctime=current_time(fsi->file);
inode_init_所有者(fsi->file,fsi->root,S_IFREG);
sb->s_root=d_make_root(fsi->root);
返回0;
}
如果父目录是根目录,则查找方法只是将
fsi->file\u inode
添加到dentry:

if(父节点->i节点==fsi->根节点->i节点){
d_添加(子文档,fsi->文件);
}
而迭代方法在调用时只发出点文件和
hello
文件:

if(ctx->pos==0){
直射发射点(文件,ctx);
ret=0;
}
如果(ctx->pos==2){
dir_emit(ctx,“hello”,5,file->f_inode->i_ino,DT_未知);
++ctx->pos;
ret=0;
}
read方法只是使用
copy\u to\u user
写入一个静态字符串。偏移量计算正确,在EOF上,该方法仅返回0。然而,由于问题即使在没有调用read方法时也会发生,我认为它超出了这个已经太长的问题的范围

为了实际运行它,我使用git主机上的用户模式linux(4.15+x提交
D48FCBD864A008802A90C58A9CEDD9436D11A49
)。userland是从头开始编译的,init进程是Rich Felker最小init的派生,我在其中添加了
mount
调用
/proc
/sys
/
(重新装载)

我的命令行是
/linux-ubda=../uml/image-root=/dev/ubda


任何指向更全面文档的指针都是值得赞赏的。

使用gdb查看
dentry->d_lockref.count
我意识到,umount中的
kill_litter\u super
调用实际上是dentry问题的原因。将其替换为
kill\u anon\u super
解决了这个问题

繁忙的inode问题几乎消失了,除非在安装后立即卸载。分配第二个inode也懒散地解决了这个问题