Skip to content

feat: expose runtime directory-sharing devices with live share swap#216

Open
jlagedo wants to merge 3 commits into
Code-Hex:mainfrom
jlagedo:feat/runtime-directory-share
Open

feat: expose runtime directory-sharing devices with live share swap#216
jlagedo wants to merge 3 commits into
Code-Hex:mainfrom
jlagedo:feat/runtime-directory-share

Conversation

@jlagedo

@jlagedo jlagedo commented May 23, 2026

Copy link
Copy Markdown

Summary

This adds support for runtime directory sharing: reading the directory-sharing devices off a running VirtualMachine and hot-swapping the directories a guest sees without recreating the VM.

The Virtualization framework exposes VZVirtioFileSystemDevice as a live device on a started VM, with a read/write share property (macOS 12+). Until now vz only surfaced the configuration side (VirtioFileSystemDeviceConfiguration), so callers could set a share before Start() but never change it afterwards. This PR fills that gap.

What's added

VirtualMachine.DirectorySharingDevices() []*VirtioFileSystemDevice
Returns the live directory-sharing devices on a running VM. Mirrors the existing SocketDevices() / USBControllers() accessors. Returns nil on macOS < 12.

VirtioFileSystemDevice — the runtime device (distinct from VirtioFileSystemDeviceConfiguration):

  • SetShare(share DirectoryShare) — swaps the directory share on the running device. The mutation runs on the VM's serial dispatch queue, as the framework requires for all VZVirtualMachine interactions.
  • Share() DirectoryShare — reads back the current share (also on the VM queue), reconstructing the concrete *SingleDirectoryShare / *MultipleDirectoryShare via Obj-C class introspection. Restores get/set symmetry with the underlying share property.

This lets a host add or remove the directories a guest sees while the VM keeps running.

Implementation notes

  • Follows the established runtime-device pattern (socket.go, usb.go): the device wrapper stores the VM's dispatchQueue and embeds *pointer.
  • The device wrapper itself uses no release finalizer — these objects are owned by the VM's array (Apple's get-rule), matching VirtioSocketDevice. Only the value returned by Share() is retained on the C side and released via a Go finalizer, since it crosses the boundary as an owned object.
  • All live calls go through dispatch_sync on the VM queue, consistent with the memory-balloon runtime device.
  • Gated on macOS 12 in both the Go and Objective-C layers.

Testing

make download_kernel && make test (run locally on Apple silicon, codesigned):

  • TestDirectorySharingDevices — a configured file-system device is returned from a created VM.
  • TestVirtioFileSystemDeviceSetShare — boots a VM with a single-directory share, asserts Share() reports *SingleDirectoryShare, mounts in-guest and sees the file; then hot-swaps to a multiple-directory share via SetShare, asserts Share() now reports *MultipleDirectoryShare, remounts in-guest and verifies the swapped-in content is visible while the original file is gone.

Existing TestSingleDirectoryShare / TestMultipleDirectoryShare continue to pass (no regression). go vet ./... is clean.

Test plan

  • go build ./...
  • go vet ./...
  • make test (new + existing shared-directory tests pass, codesigned, real guest)

🤖 Generated with Claude Code

jlagedo and others added 2 commits May 23, 2026 17:46
Add VZVirtualMachine.directorySharingDevices() and a runtime
VirtioFileSystemDevice type with SetShare(), so a host can change which
directories a guest sees on a running VM (macOS 12+) without recreating it.
Apple supports this (VZVirtioFileSystemDevice.share is get/set on the runtime
device, reachable via VZVirtualMachine.directorySharingDevices), but the binding
only exposed the config-time setter.

Mirrors the existing SocketDevices() pattern: NSArray -> ToPointerSlice -> wrap
each pointer with the VM's serial dispatch queue. SetShare runs the mutation on
that queue, as the framework requires.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose a Share() getter on the running file system device so the directory
share set via SetShare (or at configuration time) can be read back, restoring
get/set symmetry with the VZVirtioFileSystemDevice.share property. The getter
reads on the VM's serial dispatch queue and reconstructs the concrete
*SingleDirectoryShare or *MultipleDirectoryShare via Obj-C class introspection.

Add integration tests covering the runtime directory-sharing API:
- TestDirectorySharingDevices verifies a configured device is returned.
- TestVirtioFileSystemDeviceSetShare boots a VM, asserts the reported share
  type, hot-swaps single -> multiple share at runtime, and verifies the guest
  sees the swapped-in content after remount.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread shared_directory_test.go Outdated
t.Skip("VirtioFileSystemDevice is supported from macOS 12")
}

const tag = "swap"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this called "swap"?
Can be confused with swap filesystem

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — renamed the tag to "shared" to avoid confusion with swap space. Fixed in f556faa.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds runtime (live) support for Virtio directory sharing devices by exposing directory-sharing devices from a VirtualMachine and enabling hot-swapping the guest-visible directory share without recreating the VM (macOS 12+).

Changes:

  • Add Objective-C bridge functions to fetch VZVirtualMachine.directorySharingDevices and get/set VZVirtioFileSystemDevice.share on the VM dispatch queue.
  • Introduce a runtime VirtioFileSystemDevice Go wrapper with SetShare/Share plus VirtualMachine.DirectorySharingDevices().
  • Add integration tests covering runtime device discovery and live share swapping in-guest.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
virtualization_12.m Adds Obj-C bridge functions for runtime directory-sharing devices and live share get/set on the VM queue.
virtualization_12.h Declares the new Obj-C bridge function prototypes for Go to call.
shared_directory.go Adds the runtime VirtioFileSystemDevice wrapper and VirtualMachine.DirectorySharingDevices() accessor.
shared_directory_test.go Adds tests verifying runtime device discovery and live share swapping behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread shared_directory.go
Comment on lines +213 to +215
func (d *VirtioFileSystemDevice) SetShare(share DirectoryShare) {
C.setShareVZVirtioFileSystemDevice(objc.Ptr(d), objc.Ptr(share), d.dispatchQueue)
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f556faa: SetShare now passes NULL for a nil share instead of panicking.

Comment thread virtualization_12.m
Comment on lines +62 to +66
/*!
@abstract Return the list of directory sharing devices configured on this virtual machine. Return an empty array if none is configured.
@see VZDirectorySharingDevice
@see VZVirtualMachineConfiguration
*/

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f556faa: doc now references VZVirtualMachine.

- SetShare passes NULL for a nil share instead of panicking
- VZVirtualMachine_directorySharingDevices doc references VZVirtualMachine
- rename confusing virtiofs test tag "swap" -> "shared"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants