Re: [PATCH 0/3] vmsplice: make vmsplice a trivial wrapper for preadv2/pwritev2
Joanne Koong <[email protected]> Tue, 16 Jun 2026 02:38:05 -0400
| Newsgroups | org.kernel.vger.linux-api,dev.linux.lists.fuse-devel,dev.linux.lists.patches,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev |
|---|---|
| Message-ID | <CAJnrk1Z_V8TShvWV6zwTMQqXra3J4J5CL5ofFMm9DGoLj9whEw@mail.gmail.com> |
On Mon, Jun 15, 2026 at 9:15 PM Askar Safin <[email protected]> wrote: > > Joanne Koong <[email protected]>: > > > speaking of fuse_dev_splice……_write actually, this series has broken > > > xdg-document-portal! > > > > > > https://github.com/flatpak/xdg-desktop-portal/issues/2026 > > > > > > Specifically what happens is that the EINVAL is returned due to oh.len > > > != nbytes: > > > > > > fuse_dev_do_write: oh.len 16400 != nbytes 15526 > > > > > > (where 16400 == 16384 (read len) + 16, 15526 == 15510 (file len) + 16) > > > > > > After reverting the series, there is no error because oh.len > > > becomes 15526 too. > > > > I think this is because of how libfuse handles eof / short reads. When > > it detects a short read, it fixes up the header length after the > > header was already vmspliced to the pipe because it assumes vmsplice > > mapped the header's page into the pipe by reference. It assumes that > > modifying the header length in place gets then reflected in what the > > pipe later splices out. > > > > The logic for this happens in fuse_send_data_iov() [1]: > > a) sets out->len = headerlen (16) + len (16384) = 16400 in the > > stack-allocated fuse_out_header > > b) vmsplices the header to the pipe > > c) splices the backing file to the pipe. if this hits EOF, it'll get > > back 15510 instead of 16384 > > d) detects the short read [2], fixes up the stack out->len = 16 + 15510 = 15526 > > e) splices the pipe to /dev/fuse > > > > After this patch, step b) is a straight copy which means step d)'s > > fixup doesn't modify what's in the pipe. This could be fixed up in > > libfuse to not depend on modify-after-vmsplice, but I don't think this > > helps for applications using already-released libfuse versions. I > > think this patch needs to be reverted. > > > > Thanks, > > Joanne > > > > [1] https://github.com/libfuse/libfuse/blob/master/lib/fuse_lowlevel.c#L846 > > [2] https://github.com/libfuse/libfuse/blob/master/lib/fuse_lowlevel.c#L956 > > Uh, this is very unfortunate. But I still want to remove vmsplice. > Maybe we can somehow save my patchsets? For example, let's return EINVAL > for this particular combination (writable pipe + SPLICE_F_NONBLOCK). writable pipe + SPLICE_F_NONBLOCK is a valid vmsplice call today, so I think returning -EINVAL would still cause regressions. It happens to be a workaround for libfuse only because libfuse falls back to writev() when vmsplice fails, but I don't think we can assume other callers have the same fallback. Thanks, Joanne > > -- > Askar Safin