fuse-rs icon indicating copy to clipboard operation
fuse-rs copied to clipboard

read op can't reply with fuse_reply_iov

Open akiradeveloper opened this issue 10 years ago • 3 comments

rust-fuse forces the read op implementation to use ReplyData type as the reply object which is equivalent to fuse_reply_data or fuse_reply_buf because it returns a single buffer.

But, returning by scatter-gather is better for performance. If I understand correctly, that's because read op allows the user to reply with fuse_reply_iov.

This isn't a bug but I think rust-fuse has a reason to rethink its design.

        /**
         * Read data
         *
         * Read should send exactly the number of bytes requested except
         * on EOF or error, otherwise the rest of the data will be
         * substituted with zeroes.  An exception to this is when the file
         * has been opened in 'direct_io' mode, in which case the return
         * value of the read system call will reflect the return value of
         * this operation.
         *
         * fi->fh will contain the value set by the open method, or will
         * be undefined if the open method didn't set any value.
         *
         * Valid replies:
         *   fuse_reply_buf
         *   fuse_reply_iov
         *   fuse_reply_data
         *   fuse_reply_err
         *
         * @param req request handle
         * @param ino the inode number
         * @param size number of bytes to read
         * @param off offset to read from
         * @param fi file information
         */
        void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
                      struct fuse_file_info *fi);

akiradeveloper avatar Jan 25 '15 21:01 akiradeveloper

You're right, scatter-gather-I/O is more performant if data isn't stored in a single linear buffer. Internally, all reply types already use &[&[u8]] (which is similar to an iovec) to pass around data for replying. If we could enhance ReplyData's interface to work with multiple slices, it would allow a more performant reply of data blocks.

The easiest way would be to simply add a method like

    /// Reply to a request with data from the given slices
    pub fn data_slices (mut self, data: &[&[u8]]) {
        self.reply.send(0, data);
    }

Another, more Rust-like approach would be to pass an iterator or a reader that ReplyData uses to gather data and use it for the reply. But maybe this would be more appropriate for a higher level abstraction (where pathnames are used instead of inode numbers like mentioned in README.md)

zargony avatar Jan 27 '15 17:01 zargony

Sorry to start from my misunderstanding of the protocol. fuse 2.9.3 (protocol 7.19) has reply four methods for read but fuse 2.7.2 (protocol 7.8) has only two. So rust-fuse's implementation is conformant to protocol 7.8.

        /**
         * Read data
         *
         * Read should send exactly the number of bytes requested except
         * on EOF or error, otherwise the rest of the data will be
         * substituted with zeroes.  An exception to this is when the file
         * has been opened in 'direct_io' mode, in which case the return
         * value of the read system call will reflect the return value of
         * this operation.
         *
         * fi->fh will contain the value set by the open method, or will
         * be undefined if the open method didn't set any value.
         *
         * Valid replies:
         *   fuse_reply_buf
         *   fuse_reply_err
         *
         * @param req request handle
         * @param ino the inode number
         * @param size number of bytes to read
         * @param off offset to read from
         * @param fi file information
         */
        void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
                      struct fuse_file_info *fi);

So, extending the design so that read op can reply with iov is kind of back-porting.

By the way, do you know what version fuse started to support iov reply for read op? And, why fuse_reply_iov isn't used at all in fuse 2.7.2 (this is really weird)?

akiradeveloper avatar Jan 28 '15 04:01 akiradeveloper

The reply methods actually don't support different protocol versions, they just provide different ways to specify the data that should be sent with a reply (i.e. reply methods are part of the library, not the protocol). Afaik fuse used fuse_reply_iov internally for a long time already. In theory you should be able to use fuse_reply_iov with protocol 7.8 with no problems (if the older libfuse exports this function).

So no matter what protocol version, it would be nice to have a reply method in rust-fuse that sends data by scatter-gather, like the data_slices method I suggested above (we're bound to talk a specific protocol version, but we define our own (Rust-like) interface and do not depend on wether fuse_reply_iov exists or not)

zargony avatar Jan 31 '15 13:01 zargony