-
sysfs中的目录或文件是无法删除的
-
使用strace跟踪用户空间和内核的交互
unlinkat(AT_FDCWD, "dm-0", 0) = -1 EPERM (Operation not permitted)strace rm -rf dm-0
unlinkat(AT_FDCWD, "blkio.bfq.io_service_bytes", 0) = -1 EPERM (Operation not permitted)strace rm -rf blkio.bfq.io_service_bytes
- 在源码目录中查找unlinkat
可以看到unlinkat的系统调用定义在fs/namei.c文件中,进一步调用了do_unlinkat, 代码如下:
SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) { if ((flag & ~AT_REMOVEDIR) != 0) return -EINVAL; if (flag & AT_REMOVEDIR) return do_rmdir(dfd, pathname); return do_unlinkat(dfd, getname(pathname)); }
-
继续从do_unlinkat开始探索函数调用路径。例如,可以使用gdb单步调试的方法定位问题的具体发生位置
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/xxx/vmlinux...done. (gdb) target remote :1234 Remote debugging using :1234 native_safe_halt () at ./arch/x86/include/asm/irqflags.h:61 61 ./arch/x86/include/asm/irqflags.h: No such file or directory. (gdb) b do_unlinkat Breakpoint 1 at 0xffffffff813540b0: file fs/namei.c, line 4057. (gdb) c Continuing. [New Thread 6] [Switching to Thread 6] Breakpoint 1, do_unlinkat (dfd=-100, name=0xffff8881716a4740) at fs/namei.c:4057 4057 fs/namei.c: No such file or directory. (gdb) bt #0 do_unlinkat (dfd=-100, name=0xffff8881716a4740) at fs/namei.c:4057 #1 0xffffffff81004374 in do_syscall_64 (nr=<optimized out>, regs=0xffff8881716a4740) at arch/x86/entry/common.c:293 #2 0xffffffff81a00088 in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:238 #3 0x000056059bb3e6b0 in ?? () #4 0x0000000000000000 in ?? () (gdb) s 4065 in fs/namei.c (gdb) s 4057 in fs/namei.c (gdb) s 4064 in fs/namei.c (gdb) s 4067 in fs/namei.c (gdb) s filename_parentat (dfd=-100, name=0xffff8881716a4740, flags=0, parent=0xffffc900018e3ee0, last=0xffffc900018e3ef0, type=0xffffc900018e3ed4) at fs/namei.c:2389 2389 in fs/namei.c
- 在函数调用路径上可以看到一个关键函数vfs_unlink,其中会调用inode实例中i_op成员的unlink函数指针。i_op成员是一个inode_operations结构指针。
int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode)
{
struct inode *target = dentry->d_inode;
int error = may_delete(dir, dentry, 0);
if (error)
return error;
if (!dir->i_op->unlink)
return -EPERM;
inode_lock(target);
if (is_local_mountpoint(dentry))
error = -EBUSY;
else {
error = security_inode_unlink(dir, dentry);
if (!error) {
error = try_break_deleg(target, delegated_inode);
if (error)
goto out;
error = dir->i_op->unlink(dir, dentry);
if (!error) {
dont_mount(dentry);
detach_mounts(dentry);
}
}
}
out:
inode_unlock(target);
/* We don't d_delete() NFS sillyrenamed files--they still exist. */
if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
fsnotify_link_count(target);
d_delete(dentry);
}
return error;
}
EXPORT_SYMBOL(vfs_unlink);
- 各种文件系统,需要按照inode_operations中的规范,完成unlink的实现,向kernel vfs注册,而sysfs没有实现unlink。