基于inode的高性能文件查寻删除(name_to_handle_at && open_by_handle_at)

场景

如果我们对某个文件在系统中建立了非常多的硬链接,而我们需要清理掉他们。
例如像是关闭基于硬链接的反勒索诱捕能力这种场景。

问题

此时大部分人可能和我最初想的一样,使用:find ./ -inum 【inode号】 -exec rm -rf {} \;
但此时如果面临的是几十上百万的文件系统呢?上面这种方式是非常浪费时间和性能的。
即使你在建立硬链接的过程中,记录了每个硬链接的存储位置,在一些目录被重命名的情况下,又会出现缓存失效的问题。
最后就会导致文件系统一地鸡毛……

解决方案

所以有没有一种性能又高,还能无视路径被重命名的方式呢?
有的有的!

此时就要用到 name_to_handle_atopen_by_handle_at 这对孪生兄弟了。
相较于 find 命令基于应用层文件系统 自顶向下 的遍历,这对孪生兄弟则是在内核中通过 inode 信息进行 自底向上 的遍历,速度极快。
使用这两个接口,仅需要满足三个条件:

  • 一:至少要知道一个硬链接文件所在位置,用于提取句柄信息;
  • 二:要知道硬链接所在分区路径,这个简单的 df 命令就可以看到,况且不通的分区不允许互相搭建硬链接;
  • 三:需要 CAP_DAC_READ_SEARCH 权限,这个用 root 权限即可无视;

使用说明

其中 name_to_handle_at 主要是用来获取文件句柄信息;

    struct file_handle *fhp = (struct file_handle *)malloc(sizeof(struct file_handle) + 128);
    fhp->handle_bytes = 128;

    // 获取目标文件的底层句柄
    if (name_to_handle_at(AT_FDCWD, target_path, fhp, &mount_id, 0) == -1) {
        perror("name_to_handle_at 失败");
        free(fhp);
        exit(EXIT_FAILURE);
    }

open_by_handle_at 则是利用文件句柄信息去打开文件。

    // 打开挂载点文件描述符(一般传文件所在分区挂载路径,例如 /、/home/、/data……)
    int mount_fd = open(mount_point, O_RDONLY | O_DIRECTORY);
    if (mount_fd == -1) {
        perror("打开挂载点失败");
        free(fhp);
        exit(EXIT_FAILURE);
    }

    // 通过底层句柄直接打开文件 (使用 O_PATH 轻量级打开以提高性能,不需要读写权限)
    int fd = open_by_handle_at(mount_fd, fhp, O_PATH);
    if (fd == -1) {
        perror("open_by_handle_at 失败,文件可能已被删除或被跨分区移动");
        close(mount_fd);
        free(fhp);
        exit(EXIT_FAILURE);
    }

在文件成功打开之后,就可以用readlink去查看"/proc/self/fd/【被打开的fd】"所指向的路径了。

    char fd_path[64];
    char real_path[PATH_MAX];
    snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", fd);
	
    ssize_t len = readlink(fd_path, real_path, sizeof(real_path) - 1);
    if (len == -1) {
        perror("获取路径失败");
        close(fd); close(mount_fd); free(fhp);
        exit(EXIT_FAILURE);
    }
    real_path[len] = '\0';

如上查寻删除后,循环往复,便达到了删除所有硬链接的目的
如果仅仅是查寻,可能需要使用先删除再搭建硬链接的方式了
因为该方法在不删除 fd 指向的目标文件的情况下,也无法获取其它硬链接路径……

posted on 2026-08-11 18:13  书生执笔画浮沉  阅读(3)  评论(0)    收藏  举报

导航