'Why Input/Output Error occurs when use ls command in my fuse filesystem?

Why I/O Error causes when I tried ls . command in my fuse filesystem?

My filesystem has a limitation that it only allows mail address type as individual filename and it does not allows sub directory.
Now I want to display a list of file name when use ls . but it does not work.

I understood that it must implement a callback function. (Correspond function is ll_readdir in mycode)

but I have no idea what points are causes the errors.


Update:

Now I use strace command to investigate what system call raise a this error.
According to result of strace, this error caused in getdents64 syscall.

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

Code1 (implementation of 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;

Code2: (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;
}

Code 3: (implementation of readdir callback)

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);
    }
}


Solution 1:[1]

A bit late, but if anyone having this error stumbles upon this thread, they might want to check first whether the filesystem is mounted properly. The Input/output error from getdents64 is symptomatic of a filesystem that was unmounted, but failed for some reason (like a file was still in use when user tried the umount command), so still looks mounted, but no data can be fetched from it.

So in this case, some process could be calling umount (and failing) before you run ls, or the filesystem failed to correctly mount in the first place for some reason.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Craig Phillips