fd_clone给fuse带来了什么

fd_clone给fuse带来了什么

       libfuse从2016年12月08日发布3.0.0版本开始支持clone_fd选项,相应的ko模块在linux内核4.2版本做相应的修改:https://kernelnewbies.org/Linux_4.2

       查看libfuse的changelog是这么描述的

* Added *clone_fd* option.  This creates a separate device file
  descriptor for each processing thread, which might improve
  performance.

       意思是可以为一个processing thread创建一个独立的内核文件描述符file descriptor,达到提高性能的目的。这只是用户态所看到的信息,看看内核ko的protocol说明,可以看到如下的表述

Multi-Threading

Background: When a file is opened, the Linux kernel creates a "file description" for the I/O state, and returns a "file descriptor" to userland. That descriptor can be freely passed to the dup(2) functions to duplicate the descriptor, but the underlying description remains unary.

The FUSE kernel driver implicitly locks access to the /dev/fuse file descriptor so that each read() and write() syscall is atomic. This implies that multiple threads can safely share the descriptor, but also that they will face lock contention and reduced performance.

To get the best performance out of a multi-threaded filesystem server, open /dev/fuse once as a "session FD" and again in each thread as "worker FDs". After initializing the session with a standard FUSE handshake, the workers can be associated with the session by calling ioctl(worker_fd, FUSE_DEV_IOC_CLONE, &session_fd).

This allows multiple threads to serve FUSE requests without contending for the descriptor lock.

     所以不是separate file descriptor这么简单,普通的通过dup(2)复制出来的fd,最终指向的是同一个file description,下面这个图应该是熟面孔了,如果fd 20是通过对fd 2执行dup(2)得到的,则两个fd在内核实际指向同一个file description,在这种情况下,不考虑file description中file operation的实现,不同的两个线程分别操作fd 2和fd 20,最终在file description都难以避免一些竞争条件。

    而fd_clone则正是为了解决这个问题,通过使用ioctl来对一个fuse dev fd进行clone,在内核创建不同的file description,将资源分割开以达到尽量减少冲突域的目的。

    fuse在mount和clone fd后内核数据结构如下图:

  • mount一个fuse文件系统对应一个super block;
  • 一个super block对应一个fuse_conn;
  • mount时会创建第一个fuse_dev;
  • 每clone一次fd就会再创建一个fuse_dev;
  • 每个fuse_dev都有自己的processing queue;
  • 多个fuse_dev都放在fuse_conn的devices链表中;
  • 一个fuse文件系统只有一个iput queue在fuse_conn对象中;

fs handler

      从fs handler端来看,user application发起的文件操作最终都会走到__fuse_request_send(fuse_conn *, fuse_req *)。可能有多个user application线程同时发起操作,都是通过对fuse_iqueue中waitq的spinlock进行加锁来互斥,保护多个线程同时把request挂入到fuse_iqueue的pending中。所以fd clone对user application端的效率应该是没有任何帮助了。

dev handler

       而fuse daemon端的多个worker线程都是通过fuse_dev_do_read(fuse_dev *, file *, size_t)来读取request。如果是支持fd clone的话,这里的fuse_dev *和file *两个参数都是线程独享的。从流程上来看,fuse_dev_do_read是从fuse_conn的fuse_iqueue中取出一个request,放入到fuse_dev的fuse_pqueue中的io list里;然后执行内存拷贝,将内核buffer中的req数据拷贝到用户空间,copy完成后将这个req再从fuse_pqueue的io list移动到processing list。然后read操作返回。整个过程会针对fuse_pqueue加多次锁,因此如果不同的worker使用不同的fuse_dev的话,这里的竞争条件必然会缩小,从而达到提高效率的目的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值