Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
runtime: Enable file based backend
Browse files Browse the repository at this point in the history
A file based memory backend mapped to the host, fot eg: '/dev/shm' will
be used by virtio-fs for performance reasons. This change is a generic
implementation of that for kata. This will be enabled default for
virtio-fs negating the need to enable hugepages in that scenario. This
option can be used without virtio-fs by setting 'file_mem_backend' to
the location in the configuration file. Default value is an empty
string.

Fixes: #1656
Signed-off-by: Ganesh Maharaj Mahalingam <[email protected]>
  • Loading branch information
Ganesh Maharaj Mahalingam committed May 24, 2019
1 parent 9a27ac2 commit a41894d
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 3 deletions.
6 changes: 6 additions & 0 deletions cli/config/configuration-qemu.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ enable_iothreads = @DEFENABLEIOTHREADS@
# result in memory pre allocation
#enable_hugepages = true

# Enable file based guest memory support. The default is an empty string which
# will disable this feature. In the case of virtio-fs, this is enabled
# automatically and '/dev/shm' is used as the backing folder.
# This option will be ignored if VM templating is enabled.
#file_mem_backend = ""

# Enable swap of vm memory. Default false.
# The behaviour is undefined if mem_prealloc is also set to true
#enable_swap = true
Expand Down
1 change: 1 addition & 0 deletions pkg/katautils/config-settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const defaultBlockDeviceCacheNoflush bool = false
const defaultEnableIOThreads bool = false
const defaultEnableMemPrealloc bool = false
const defaultEnableHugePages bool = false
const defaultFileBackedMemRootDir string = ""
const defaultEnableSwap bool = false
const defaultEnableDebug bool = false
const defaultDisableNestingChecks bool = false
Expand Down
3 changes: 3 additions & 0 deletions pkg/katautils/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type hypervisor struct {
DisableBlockDeviceUse bool `toml:"disable_block_device_use"`
MemPrealloc bool `toml:"enable_mem_prealloc"`
HugePages bool `toml:"enable_hugepages"`
FileBackedMemRootDir string `toml:"file_mem_backend"`
Swap bool `toml:"enable_swap"`
Debug bool `toml:"enable_debug"`
DisableNestingChecks bool `toml:"disable_nesting_checks"`
Expand Down Expand Up @@ -584,6 +585,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
VirtioFSCache: h.VirtioFSCache,
MemPrealloc: h.MemPrealloc,
HugePages: h.HugePages,
FileBackedMemRootDir: h.FileBackedMemRootDir,
Mlock: !h.Swap,
Debug: h.Debug,
DisableNestingChecks: h.DisableNestingChecks,
Expand Down Expand Up @@ -850,6 +852,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig {
DefaultBridges: defaultBridgesCount,
MemPrealloc: defaultEnableMemPrealloc,
HugePages: defaultEnableHugePages,
FileBackedMemRootDir: defaultFileBackedMemRootDir,
Mlock: !defaultEnableSwap,
Debug: defaultEnableDebug,
DisableNestingChecks: defaultDisableNestingChecks,
Expand Down
3 changes: 3 additions & 0 deletions virtcontainers/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ type HypervisorConfig struct {
// HugePages specifies if the memory should be pre-allocated from huge pages
HugePages bool

// File based memory backend root directory
FileBackedMemRootDir string

// Realtime Used to enable/disable realtime
Realtime bool

Expand Down
3 changes: 3 additions & 0 deletions virtcontainers/persist/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ type HypervisorConfig struct {
// HugePages specifies if the memory should be pre-allocated from huge pages
HugePages bool

// File based memory backend root directory
FileBackedMemRootDir string

// Realtime Used to enable/disable realtime
Realtime bool

Expand Down
37 changes: 34 additions & 3 deletions virtcontainers/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ const (
qmpCapErrMsg = "Failed to negoatiate QMP capabilities"
qmpExecCatCmd = "exec:cat"

scsiControllerID = "scsi0"
rngID = "rng0"
vsockKernelOption = "agent.use_vsock"
scsiControllerID = "scsi0"
rngID = "rng0"
vsockKernelOption = "agent.use_vsock"
fallbackFileBackedMemDir = "/dev/shm"
)

var qemuMajorVersion int
Expand Down Expand Up @@ -423,6 +424,23 @@ func (q *qemu) setupTemplate(knobs *govmmQemu.Knobs, memory *govmmQemu.Memory) g
return incoming
}

func (q *qemu) setupFileBackedMem(knobs *govmmQemu.Knobs, memory *govmmQemu.Memory) {
var target string
if q.config.FileBackedMemRootDir != "" {
target = q.config.FileBackedMemRootDir
} else {
target = fallbackFileBackedMemDir
}
if _, err := os.Stat(target); err != nil {
q.Logger().WithError(err).Error("File backed memory location does not exist")
return
}

knobs.FileBackedMem = true
knobs.FileBackedMemShared = true
memory.Path = target
}

// createSandbox is the Hypervisor sandbox creation implementation for govmmQemu.
func (q *qemu) createSandbox(ctx context.Context, id string, hypervisorConfig *HypervisorConfig, store *store.VCStore) error {
// Save the tracing context
Expand Down Expand Up @@ -476,6 +494,19 @@ func (q *qemu) createSandbox(ctx context.Context, id string, hypervisorConfig *H

incoming := q.setupTemplate(&knobs, &memory)

// With the current implementations, VM templating will not work with file
// based memory (stand-alone) or virtiofs. This is because VM templating
// builds the first VM with file-backed memory and shared=on and the
// subsequent ones with shared=off. virtio-fs always requires shared=on for
// memory.
if q.config.SharedFS == config.VirtioFS || q.config.FileBackedMemRootDir != "" {
if !(q.config.BootToBeTemplate || q.config.BootFromTemplate) {

This comment has been minimized.

Copy link
@freeHackOfJeff

freeHackOfJeff Aug 12, 2019

Consider readability, if (!q.config.BootToBeTemplate && !q.config.BootFromTemplate) {} is preferred.

This comment has been minimized.

Copy link
@egernst

egernst Aug 12, 2019

Member

/cc @ganeshmaharaj

I like de morgan’s law :). @freeHackOfJeff: 1) love the GitHub handle, 2) can you send PR? I’m fine with the change.

This comment has been minimized.

Copy link
@ganeshmaharaj

ganeshmaharaj Aug 12, 2019

Contributor

Works for me. 😀

This comment has been minimized.

Copy link
@freeHackOfJeff

freeHackOfJeff Aug 13, 2019

Sure @egernst, will post once another test done. :-P.

q.setupFileBackedMem(&knobs, &memory)
} else {
return errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")
}
}

rtc := govmmQemu.RTC{
Base: "utc",
DriftFix: "slew",
Expand Down
68 changes: 68 additions & 0 deletions virtcontainers/qemu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"testing"

govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -482,3 +483,70 @@ func TestQemuAddDeviceToBridge(t *testing.T) {
exceptErr = errors.New("failed to get available address from bridges")
assert.Equal(exceptErr, err)
}

func TestQemuFileBackedMem(t *testing.T) {
assert := assert.New(t)

// Check default Filebackedmem location for virtio-fs
sandbox, err := createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q := &qemu{}
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, true)
assert.Equal(q.qemuConfig.Knobs.FileBackedMemShared, true)
assert.Equal(q.qemuConfig.Memory.Path, fallbackFileBackedMemDir)

// Check failure for VM templating
sandbox, err = createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q = &qemu{}
sandbox.config.HypervisorConfig.BootToBeTemplate = true
sandbox.config.HypervisorConfig.SharedFS = config.VirtioFS
sandbox.config.HypervisorConfig.MemoryPath = fallbackFileBackedMemDir

err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store)

expectErr := errors.New("VM templating has been enabled with either virtio-fs or file backed memory and this configuration will not work")
assert.Equal(expectErr, err)

// Check Setting of non-existent shared-mem path
sandbox, err = createQemuSandboxConfig()
if err != nil {
t.Fatal(err)
}
q = &qemu{}
sandbox.config.HypervisorConfig.FileBackedMemRootDir = "/tmp/xyzabc"
if err = q.createSandbox(context.Background(), sandbox.id, &sandbox.config.HypervisorConfig, sandbox.store); err != nil {
t.Fatal(err)
}
assert.Equal(q.qemuConfig.Knobs.FileBackedMem, false)
assert.Equal(q.qemuConfig.Knobs.FileBackedMemShared, false)
assert.Equal(q.qemuConfig.Memory.Path, "")
}

func createQemuSandboxConfig() (*Sandbox, error) {

qemuConfig := newQemuConfig()
sandbox := Sandbox{
ctx: context.Background(),
id: "testSandbox",
config: &SandboxConfig{
HypervisorConfig: qemuConfig,
},
}

vcStore, err := store.NewVCSandboxStore(sandbox.ctx, sandbox.id)
if err != nil {
return &Sandbox{}, err
}
sandbox.store = vcStore

return &sandbox, nil
}

0 comments on commit a41894d

Please sign in to comment.