From 84e0ee13c8de454c1e6809e2089a4d09d53f9794 Mon Sep 17 00:00:00 2001 From: Julio Montes Date: Fri, 20 Mar 2020 14:12:38 +0000 Subject: [PATCH] virtcontainers: reimplement `createBlockDevices` Reimplement `createBlockDevices` to identify possible volumes that can be used as pmem devices Signed-off-by: Julio Montes --- virtcontainers/container.go | 31 +++++++++++++++++++++--- virtcontainers/device/manager/manager.go | 16 +++++++----- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/virtcontainers/container.go b/virtcontainers/container.go index bfb32e9a42..4ba7ee2e3a 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -643,6 +643,11 @@ func filterDevices(c *Container, devices []ContainerDevice) (ret []ContainerDevi } func (c *Container) createBlockDevices() error { + if !c.checkBlockDeviceSupport() { + c.Logger().Warn("Block device not supported") + return nil + } + // iterate all mounts and create block device if it's block based. for i, m := range c.mounts { if len(m.BlockDeviceID) > 0 || m.Type != "bind" { @@ -657,18 +662,36 @@ func (c *Container) createBlockDevices() error { return fmt.Errorf("stat %q failed: %v", m.Source, err) } + var di *config.DeviceInfo + var err error + // Check if mount is a block device file. If it is, the block device will be attached to the host // instead of passing this as a shared mount. - if c.checkBlockDeviceSupport() && stat.Mode&unix.S_IFBLK == unix.S_IFBLK { - b, err := c.sandbox.devManager.NewDevice(config.DeviceInfo{ + if stat.Mode&unix.S_IFBLK == unix.S_IFBLK { + di = &config.DeviceInfo{ HostPath: m.Source, ContainerPath: m.Destination, DevType: "b", Major: int64(unix.Major(stat.Rdev)), Minor: int64(unix.Minor(stat.Rdev)), - }) + } + // check whether source can be used as a pmem device + } else if di, err = config.PmemDeviceInfo(m.Source, m.Destination); err != nil { + c.Logger().WithError(err). + WithField("mount-source", m.Source). + Debug("no loop device") + } + + if err == nil && di != nil { + b, err := c.sandbox.devManager.NewDevice(*di) + if err != nil { - return fmt.Errorf("device manager failed to create new device for %q: %v", m.Source, err) + // Do not return an error, try to create + // devices for other mounts + c.Logger().WithError(err).WithField("mount-source", m.Source). + Error("device manager failed to create new device") + continue + } c.mounts[i].BlockDeviceID = b.DeviceID() diff --git a/virtcontainers/device/manager/manager.go b/virtcontainers/device/manager/manager.go index 531cbd1ddb..6a2b665a5e 100644 --- a/virtcontainers/device/manager/manager.go +++ b/virtcontainers/device/manager/manager.go @@ -98,11 +98,15 @@ func (dm *deviceManager) findDeviceByMajorMinor(major, minor int64) api.Device { // createDevice creates one device based on DeviceInfo func (dm *deviceManager) createDevice(devInfo config.DeviceInfo) (dev api.Device, err error) { - path, err := config.GetHostPathFunc(devInfo, dm.vhostUserStoreEnabled, dm.vhostUserStorePath) - if err != nil { - return nil, err + // pmem device may points to block devices or raw files, + // do not change its HostPath. + if !devInfo.Pmem { + path, err := config.GetHostPathFunc(devInfo, dm.vhostUserStoreEnabled, dm.vhostUserStorePath) + if err != nil { + return nil, err + } + devInfo.HostPath = path } - devInfo.HostPath = path defer func() { if err == nil { @@ -119,7 +123,7 @@ func (dm *deviceManager) createDevice(devInfo config.DeviceInfo) (dev api.Device if devInfo.ID, err = dm.newDeviceID(); err != nil { return nil, err } - if isVFIO(path) { + if isVFIO(devInfo.HostPath) { return drivers.NewVFIODevice(&devInfo), nil } else if isVhostUserBlk(devInfo) { if devInfo.DriverOptions == nil { @@ -134,7 +138,7 @@ func (dm *deviceManager) createDevice(devInfo config.DeviceInfo) (dev api.Device devInfo.DriverOptions["block-driver"] = dm.blockDriver return drivers.NewBlockDevice(&devInfo), nil } else { - deviceLogger().WithField("device", path).Info("Device has not been passed to the container") + deviceLogger().WithField("device", devInfo.HostPath).Info("Device has not been passed to the container") return drivers.NewGenericDevice(&devInfo), nil } }