Re: [PATCH 0/3] vmsplice: make vmsplice a trivial wrapper for preadv2/pwritev2
Askar Safin <[email protected]> Tue, 16 Jun 2026 04:15:09 +0300
| 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 | <[email protected]> |
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). -- Askar Safin