用户空间文件系统(FUSE)( 二 )

3.2 模块参数FUSE内核模块包括两个参数 , 模块注册后也可以在sysfs文件系统中查看默认值:
# modinfo -p fusemax_user_bgreq:Global limit for the maximum number of backgrounded requests an unprivileged user can set (uint)max_user_congthresh:Global limit for the maximum congestion threshold an unprivileged user can set (uint)# ls /sys/module/fuse/parameters/max_user_bgreqmax_user_congthresh# cat /sys/module/fuse/parameters/max_user_bgreq 19701# cat /sys/module/fuse/parameters/max_user_congthresh 19701

  • max_user_bgreq: 后台请求的最大数量;在FUSE控制文件系统中 , max_background属性在普通用户下禁止超过该值;
  • max_user_congthresh:后台请求限流开始的数量;在FUSE控制文件系统中 , congestion_threshold属性在普通用户下不会超过该值;
3.3 文件系统挂载参数文件系统挂载可以指定如下的参数:
  • fd=: 必填 , 指定了用户空间进程打开杂项设备`/dev/fuse`的文件描述符;
  • rootmode=:必填 , 指定了文件系统挂载时跟目录的文件权限;
  • user_id=:必填 , 指定了用户空间进程所属的用户id;
  • group_id=:必填 , 指定了用户空间进程所属的用户组id;
  • default_permissions:默认情况下FUSE是不进行文件系统权限校验的 , 这可以在用户空间进程中对权限进行合乎场景的实现;指定该参数后 , 内核会对文件按照访问控制权限进行检查;
  • allow_other:允许其他用户访问挂载点的数据 , 和default_permissions共同设置可以到达共享文件访问限制的功能;另外 , 需要注意的是 , 使用普通用户挂载文件系统时需要在配置文件/etc/fuse.conf中添加user_allow_other参数;
  • max_read=:文件系统读请求IO的最大值 , 默认为无符号整型的最大值 , 也可以通过初始化请求从用户空间获取;
  • blksize=:在文件系统类型fuseblk时设置块大小 。 文件系统类型为fuse时不需要指定 , 此时默认值为页大小;
3.4 文件系统挂载流程文件系统挂载时会调到文件系统注册时的.mount接口 , 对应到FUSE为fuse_mount , 进入方法后实际主要分为两个部分:
  • 调用sget获取或分配文件系统超级块;
  • 调用fuse_fill_super初始化文件系统并填充超级块字段;

用户空间文件系统(FUSE)文章插图
如上图所示 , 默认会初始化一个根节点索引号为1的文件系统 , 用户空间文件系统在实现的时候需要进行默认维护 , 所有文件系统跟节点下的操作的父节点索引号都是1 。 另外 , 每当挂载一个文件系统 , 都会在内核模块中创建一个与之对应的fuse通道 , fuse通道会被添加FUSE控制文件系统fusectl中;挂载多个文件系统时 , 多个fuse通道会被组织成一个链表 , 如下是一个fuse通道的内部结构:
用户空间文件系统(FUSE)文章插图
fuse通道主要用于维护文件系统中各种类型的请求队列:
  • pending queue:一般的请求在初始化完成后会加入该队列 , 等待用户空间进程来读取;
  • io queue:请求数据正在被读取时会被加入该队列;
  • processing queue:请求数据被读取完成后正在用户空间进行处理 , 则会加入该队列;
  • bg_queue:后台请求的队列 , 每当由请求处理完成时 , 会将后台队列加入pending queue中 , 最多添加max_background和请求;
  • interrupts queue:被中断的请求会被加入该列表;
  • forget list:缓存失效时发送的forget请求链表;
用户空间进程在读取请求时各个队列之间存在一定的优先级 , interrupt queue > forget list > pending queue 。 waitq是用于维护等待请求返回的睡眠线程 , 用户空间进程写入请求返回或请求被终止后会被唤醒;
3.5 FUSE控制文件系统在FUSE内核模块加载时会创建FUSE控制文件系统 , 如3.1节;文件系统挂载时 , 创建的fuse通道会被加入FUSE控制文件系统中 , 这样就可以查看文件系统当前的状态 , 或则通过写入数据到文件达到控制文件系统的目的;如果FUSE控制文件系统不存在的话 , 需要进行手动挂载 。 另外一个在维护上需要注意的是 , FUSE控制文件系统依赖于fuse内核模块 , 有时需要卸载fuse内核模块 , 没有文件系统挂载但还提示模块正在被使用 , 大多数情况是由于FUSE控制文件系统处于挂载状态 , 卸载后就可以正常的移除内核模块了 。
# mount -t fusectl none /sys/fs/fuse/connections/# ll /sys/fs/fuse/connections/total 0dr-x------ 2 test test 0 Oct 18 15:48 39# ll /sys/fs/fuse/connections/39/total 0--w------- 1 test test 0 Oct 18 15:48 abort-rw------- 1 test test 0 Oct 18 15:48 congestion_threshold-rw------- 1 test test 0 Oct 18 15:48 max_background-r-------- 1 test test 0 Oct 18 15:48 waiting