• Miklos Szeredi's avatar
    fuse: support splice() writing to fuse device · dd3bb14f
    Miklos Szeredi authored
    Allow userspace filesystem implementation to use splice() to write to
    the fuse device.  The semantics of using splice() are:
    
     1) buffer the message header and data in a temporary pipe
     2) with a *single* splice() call move the message from the temporary pipe
        to the fuse device
    
    The READ reply message has the most interesting use for this, since
    now the data from an arbitrary file descriptor (which could be a
    regular file, a block device or a socket) can be tranferred into the
    fuse device without having to go through a userspace buffer.  It will
    also allow zero copy moving of pages.
    
    One caveat is that the protocol on the fuse device requires the length
    of the whole message to be written into the header.  But the length of
    the data transferred into the temporary pipe may not be known in
    advance.  The current library implementation works around this by
    using vmplice to write the header and modifying the header after
    splicing the data into the pipe (error handling omitted):
    
    	struct fuse_out_header out;
    
    	iov.iov_base = &out;
    	iov.iov_len = sizeof(struct fuse_out_header);
    	vmsplice(pip[1], &iov, 1, 0);
    	len = splice(input_fd, input_offset, pip[1], NULL, len, 0);
    	/* retrospectively modify the header: */
    	out.len = len + sizeof(struct fuse_out_header);
    	splice(pip[0], NULL, fuse_chan_fd(req->ch), NULL, out.len, flags);
    
    This works since vmsplice only saves a pointer to the data, it does
    not copy the data itself.
    
    Since pipes are currently limited to 16 pages and messages need to be
    spliced atomically, the length of the data is limited to 15 pages (or
    60kB for 4k pages).
    Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
    dd3bb14f
dev.c 31.5 KB