@@ -1113,15 +1113,16 @@ function configure_file_sharing() {
11131113 * ) echo " - WebDAV: On guest: dav://localhost:9843/" ;;
11141114 esac
11151115
1116- # 9P
1116+ # virtiofs or 9p depending on host capability
11171117 if [ " ${guest_os} " != " windows" ] || [ " ${guest_os} " == " windows-server" ]; then
1118- echo -n " - 9P: On guest: "
1119- if [ " ${guest_os} " == " linux" ]; then
1120- echo " sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=104857600 ${PUBLIC_TAG} ~/$( basename " ${PUBLIC} " ) "
1118+ if [ " ${guest_os} " == " linux" ] && [ -n " ${VIRTIOFSD} " ]; then
1119+ echo " - virtiofs: On guest: sudo mount -t virtiofs ${PUBLIC_TAG} ~/$( basename " ${PUBLIC} " ) "
1120+ elif [ " ${guest_os} " == " linux" ]; then
1121+ echo " - 9P: On guest: sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=104857600 ${PUBLIC_TAG} ~/$( basename " ${PUBLIC} " ) "
11211122 elif [ " ${guest_os} " == " macos" ]; then
11221123 # PUBLICSHARE needs to be world writeable for seamless integration with
11231124 # macOS. Test if it is world writeable, and prompt what to do if not.
1124- echo " sudo mount_9p ${PUBLIC_TAG} "
1125+ echo " - 9P: On guest: sudo mount_9p ${PUBLIC_TAG} "
11251126 if [ " ${PUBLIC_PERMS} " != " drwxrwxrwx" ]; then
11261127 echo " - 9P: On host: chmod 777 ${PUBLIC} "
11271128 echo " Required for macOS integration 👆"
@@ -1156,6 +1157,37 @@ function configure_tpm() {
11561157 fi
11571158}
11581159
1160+ function start_virtiofsd() {
1161+ # Start virtiofsd as a background daemon and record its PID so it can be
1162+ # cleaned up when the VM exits. The socket path is placed alongside other
1163+ # VM runtime files in VMDIR.
1164+ if [ -z " ${VIRTIOFSD} " ]; then
1165+ return
1166+ fi
1167+
1168+ VIRTIOFSD_SOCKET=" ${VMDIR} /${VMNAME} .virtiofsd-sock"
1169+ local virtiofsd_args=(
1170+ --socket-path=" ${VIRTIOFSD_SOCKET} "
1171+ --shared-dir=" ${PUBLIC} "
1172+ --announce-submounts
1173+ )
1174+
1175+ echo " ${VIRTIOFSD} ${virtiofsd_args[*]} &" >> " ${VMDIR} /${VMNAME} .sh"
1176+ ${VIRTIOFSD} " ${virtiofsd_args[@]} " >> " ${VMDIR} /${VMNAME} .log" 2>&1 &
1177+ VIRTIOFSD_PID=$!
1178+ sleep 0.25
1179+
1180+ if ! kill -0 " ${VIRTIOFSD_PID} " 2> /dev/null; then
1181+ echo " - WARNING! virtiofsd failed to start; falling back to 9p."
1182+ VIRTIOFSD=" "
1183+ VIRTIOFSD_SOCKET=" "
1184+ VIRTIOFSD_PID=" "
1185+ return
1186+ fi
1187+
1188+ echo " - virtiofsd: ${VIRTIOFSD_SOCKET} (${VIRTIOFSD_PID} )"
1189+ }
1190+
11591191function vm_boot() {
11601192 AUDIO_DEV=" "
11611193 BALLOON=" -device virtio-balloon"
@@ -1481,12 +1513,23 @@ function vm_boot() {
14811513 -drive id=SystemDisk,if=none,format=${disk_format} ,file=" ${disk_img} " ${STATUS_QUO} )
14821514 fi
14831515
1516+ # File sharing: prefer virtiofs (shared memory, lower latency) over 9p when
1517+ # virtiofsd is available; virtiofsd must already be running at this point.
14841518 # https://wiki.qemu.org/Documentation/9psetup
14851519 # https://askubuntu.com/questions/772784/9p-libvirt-qemu-share-modes
14861520 if [ " ${guest_os} " != " windows" ] || [ " ${guest_os} " == " windows-server" ] && [ -n " ${PUBLIC} " ]; then
1487- # shellcheck disable=SC2054
1488- args+=(-fsdev local,id=fsdev0,path=" ${PUBLIC} " ,security_model=mapped-xattr
1489- -device virtio-9p-pci,fsdev=fsdev0,mount_tag=" ${PUBLIC_TAG} " )
1521+ if [ -n " ${VIRTIOFSD_SOCKET} " ]; then
1522+ # virtiofs requires a shared-memory backend; the size mirrors the VM RAM.
1523+ # shellcheck disable=SC2054
1524+ args+=(-object " memory-backend-file,id=mem,size=${RAM_VM} ,mem-path=/dev/shm,share=on"
1525+ -numa node,memdev=mem
1526+ -chardev " socket,id=char0,path=${VIRTIOFSD_SOCKET} "
1527+ -device " vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=${PUBLIC_TAG} " )
1528+ else
1529+ # shellcheck disable=SC2054
1530+ args+=(-fsdev local,id=fsdev0,path=" ${PUBLIC} " ,security_model=mapped-xattr
1531+ -device virtio-9p-pci,fsdev=fsdev0,mount_tag=" ${PUBLIC_TAG} " )
1532+ fi
14901533 fi
14911534
14921535 if [ -n " ${USB_PASSTHROUGH} " ]; then
@@ -1829,6 +1872,16 @@ function fileshare_param_check() {
18291872 PUBLIC_PERMS=$( ${STAT} -c " %A" " ${PUBLIC} " )
18301873 fi
18311874 fi
1875+
1876+ # Prefer virtiofs over 9p when virtiofsd is available and the guest is Linux.
1877+ # virtiofs uses shared memory rather than a transport protocol, giving much
1878+ # lower latency and higher throughput than 9p.
1879+ if [ -n " ${PUBLIC} " ] && [ " ${guest_os} " == " linux" ]; then
1880+ VIRTIOFSD=$( command -v virtiofsd 2> /dev/null || echo " /usr/lib/qemu/virtiofsd" )
1881+ if [ ! -x " ${VIRTIOFSD} " ]; then
1882+ VIRTIOFSD=" "
1883+ fi
1884+ fi
18321885}
18331886
18341887function parse_ports_from_file {
@@ -1936,6 +1989,9 @@ MONITOR_CMD=""
19361989PUBLIC=" "
19371990PUBLIC_PERMS=" "
19381991PUBLIC_TAG=" "
1992+ VIRTIOFSD=" "
1993+ VIRTIOFSD_PID=" "
1994+ VIRTIOFSD_SOCKET=" "
19391995SHORTCUT_OPTIONS=" "
19401996SNAPSHOT_ACTION=" "
19411997SNAPSHOT_TAG=" "
@@ -2219,6 +2275,7 @@ viewer_param_check
22192275fileshare_param_check
22202276
22212277if [ -z " ${VM_PID} " ]; then
2278+ start_virtiofsd
22222279 vm_boot
22232280 start_viewer
22242281 # If the VM being started is an uninstalled Windows VM then auto-skip the press-any key prompt.
0 commit comments