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
相关产品推荐
相关产品推荐

