Filesystems 在ramfs中,如何根据NUMA节点跟踪文件访问模式?

Filesystems 在ramfs中,如何根据NUMA节点跟踪文件访问模式?,filesystems,numa,Filesystems,Numa,由于Ramfs将文件存储到内存中,并且内存绑定到某个NUMA节点,因此我认为存在一些方法来跟踪请求文件的节点(a.txt) 例如,如果有4个NUMA节点及其本地内存,则访问a.txt的节点列表可以是0 0 0 1 0 2 2 0 3 3 3 一种可能的解决方案如下: 查找低级ramfs文件操作函数(如read或write) 获取执行该函数的线程的节点号 将该节点号存储到某个地方(例如a.txt的inode或其他内容) 但是我没有找到这样一个低级的ramfs函数,我不能继续了 有没有办法做到这一点

由于
Ramfs
将文件存储到内存中,并且内存绑定到某个
NUMA
节点,因此我认为存在一些方法来跟踪请求文件的
节点(
a.txt

例如,如果有4个NUMA节点及其本地内存,则访问
a.txt
的节点列表可以是
0 0 0 1 0 2 2 0 3 3 3

一种可能的解决方案如下:

  • 查找低级
    ramfs
    文件操作函数(如
    read
    write
  • 获取执行该函数的线程的节点号
  • 将该节点号存储到某个地方(例如a.txt的inode
  • 或其他内容) 但是我没有找到这样一个低级的ramfs函数,我不能继续了


    有没有办法做到这一点?

    不是一个完整的解决方案,而是一些想法

    somefs将文件存储到内存中,并且该内存绑定到某个NUMA节点。。我认为有一些方法可以跟踪请求文件的节点

    在现代Linux(4.x内核)中,有许多跟踪文件访问的方法(一些基本类型;open/read/write/mmap;但不包括mmaped区域的使用)。对于单个pid,您可以使用
    strace
    system call tracer(或
    ltrace-S
    ,另外还可以捕获库调用)。对于许多PID(完整系统跟踪),您可以尝试
    sysdig

    也可以使用内核内(和树外内核模式)跟踪框架。比如基于perf+probe/ftrace(trace cmd)的东西,或者更高级的跟踪解决方案,比如定义并启用相应跟踪点的
    stap
    /
    dtrace
    /
    lttng
    。Gregg在他的文章中列出了更多的工具,都是经典的(VFS的小列表);和基于bcc/eBPF的:

    大多数系统范围的工具已经有了很好的框架来做时间戳和进程记帐,并将大量跟踪数据从内核模式下载到一些日志/转储文件中。其中一些(stap/dtrace/bcc+探针)允许您编写小代码片段,以便在调用跟踪函数时执行

    Gregg的工具的例子是“iosnoop”(它位于
    debugfs&/sys/kernel/debug/tracing
    之上,即&)。它显示每个realread/write操作的延迟时间(该操作进入real disk;而不是像在ramfs中一样访问页面缓存中已经读取的数据):

    • 博士
    • src
    • (通过
      nop ftracing
      两个事件几乎可以在任何地方工作:事件/块/块插入和事件/块/块完成)
    • (通过在iosnoop src中将
      cat trace
      行替换为
      cat trace | tee-a~/iotrace.$$.dump
      添加原始跟踪的调试保存,并查看它)
  • 查找低级ramfs文件操作函数(如读或写)
  • 不幸的是,ramfs太基本了,无法实现任何有趣的东西。RAMF有地址空间操作和文件操作:

    simple\u
    /
    generic\u file\u
    操作是在libfs/或mm/(使用elixir/lxr网站,您只需单击函数即可找到其定义和用法)中定义的,并且它们被用于多个linux FS实现中,因此无条件地跟踪它们可能是不安全的

    您可以尝试重写ramfs的实现;只需在变量中用不同的名称定义类似的
    简单
    /
    通用文件
    操作即可。您将只能跟踪它们

  • 获取执行该函数的线程的节点号
  • 我认为,还有另一种方法。检测到访问时获取进程/线程的pid/tid;但是不要做任何事情来查找NUMA节点(有可能的是,您将修改ramfs实现,并添加自己的
    aops
    ,读取
    current
    ptr并从中查找NUMA节点;但是在哪里编写它呢?)

    当有高级跟踪框架时,更容易的是记录调度器的所有动作,以及计划给每个CPU的pid(如在
    sched_
    函数的perf/stap/lttng跟踪中-
    sched_开关
    可能带有参数;甚至ftrace也允许您在单个过滤器中组合两个跟踪,io和sched)

    您将有一些后处理来对输出进行排序和合并信息,但这应该可以完成任务

  • 将该节点号存储到某个地方(如a.txt的inode或其他内容)

  • 不要重新发明轮子,使用跟踪框架。

    什么是Ramfs?是Linux吗?您的机器是NUMA吗(有多个套接字,每个套接字都有自己的集成内存控制器)?NUMA放置物理4KB(或2MB)页面。Linux有libnuma()如果来自Ramfs的数据是
    mmap
    ed,要找到数据的位置,您可以尝试
    numa\u move\u pages
    /
    move\u pages
    (),节点中为NULL:“节点也可以为NULL,在这种情况下,move\u pages()不移动任何页面,而是返回每个页面当前所在的节点,在状态数组中。”我的问题是:我如何知道哪个节点需要数据,而不是数据驻留在哪个节点。更具体地说,我想在Ramfs中为每个文件(每个inode)保留日志。日志是NUMA节点列表,将告诉我们哪些节点访问了该文件。Bot,请解释更多。是Linux(哪个内核版本)?它是tmpfs吗?程序如何访问文件(读、mmap、写还是什么)。它是你的程序(你能修改它)还是许多不是你的程序?你能改变什么(补丁+重新编译内核,补丁ramfs兼容模块,FUSE;你能用ftrace/stap/dprobe/strace/ltrace吗?你不能在inode中存储太多。(PS如果这是您课程中的任务,请告诉我们这门课程是关于什么的,内核编程还是unix编程还是什么?)
    static const struct address_space_operations ramfs_aops = {
        .readpage   = simple_readpage,
        .write_begin    = simple_write_begin,
        .write_end  = simple_write_end,
        .set_page_dirty = __set_page_dirty_no_writeback,
    };
    
    const struct file_operations ramfs_file_operations = {
        .read_iter  = generic_file_read_iter,
        .write_iter = generic_file_write_iter,
        .mmap       = generic_file_mmap,
        .fsync      = noop_fsync,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .llseek     = generic_file_llseek,
    };