Add qemu virtiofs command line option

Enables support for C version of virtiofs
A qemu option allows to specify virtiofsd path.
config.StatePath is used for storing the virtiofs sockets
Note that virtiofsd requires to start as root

Signed-off-by: Frédéric Dalleau <frederic.dalleau@docker.com>
This commit is contained in:
Frédéric Dalleau 2023-01-02 16:31:32 +01:00
parent f0f21bec52
commit 13426fe805

View File

@ -23,28 +23,30 @@ const (
// QemuConfig contains the config for Qemu
type QemuConfig struct {
Path string
ISOBoot bool
UEFI bool
SquashFS bool
Kernel bool
GUI bool
Disks Disks
ISOImages []string
StatePath string
FWPath string
Arch string
CPUs string
Memory string
Accel string
Detached bool
QemuBinPath string
QemuImgPath string
PublishedPorts []string
NetdevConfig string
UUID uuid.UUID
USB bool
Devices []string
Path string
ISOBoot bool
UEFI bool
SquashFS bool
Kernel bool
GUI bool
Disks Disks
ISOImages []string
StatePath string
FWPath string
Arch string
CPUs string
Memory string
Accel string
Detached bool
QemuBinPath string
QemuImgPath string
PublishedPorts []string
NetdevConfig string
UUID uuid.UUID
USB bool
Devices []string
VirtiofsdBinPath string
VirtiofsShares []string
}
const (
@ -119,23 +121,25 @@ func generateMAC() net.HardwareAddr {
func runQEMUCmd() *cobra.Command {
var (
enableGUI bool
uefiBoot bool
isoBoot bool
squashFSBoot bool
kernelBoot bool
state string
data string
dataPath string
fw string
accel string
arch string
qemuCmd string
qemuDetached bool
networking string
usbEnabled bool
deviceFlags multipleFlag
publishFlags multipleFlag
enableGUI bool
uefiBoot bool
isoBoot bool
squashFSBoot bool
kernelBoot bool
state string
data string
dataPath string
fw string
accel string
arch string
qemuCmd string
qemuDetached bool
networking string
usbEnabled bool
deviceFlags multipleFlag
publishFlags multipleFlag
virtiofsdCmd string
virtiofsShares []string
)
cmd := &cobra.Command{
@ -279,34 +283,43 @@ func runQEMUCmd() *cobra.Command {
}
config := QemuConfig{
Path: path,
ISOBoot: isoBoot,
UEFI: uefiBoot,
SquashFS: squashFSBoot,
Kernel: kernelBoot,
GUI: enableGUI,
Disks: disks,
ISOImages: isoPaths,
StatePath: state,
FWPath: fw,
Arch: arch,
CPUs: fmt.Sprintf("%d", cpus),
Memory: fmt.Sprintf("%d", mem),
Accel: accel,
Detached: qemuDetached,
QemuBinPath: qemuCmd,
PublishedPorts: publishFlags,
NetdevConfig: netdevConfig,
UUID: vmUUID,
USB: usbEnabled,
Devices: deviceFlags,
Path: path,
ISOBoot: isoBoot,
UEFI: uefiBoot,
SquashFS: squashFSBoot,
Kernel: kernelBoot,
GUI: enableGUI,
Disks: disks,
ISOImages: isoPaths,
StatePath: state,
FWPath: fw,
Arch: arch,
CPUs: fmt.Sprintf("%d", cpus),
Memory: fmt.Sprintf("%d", mem),
Accel: accel,
Detached: qemuDetached,
QemuBinPath: qemuCmd,
PublishedPorts: publishFlags,
NetdevConfig: netdevConfig,
UUID: vmUUID,
USB: usbEnabled,
Devices: deviceFlags,
VirtiofsdBinPath: virtiofsdCmd,
VirtiofsShares: virtiofsShares,
}
config, err = discoverBinaries(config)
config, err = discoverQemu(config)
if err != nil {
return err
}
if len(config.VirtiofsShares) > 0 {
config, err = discoverVirtiofsd(config)
if err != nil {
return err
}
}
if err = runQemuLocal(config); err != nil {
return err
}
@ -351,6 +364,10 @@ func runQEMUCmd() *cobra.Command {
cmd.Flags().BoolVar(&usbEnabled, "usb", false, "Enable USB controller")
cmd.Flags().Var(&deviceFlags, "device", "Add USB host device(s). Format driver[,prop=value][,...] -- add device, like -device on the qemu command line.")
// Filesystems
cmd.Flags().StringVar(&virtiofsdCmd, "virtiofsd", "", "Path to virtiofsd binary (otherwise look in /usr/lib/qemu and /usr/local/lib/qemu)")
cmd.Flags().StringArrayVar(&virtiofsShares, "virtiofs", []string{}, "Directory shared on virtiofs")
return cmd
}
@ -398,6 +415,25 @@ func runQemuLocal(config QemuConfig) error {
return fmt.Errorf("Detached mode is only supported when running in a container, not locally")
}
if len(config.VirtiofsShares) > 0 {
args = append(args, "-object", "memory-backend-memfd,id=mem,size="+config.Memory+"M,share=on", "-numa", "node,memdev=mem")
}
for index, source := range config.VirtiofsShares {
socket := filepath.Join(config.StatePath, fmt.Sprintf("%s%d", "virtiofs", index))
cmd := exec.Command(config.VirtiofsdBinPath,
"--socket-path="+socket,
"-o", fmt.Sprintf("source=%s", source))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return fmt.Errorf("virtiofs server cannot start: %v", err)
}
args = append(args, "-chardev", fmt.Sprintf("socket,id=char%d,path=%s", index, socket))
args = append(args, "-device",
fmt.Sprintf("vhost-user-fs-pci,chardev=char%d,tag=virtiofs%d", index, index))
}
qemuCmd := exec.Command(config.QemuBinPath, args...)
// If verbosity is enabled print out the full path/arguments
log.Debugf("%v\n", qemuCmd.Args)
@ -589,7 +625,7 @@ func buildQemuCmdline(config QemuConfig) (QemuConfig, []string) {
return config, qemuArgs
}
func discoverBinaries(config QemuConfig) (QemuConfig, error) {
func discoverQemu(config QemuConfig) (QemuConfig, error) {
if config.QemuImgPath != "" {
return config, nil
}
@ -611,6 +647,16 @@ func discoverBinaries(config QemuConfig) (QemuConfig, error) {
return config, nil
}
func discoverVirtiofsd(config QemuConfig) (QemuConfig, error) {
if config.VirtiofsdBinPath != "" {
return config, nil
}
virtiofsdPath := filepath.Dir(config.QemuBinPath)
config.VirtiofsdBinPath = filepath.Join(virtiofsdPath, "..", "lib", "qemu", "virtiofsd")
return config, nil
}
func buildQemuForwardings(publishFlags multipleFlag) (string, error) {
if len(publishFlags) == 0 {
return "", nil