From a5038eb957359a09ccc9337ad009b571899ad909 Mon Sep 17 00:00:00 2001 From: AlexSSD7 Date: Wed, 27 Sep 2023 10:48:23 +0100 Subject: [PATCH] Enable the use of original device block size --- cmd/utils.go | 8 +++++++- vm/cfg.go | 31 +++++++++++++++++++++++++++++-- vm/passthrough.go | 3 ++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cmd/utils.go b/cmd/utils.go index 047c7f5..d5c3a20 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -264,8 +264,14 @@ func getDevicePassthroughConfig(val string) (*vm.PassthroughConfig, error) { return nil, errors.Wrapf(err, "check whether device path is valid '%v'", devPath) } + blockSize, err := osspecifics.GetDeviceLogicalBlockSize(devPath) + if err != nil { + return nil, errors.Wrapf(err, "get logical block size for device '%v'", devPath) + } + return &vm.PassthroughConfig{Block: []vm.BlockDevicePassthroughConfig{{ - Path: devPath, + Path: devPath, + BlockSize: blockSize, }}}, nil default: return nil, fmt.Errorf("unknown device passthrough type '%v'", val) diff --git a/vm/cfg.go b/vm/cfg.go index cbb7d00..382f432 100644 --- a/vm/cfg.go +++ b/vm/cfg.go @@ -24,6 +24,7 @@ import ( "os" "path/filepath" "runtime" + "strconv" "strings" "time" @@ -325,18 +326,44 @@ func configureVMCmdBlockDevicePassthrough(logger *slog.Logger, cfg Config) ([]qe } } + if dev.BlockSize == 0 { + return nil, fmt.Errorf("invalid zero block size specified for device '%v'", dev.Path) + } + + if dev.BlockSize > 65536 { + return nil, fmt.Errorf("block size specified for device '%v' is too large (max is 65536): '%v'", dev.Path, dev.BlockSize) + } + + if dev.BlockSize/512*512 != dev.BlockSize { + return nil, fmt.Errorf("unaligned block size specified for device '%v' (must be in increments of 512): '%v'", dev.Path, dev.BlockSize) + } + + strBlockSize := strconv.FormatUint(dev.BlockSize, 10) + devPath := cleanQEMUPath(dev.Path) + driveID := getUniqueQEMUDriveID() + + driveDevArg, err := qemucli.NewKeyValueArg("device", []qemucli.KeyValueArgItem{ + {Key: "driver", Value: "virtio-blk-pci"}, + {Key: "drive", Value: driveID}, + {Key: "logical_block_size", Value: strBlockSize}, + {Key: "physical_block_size", Value: strBlockSize}, + }) + if err != nil { + return nil, errors.Wrapf(err, "create drive device key-value arg (path '%v')", devPath) + } driveArg, err := qemucli.NewKeyValueArg("drive", []qemucli.KeyValueArgItem{ {Key: "file", Value: devPath}, {Key: "format", Value: "raw"}, - {Key: "if", Value: "virtio"}, + {Key: "if", Value: "none"}, + {Key: "id", Value: driveID}, }) if err != nil { return nil, errors.Wrapf(err, "create drive key-value arg (path '%v')", devPath) } - args = append(args, driveArg) + args = append(args, driveDevArg, driveArg) } return args, nil diff --git a/vm/passthrough.go b/vm/passthrough.go index e8c17f2..36b0746 100644 --- a/vm/passthrough.go +++ b/vm/passthrough.go @@ -22,7 +22,8 @@ type USBDevicePassthroughConfig struct { } type BlockDevicePassthroughConfig struct { - Path string + Path string + BlockSize uint64 } type PassthroughConfig struct {