質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

0回答

546閲覧

FUSEでls .を実行するとI/O Errorが発生する

real_truely_fon

総合スコア0

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/09/05 01:55

Linuxのfuse(Filesytem in Userspace)を使ってメールアドレスでしかファイルを作れないファイルシステムを作ろうとしています。

ls .で作ったファイルの一覧を表示したいのですが、これを行うとInput/Output Errorが発生してしまいます。
なぜでしょうか?
下記コード内において、readdir system callに対するコールバックはll_readirでこのあたりの実装に問題があるかもしれないなと思っています。

FUSE内でstrace ls .をしてみたところ
getdents64(3, 0x5611ed000540, 32768) = -1 EIO (Input/output error)となっていてこのあたりが原因ではないかなと考えています

FUSEのコード:

#define FUSE_USE_VERSION 310 #include <dirent.h> #include <fuse3/fuse_lowlevel.h> #include <time.h> #include <unistd.h> #include <cerrno> #include <cstdio> #include <cstring> #include <mutex> #include <regex> #include <unordered_map> 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; 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; } static void list_dir() {} static void ll_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) { struct fuse_entry_param e; if (parent != 1) { fuse_reply_err(req, ENOENT); return; } if (mm._rev_data.find(std::string(name)) == mm._rev_data.end()) { fuse_reply_err(req, ENOENT); return; } puts("Found!"); memset(&e, 0, sizeof(e)); int new_ino = mm.set_value(name); e.ino = (uint64_t)new_ino; e.attr_timeout = 1.0; e.entry_timeout = 1.0; sendmailfs_stat(e.ino, &e.attr, strlen(name)); puts("Helloworld2"); printf("strlen:%zu: %s\n", strlen(name), name); fuse_reply_entry(req, &e); } static void ll_mknod(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev) { if (parent != 1) { fuse_reply_err(req, ENOENT); return; } int ret; std::regex re("(\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+"); if (std::regex_match(name, re)) { puts("Matched"); int inode_num = mm.set_value(name); struct fuse_entry_param e; e.ino = inode_num; e.attr_timeout = 1.0; e.entry_timeout = 1.0; sendmailfs_stat(e.ino, &e.attr, strlen(name)); ret = fuse_reply_entry(req, &e); } else { puts("Unmatched"); ret = fuse_reply_err(req, EINVAL); } printf("%d\n", ret); } static void ll_write(fuse_req_t req, fuse_ino_t ino, const char* buf, size_t size, off_t off, struct fuse_file_info* fi) { if (mm.get_value(ino) == NULL) { fuse_reply_err(req, EINVAL); return; } fuse_reply_write(req, size); } static void ll_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { if (ino == 1 || !mm.get_value(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); } static void ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, struct fuse_file_info* fi) { printf("to_set flag: %d\n", to_set); puts("setattr"); const char* s = mm.get_value(ino); size_t len = strlen(s); struct stat local_st; // do not use outsize of this function. memcpy(&local_st, attr, sizeof(struct stat)); sendmailfs_stat(ino, attr, len); struct timespec t; if (to_set & FUSE_SET_ATTR_MODE) { attr->st_mode = local_st.st_mode; } if (to_set & FUSE_SET_ATTR_UID) { attr->st_uid = local_st.st_uid; } if (to_set & FUSE_SET_ATTR_GID) { attr->st_gid = local_st.st_gid; } if (to_set & FUSE_SET_ATTR_SIZE) { attr->st_size = local_st.st_size; } if (to_set & FUSE_SET_ATTR_ATIME) { attr->st_atim = local_st.st_atim; } if (to_set & FUSE_SET_ATTR_MTIME) { attr->st_atim = local_st.st_mtim; } if (to_set & FUSE_SET_ATTR_ATIME_NOW) { clock_gettime(CLOCK_REALTIME, &attr->st_atim); } if (to_set & FUSE_SET_ATTR_MTIME_NOW) { clock_gettime(CLOCK_REALTIME, &attr->st_mtim); } if (to_set & FUSE_SET_ATTR_CTIME) { attr->st_ctim = local_st.st_ctim; } int err = fuse_reply_attr(req, attr, 10.0); // if (err < 0) { // puts("Error"); // fuse_reply_err(req, EINVAL); // return; //} } static void ll_setxattr(fuse_req_t req, fuse_ino_t ino, const char* name, const char* value, size_t size, int flags) { puts("setxattr"); fuse_reply_err(req, EINVAL); } static void ll_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { struct stat s; sendmailfs_stat(ino, &s, strlen(mm.get_value(ino))); puts("getattr"); fuse_reply_attr(req, &s, 2.0); } static void ll_getxattr(fuse_req_t req, fuse_ino_t ino, const char* name, size_t size) { puts("getxattr"); fuse_reply_err(req, EINVAL); } 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); printf("ino2=%d\n", ino2); 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); } } static const struct fuse_lowlevel_ops opener = { .lookup = ll_lookup, .getattr = ll_getattr, .setattr = ll_setattr, .mknod = ll_mknod, .open = ll_open, .write = ll_write, .readdir = ll_readdir, }; int main(int argc, char* argv[]) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); struct fuse_session* se; struct fuse_cmdline_opts opts; struct fuse_loop_config config; int ret = -1; if (fuse_parse_cmdline(&args, &opts) != 0) { return 1; } if (opts.show_help) { printf("usage: %s [options] <mountpoint>\n\n", argv[0]); fuse_cmdline_help(); fuse_lowlevel_help(); ret = 0; goto err_out1; } else if (opts.show_version) { printf("FUSE library version %d\n", fuse_version()); fuse_lowlevel_version(); ret = 0; goto err_out1; } if (opts.mountpoint == NULL) { printf("usage: %s [options] <mountpoint>\n\n", argv[0]); printf(" %s --help\n", argv[0]); ret = 1; goto err_out1; } se = fuse_session_new(&args, &opener, sizeof(opener), NULL); if (fuse_set_signal_handlers(se) != 0) { goto err_out2; } if (fuse_session_mount(se, opts.mountpoint) != 0) { goto err_out3; } fuse_daemonize(opts.foreground); if (opts.singlethread) { ret = fuse_session_loop(se); } else { config.clone_fd = opts.clone_fd; config.max_idle_threads = opts.max_idle_threads; ret = fuse_session_loop_mt(se, &config); } fuse_session_unmount(se); err_out3: fuse_remove_signal_handlers(se); err_out2: fuse_session_destroy(se); err_out1: free(opts.mountpoint); fuse_opt_free_args(&args); return ret ? 1 : 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問