【问题标题】:Why Input/Output Error occurs when use ls command in my fuse filesystem?为什么在我的 fuse 文件系统中使用 ls 命令时会出现输入/输出错误?
【发布时间】:2022-05-11 00:41:41
【问题描述】:

为什么在我的 fuse 文件系统中尝试 ls . 命令时会导致 I/O 错误?

我的文件系统有一个限制,它只允许邮件地址类型作为单独的文件名,并且不允许子目录。
现在我想在使用ls .时显示文件名列表,但它不起作用。

我知道它必须实现一个回调函数。 (对应函数为mycode中的ll_readdir)

但我不知道是什么点导致了错误。


更新:

现在我使用strace 命令来调查是什么系统调用引发了这个错误。
根据strace的结果,这个错误是在getdents64系统调用中引起的。

getdents64(3, 0x5611ed000540, 32768)    = -1 EIO (Input/output error)

Code1(mm的实现:

struct mutex_map {
    int counter = 2;
    std::mutex _mtx;
    std::unordered_map<int, std::string> _data;
    std::unordered_map<std::string, int> _rev_data;

   public:
    int set_value(const char* value) {
        std::string s = std::string(value);
        std::lock_guard<std::mutex> lock(_mtx);
        counter++;
        _data[counter] = s;
        _rev_data[s] = counter;
        return counter;
    }

    const char* get_value(int key) { return _data[key].c_str(); }
    int get_ino(const char* name) { return _rev_data[std::string(name)]; }
};

static mutex_map mm;

代码2:(sendmailfs_stat)

static int sendmailfs_stat(fuse_ino_t ino, struct stat* stbuf,
                           size_t name_length) {
    uid_t uid = getuid();
    gid_t gid = getgid();
    stbuf->st_ino = ino;
    if (ino == 1) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
        stbuf->st_uid = uid;
        stbuf->st_mode = S_IFDIR;
    } else {
        stbuf->st_mode = S_IFCHR | 0666;
        stbuf->st_nlink = 1;
        stbuf->st_size = name_length;
        stbuf->st_uid = uid;
        stbuf->st_gid = gid;
    }
    return 0;
}

代码3:(readdir回调的实现)

static void ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
                       struct fuse_file_info* fi) {
    // printf("size_t=%ld, fh=%ld, ino=%ld\n", size, fi->fh, ino);
    if (ino == 1) {
        off_t o = 0;
        size_t rest = size;
        size_t res;
        char* buf = (char*)calloc(1, size);
        struct stat dotst;
        sendmailfs_stat(ino, &dotst, strlen("."));
        res = fuse_add_direntry(req, buf, rest, ".", &dotst, o);
        rest -= res;
        o++;
        printf("%s\n", "start of loop");
        uint64_t num_contain = 0;
        for (auto& c : mm._data) {
            const char* t = c.second.c_str();
            int ino2 = mm.get_ino(t);
            struct stat st;
            sendmailfs_stat(ino2, &st, strlen(t));
            fuse_entry_param e;
            e.ino = ino2;
            e.attr_timeout = 0;
            sendmailfs_stat(ino2, &e.attr, strlen(t));
            res = fuse_add_direntry_plus(req, buf, rest, t, &e, o);
            o += 1;
            rest -= res;
        }
        fuse_reply_buf(req, buf, size);
    }
}

【问题讨论】:

  • 您似乎已经回答了自己的问题——ls 调用了getdents64,但您还没有提供getdents64 函数。
  • 或许你应该在当前没有有效回复的情况下回复一些错误?顺便说一句:为什么要为此使用低电平保险丝?还有一件事:您还可以使用debug 选项安装保险丝以获取更多调试信息。

标签: linux filesystems c++ fuse


【解决方案1】:

有点晚了,但是如果有这个错误的人偶然发现了这个线程,他们可能想先检查文件系统是否安装正确。 getdents64 的输入/输出错误表明文件系统已卸载,但由于某种原因失败(例如当用户尝试 umount 命令时文件仍在使用中),因此看起来仍然已安装,但无法获取数据来自它。

所以在这种情况下,在您运行 ls 之前,某些进程可能会调用 umount(并且失败),或者文件系统由于某种原因一开始就无法正确挂载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多