小编abu*_*ord的帖子

FUSE getattr操作是否应该始终序列化?

我正在实现一个FUSE文件系统,旨在通过熟悉的POSIX调用提供对实际存储在RESTful API后面的文件的访问.文件系统首次检索文件后会对文件进行缓存,以便在后续访问中更容易使用它们.

我正在以多线程模式运行文件系统(这是FUSE的默认模式),但发现getattr调用似乎是序列化的,即使其他调用可以并行进行.

打开文件时,FUSE总是先调用getattr,而我支持的客户端需要这个初始调用返回的文件大小是准确的(我对此行为没有任何控制权).这意味着,如果我没有在文件缓存我需要真正获得通过的RESTful API调用的信息.有时这些呼叫是在高延迟网络上发生的,往返时间约为600毫秒.

由于getattr调用的明显顺序性质,对当前未缓存的文件的任何访问都将导致整个文件系统在为此getattr提供服务时阻止任何新操作.

我已经提出了很多方法来解决这个问题,但是所有这些方法看起来都很丑陋或啰嗦,实际上我只是想让getattr调用并行运行,就像所有其他调用一样.

查看源代码我不明白为什么getattr应该像这样,FUSE会锁定tree_lock互斥锁,但仅用于读取,并且没有同时发生写入.

为了在这个问题中发布一些简单的东西,我已经敲了一个非常基本的实现,它只支持getattr并且可以轻松演示问题.

#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 22
#endif

#include <fuse.h>
#include <iostream>

static int GetAttr(const char *path, struct stat *stbuf)
{
    std::cout << "Before: " << path << std::endl;
    sleep(5);
    std::cout << "After: " << path << std::endl;
    return -1;
}

static struct fuse_operations ops;

int main(int argc, char *argv[])
{
    ops.getattr = GetAttr;
    return fuse_main(argc, argv, &ops);
}
Run Code Online (Sandbox Code Playgroud)

使用几个终端在(大致)同一时间在路径上调用ls表示第二个getattr调用仅在第一个完成时启动,这导致第二个ls需要~10秒而不是5秒.

1号航站楼

$ date; sudo ls /mnt/cachefs/file1.ext; date
Tue Aug 27 16:56:34 …
Run Code Online (Sandbox Code Playgroud)

c c++ linux multithreading fuse

12
推荐指数
1
解决办法
2186
查看次数

标签 统计

c ×1

c++ ×1

fuse ×1

linux ×1

multithreading ×1