You need to enable JavaScript to run this app. FUSE示例应用调用mknod回调触发Input/Output Error如何解决
优惠活动
大模型
产品
解决方案
定价
更多

FUSE示例应用调用mknod回调触发Input/Output Error如何解决

FUSE touch触发ll_mknod返回I/O错误修复方案

核心问题及修复步骤

  • 问题1:文件类型设置错误
    你当前在sendmailfs_stat里给非根节点的文件设置的是S_IFCHR(字符设备),而touch创建的是普通文件,对应标识应为S_IFREG。同时mknod回调需要先判断传入的mode是否是普通文件,避免处理非法的设备文件创建请求。
    修复代码:
    // 修改sendmailfs_stat里非根inode的mode设置
    stbuf->st_mode = S_IFREG | 0666;
    // ll_mknod开头新增mode判断
    if (!S_ISREG(mode)) {
        fuse_reply_err(req, EINVAL);
        return;
    }
    
  • 问题2:元数据存储逻辑错误
    你的mutex_map::set_value只写入了_data正向着映射,没有写入_rev_data反向映射,而且你存储的是临时的const char*指针,fuse传递的name参数在回调结束后就会被释放,后续访问会触发野指针问题。
    修复:把两个map的键值类型改成std::string避免野指针,同时写入双向映射:
    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 std::string& value) {
            std::lock_guard<std::mutex> lock(_mtx);
            counter++;
            _data[counter] = value;
            _rev_data[value] = counter; // 新增反向映射写入
            return counter;
        }
    
        const std::string& get_value(int key) { return _data[key]; }
        int get_ino(const std::string& name) { return _rev_data[name]; }
    };
    
  • 问题3:ll_open逻辑错误+重复回复
    你判断写权限用了逻辑与&&而不是按位与&,而且报错后没有加return,会同时回复错误和open成功,导致FUSE内核模块报错I/O。
    修复:
    static void ll_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
        if (ino == 1 || !mm._data.count(ino)) {
            puts("invalid access due to hello");
            fuse_reply_err(req, ENOENT);
            return; // 报错后直接返回
        } else if ((fi->flags & O_WRONLY)) { // 改成按位与判断
            fuse_reply_err(req, EINVAL);
            return; // 报错后直接返回
        }
        fuse_reply_open(req, fi);
    }
    
  • 问题4:未实现必要的回调函数
    touch创建文件后会依次调用setattr(修改时间戳)和getattr(查询文件属性),你当前这两个回调直接返回EINVAL,必然触发错误。
    修复:
    static void ll_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
        struct stat st = {0};
        if (ino == 1) {
            sendmailfs_stat(ino, &st, 0);
        } else if (!mm._data.count(ino)) {
            fuse_reply_err(req, ENOENT);
            return;
        } else {
            sendmailfs_stat(ino, &st, mm.get_value(ino).size());
        }
        fuse_reply_attr(req, &st, 1.0);
    }
    
    static void ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, struct fuse_file_info* fi) {
        // 不需要真实存储属性的话直接返回成功即可
        struct stat st = {0};
        if (!mm._data.count(ino) && ino !=1) {
            fuse_reply_err(req, ENOENT);
            return;
        }
        sendmailfs_stat(ino, &st, ino ==1 ? 0 : mm.get_value(ino).size());
        // 可以忽略to_set的修改,直接返回现有属性
        fuse_reply_attr(req, &st, 1.0);
    }
    
    同时记得把这两个回调注册到fuse_lowlevel_ops里:
    static const struct fuse_lowlevel_ops opener = {
        .lookup = ll_lookup,
        .mknod = ll_mknod,
        .getattr = ll_getattr,
        .setattr = ll_setattr,
        .open = ll_open,
        .write = ll_write,
    };
    
  • 问题5:正则表达式转义错误
    C++字符串里的\w需要转义成\\w,否则正则匹配会失效,如果你测试的文件名不符合邮箱格式会直接返回EINVAL,可以先注释正则验证测试功能是否正常,再调整匹配规则。
    修复:
    std::regex re("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
    

验证方法

修复后重新编译运行,挂载目录后执行touch test@example.com(符合你正则的邮箱格式文件名)即可正常创建文件,不会报I/O错误。

内容的提问来源于stack exchange,提问作者KiYugadgeter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 01:57:03