sendfile() is broken when sending a file from a Linux guest which is mounted in a shared folder

This is a somewhat important usecase for me which ironically the virtualisation tools which use Apple's virtualization.framework don't encounter.
Code:
wzdd@closedhonk /m/p/Projects [1]> pwd
/media/psf/Projects
wzdd@closedhonk /m/p/Projects> cat testserver.py
# Simple python sendfile() test

import socket
import os

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('', 8000))
    s.listen(1)
    conn, addr = s.accept()
    f = open('test', 'rb')
    os.sendfile(conn.fileno(), f.fileno(), 0, os.path.getsize('test'))
    f.close()
    conn.close()

if __name__ == '__main__':
    main()
wzdd@closedhonk /m/p/Projects> python3 testserver.py
[run 'nc localhost 8000' elsewhere]
Traceback (most recent call last):
  File "/media/psf/Projects/testserver.py", line 18, in <module>
    main()
  File "/media/psf/Projects/testserver.py", line 13, in main
    os.sendfile(conn.fileno(), f.fileno(), 0, os.path.getsize('test'))
OSError: [Errno 22] Invalid argument

On the other hand, running it in a nonshared directory works fine:
Code:
wzdd@closedhonk /m/p/Projects [1]> cd /tmp
wzdd@closedhonk /tmp> python3 testserver.py
[nc localhost 8000]
wzdd@closedhonk /tmp>
[exits cleanly]

'test' is a small text file; it doesn't seem to matter what size it is.
 
Okay, I made a patch which seems to fix it. I'll accept credit in comped subscriptions to Pro. ;-)

Code:
diff --color=auto -ru kmods.orig/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c kmods/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c
--- kmods.orig/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c    2024-04-27 14:43:46
+++ kmods/prl_fs/SharedFolders/Guest/Linux/prl_fs/file.c    2024-04-27 13:54:15
@@ -424,6 +424,8 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
     .read_iter  = generic_file_read_iter,
     .write_iter = generic_file_write_iter,
+    .splice_read = generic_file_splice_read,
+    .splice_write = iter_file_splice_write,
 #else
     .aio_read   = generic_file_aio_read,
     .aio_write  = generic_file_aio_write,
 
Back
Top