qemu/qmp: add new function ExecuteBlockdevAddWithCache

ExecuteBlockdevAddWithCache has two more parameters direct and noFlush
than ExecuteBlockdevAdd.
They are cache-related options for block devices that are described in
https://github.com/qemu/qemu/blob/master/qapi/block-core.json.
direct denotes whether use of O_DIRECT (bypass the host page cache)
is enabled.  noFlush denotes whether flush requests for the device are
ignored.

Signed-off-by: Hui Zhu <teawater@hyper.sh>
This commit is contained in:
Hui Zhu 2018-11-19 12:33:05 +08:00
parent a0b0c86e9c
commit 110d2fa049
2 changed files with 58 additions and 5 deletions

View File

@ -722,11 +722,7 @@ func (q *QMP) ExecuteQuit(ctx context.Context) error {
return q.executeCommand(ctx, "quit", nil, nil) return q.executeCommand(ctx, "quit", nil, nil)
} }
// ExecuteBlockdevAdd sends a blockdev-add to the QEMU instance. device is the func (q *QMP) blockdevAddBaseArgs(device, blockdevID string) (map[string]interface{}, map[string]interface{}) {
// path of the device to add, e.g., /dev/rdb0, and blockdevID is an identifier
// used to name the device. As this identifier will be passed directly to QMP,
// it must obey QMP's naming rules, e,g., it must start with a letter.
func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string) error {
var args map[string]interface{} var args map[string]interface{}
blockdevArgs := map[string]interface{}{ blockdevArgs := map[string]interface{}{
@ -747,6 +743,39 @@ func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string)
} }
} }
return args, blockdevArgs
}
// ExecuteBlockdevAdd sends a blockdev-add to the QEMU instance. device is the
// path of the device to add, e.g., /dev/rdb0, and blockdevID is an identifier
// used to name the device. As this identifier will be passed directly to QMP,
// it must obey QMP's naming rules, e,g., it must start with a letter.
func (q *QMP) ExecuteBlockdevAdd(ctx context.Context, device, blockdevID string) error {
args, _ := q.blockdevAddBaseArgs(device, blockdevID)
return q.executeCommand(ctx, "blockdev-add", args, nil)
}
// ExecuteBlockdevAddWithCache has two more parameters direct and noFlush
// than ExecuteBlockdevAdd.
// They are cache-related options for block devices that are described in
// https://github.com/qemu/qemu/blob/master/qapi/block-core.json.
// direct denotes whether use of O_DIRECT (bypass the host page cache)
// is enabled. noFlush denotes whether flush requests for the device are
// ignored.
func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, device, blockdevID string, direct, noFlush bool) error {
args, blockdevArgs := q.blockdevAddBaseArgs(device, blockdevID)
if q.version.Major < 2 || (q.version.Major == 2 && q.version.Minor < 9) {
return fmt.Errorf("versions of qemu (%d.%d) older than 2.9 do not support set cache-related options for block devices",
q.version.Major, q.version.Minor)
}
blockdevArgs["cache"] = map[string]interface{}{
"direct": direct,
"no-flush": noFlush,
}
return q.executeCommand(ctx, "blockdev-add", args, nil) return q.executeCommand(ctx, "blockdev-add", args, nil)
} }

View File

@ -403,6 +403,30 @@ func TestQMPBlockdevAdd(t *testing.T) {
<-disconnectedCh <-disconnectedCh
} }
// Checks that the blockdev-add with cache options command is correctly sent.
//
// We start a QMPLoop, send the blockdev-add with cache options
// command and stop the loop.
//
// The blockdev-add with cache options command should be correctly sent and
// the QMP loop should exit gracefully.
func TestQMPBlockdevAddWithCache(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
buf.AddCommand("blockdev-add", nil, "return", nil)
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
q.version = checkVersion(t, connectedCh)
err := q.ExecuteBlockdevAddWithCache(context.Background(), "/dev/rbd0",
fmt.Sprintf("drive_%s", volumeUUID), true, true)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
q.Shutdown()
<-disconnectedCh
}
// Checks that the netdev_add command is correctly sent. // Checks that the netdev_add command is correctly sent.
// //
// We start a QMPLoop, send the netdev_add command and stop the loop. // We start a QMPLoop, send the netdev_add command and stop the loop.