Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions internal/guest/storage/devicemapper/devicemapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (
_DM_SUSPEND_FLAG = 1 << 1
_DM_PERSISTENT_DEV_FLAG = 1 << 3

BlockSize = 512
blockSize = 512
)

const (
Expand Down Expand Up @@ -186,11 +186,11 @@ func LinearTarget(sectorStart, lengthBlocks int64, path string, deviceStart int6
}
}

// PMemLinearTarget constructs a LinearTarget for PMem device with 0 sector start and length/device start
// zeroSectorLinearTarget creates a Target for devices with 0 sector start and length/device start
// expected to be in bytes rather than blocks
func PMemLinearTarget(lengthBytes int64, path string, deviceStartBytes int64) Target {
lengthInBlocks := lengthBytes / BlockSize
startInBlocks := deviceStartBytes / BlockSize
func zeroSectorLinearTarget(lengthBytes int64, path string, deviceStartBytes int64) Target {
lengthInBlocks := lengthBytes / blockSize
startInBlocks := deviceStartBytes / blockSize
return LinearTarget(0, lengthInBlocks, path, startInBlocks)
}

Expand Down
80 changes: 80 additions & 0 deletions internal/guest/storage/devicemapper/targets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// +build linux

package devicemapper

import (
"context"
"fmt"

"github.com/pkg/errors"
"go.opencensus.io/trace"

"github.com/Microsoft/hcsshim/internal/guest/prot"
"github.com/Microsoft/hcsshim/internal/oc"
)

// CreateZeroSectorLinearTarget creates dm-linear target for a device at `devPath` and `mappingInfo`, returns
// virtual block device path.
func CreateZeroSectorLinearTarget(ctx context.Context, devPath, devName string, mappingInfo *prot.DeviceMappingInfo) (_ string, err error) {
_, span := trace.StartSpan(ctx, "devicemapper::CreateZeroSectorLinearTarget")
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

linearTarget := zeroSectorLinearTarget(mappingInfo.DeviceSizeInBytes, devPath, mappingInfo.DeviceOffsetInBytes)

span.AddAttributes(
trace.StringAttribute("devicePath", devPath),
trace.Int64Attribute("deviceStart", mappingInfo.DeviceOffsetInBytes),
trace.Int64Attribute("sectorSize", mappingInfo.DeviceSizeInBytes),
trace.StringAttribute("linearTable", fmt.Sprintf("%s: '%d %d %s'", devName, linearTarget.SectorStart, linearTarget.LengthInBlocks, linearTarget.Params)))

devMapperPath, err := CreateDevice(devName, CreateReadOnly, []Target{linearTarget})
if err != nil {
return "", errors.Wrapf(err, "failed to create dm-linear target, device=%s, offset=%d", devPath, mappingInfo.DeviceOffsetInBytes)
}

return devMapperPath, nil
}

// CreateVerityTarget creates a dm-verity target for a given device and returns created virtual block device path.
//
// Example verity target table:
// 0 417792 verity 1 /dev/sdb /dev/sdc 4096 4096 52224 1 sha256 2aa4f7b7b6...f4952060e8 762307f4bc8...d2a6b7595d8..
// | | | | | | | | | | | | |
// start| | | data_dev | data_block | #blocks | hash_alg root_digest salt
// size | version hash_dev | hash_offset
// target hash_block
func CreateVerityTarget(ctx context.Context, devPath, devName string, verityInfo *prot.DeviceVerityInfo) (_ string, err error) {
_, span := trace.StartSpan(ctx, "devicemapper::CreateVerityTarget")
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

dmBlocks := verityInfo.Ext4SizeInBytes / blockSize
dataBlocks := verityInfo.Ext4SizeInBytes / int64(verityInfo.BlockSize)
hashOffsetBlocks := dataBlocks
if verityInfo.SuperBlock {
hashOffsetBlocks++
}
hashes := fmt.Sprintf("%s %s %s", verityInfo.Algorithm, verityInfo.RootDigest, verityInfo.Salt)
blkInfo := fmt.Sprintf("%d %d %d %d", verityInfo.BlockSize, verityInfo.BlockSize, dataBlocks, hashOffsetBlocks)
devices := fmt.Sprintf("%s %s", devPath, devPath)

verityTarget := Target{
SectorStart: 0,
LengthInBlocks: dmBlocks,
Type: "verity",
Params: fmt.Sprintf("%d %s %s %s", verityInfo.Version, devices, blkInfo, hashes),
}

span.AddAttributes(
trace.StringAttribute("devicePath", devPath),
trace.Int64Attribute("sectorSize", dmBlocks),
trace.StringAttribute("verityTable", verityTarget.Params))

mapperPath, err := CreateDevice(devName, CreateReadOnly, []Target{verityTarget})
if err != nil {
return "", errors.Wrapf(err, "failed to create dm-verity target. device=%s", devPath)
}

return mapperPath, nil
}
77 changes: 3 additions & 74 deletions internal/guest/storage/pmem/pmem.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,12 @@ func Mount(ctx context.Context, device uint32, target string, mappingInfo *prot.
return errors.Wrapf(err, "won't mount pmem device %d onto %s", device, target)
}

// dm linear target has to be created first. when verity info is also present, the linear target becomes the data
// dm-linear target has to be created first. When verity info is also present, the linear target becomes the data
// device instead of the original VPMem.
if mappingInfo != nil {
dmLinearName := fmt.Sprintf(linearDeviceFmt, device, mappingInfo.DeviceOffsetInBytes, mappingInfo.DeviceSizeInBytes)
if dmLinearPath, err := createDMLinearTarget(mCtx, devicePath, dmLinearName, target, mappingInfo); err != nil {
if devicePath, err = dm.CreateZeroSectorLinearTarget(mCtx, devicePath, dmLinearName, mappingInfo); err != nil {
return err
} else {
devicePath = dmLinearPath
}
defer func() {
if err != nil {
Expand All @@ -105,10 +103,8 @@ func Mount(ctx context.Context, device uint32, target string, mappingInfo *prot.

if verityInfo != nil {
dmVerityName := fmt.Sprintf(verityDeviceFmt, device, verityInfo.RootDigest)
if dmVerityPath, err := createDMVerityTarget(mCtx, devicePath, dmVerityName, target, verityInfo); err != nil {
if devicePath, err = dm.CreateVerityTarget(mCtx, devicePath, dmVerityName, verityInfo); err != nil {
return err
} else {
devicePath = dmVerityPath
}
defer func() {
if err != nil {
Expand All @@ -122,73 +118,6 @@ func Mount(ctx context.Context, device uint32, target string, mappingInfo *prot.
return mountInternal(mCtx, devicePath, target)
}

// createDMLinearTarget creates dm-linear target from a given `device` slot location and `mappingInfo`
func createDMLinearTarget(ctx context.Context, devPath, devName string, target string, mappingInfo *prot.DeviceMappingInfo) (_ string, err error) {
_, span := trace.StartSpan(ctx, "pmem::createDMLinearTarget")
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

linearTarget := dm.PMemLinearTarget(mappingInfo.DeviceSizeInBytes, devPath, mappingInfo.DeviceOffsetInBytes)

span.AddAttributes(
trace.StringAttribute("devicePath", devPath),
trace.Int64Attribute("deviceStart", mappingInfo.DeviceOffsetInBytes),
trace.Int64Attribute("sectorSize", mappingInfo.DeviceSizeInBytes),
trace.StringAttribute("target", target),
trace.StringAttribute("linearTable", fmt.Sprintf("%s: '%d %d %s'", devName, linearTarget.SectorStart, linearTarget.LengthInBlocks, linearTarget.Params)))

devMapperPath, err := dm.CreateDevice(devName, dm.CreateReadOnly, []dm.Target{linearTarget})
if err != nil {
return "", errors.Wrapf(err, "failed to create dm-linear target: pmem device: %s, offset: %d", devPath, mappingInfo.DeviceOffsetInBytes)
}

return devMapperPath, nil
}

// createDMVerityTarget creates a dm-verity target for a given device and mounts that target instead of the device itself
//
// verity target table
// 0 417792 verity 1 /dev/sdb /dev/sdc 4096 4096 52224 1 sha256 2aa4f7b7b6...f4952060e8 762307f4bc8...d2a6b7595d8..
// | | | | | | | | | | | | |
// start| | | data_dev | data_block | #blocks | hash_alg root_digest salt
// size | version hash_dev | hash_offset
// target hash_block
func createDMVerityTarget(ctx context.Context, devPath, devName, target string, verityInfo *prot.DeviceVerityInfo) (_ string, err error) {
_, span := trace.StartSpan(ctx, "pmem::createDMVerityTarget")
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()

dmBlocks := verityInfo.Ext4SizeInBytes / dm.BlockSize
dataBlocks := verityInfo.Ext4SizeInBytes / int64(verityInfo.BlockSize)
hashOffsetBlocks := dataBlocks
if verityInfo.SuperBlock {
hashOffsetBlocks++
}
hashes := fmt.Sprintf("%s %s %s", verityInfo.Algorithm, verityInfo.RootDigest, verityInfo.Salt)
blkInfo := fmt.Sprintf("%d %d %d %d", verityInfo.BlockSize, verityInfo.BlockSize, dataBlocks, hashOffsetBlocks)
devices := fmt.Sprintf("%s %s", devPath, devPath)

verityTarget := dm.Target{
SectorStart: 0,
LengthInBlocks: dmBlocks,
Type: "verity",
Params: fmt.Sprintf("%d %s %s %s", verityInfo.Version, devices, blkInfo, hashes),
}

span.AddAttributes(
trace.StringAttribute("devicePath", devPath),
trace.StringAttribute("target", target),
trace.Int64Attribute("sectorSize", dmBlocks),
trace.StringAttribute("verityTable", verityTarget.Params))

mapperPath, err := dm.CreateDevice(devName, dm.CreateReadOnly, []dm.Target{verityTarget})
if err != nil {
return "", errors.Wrapf(err, "failed to create dm-verity target: pmem device: %s", devPath)
}

return mapperPath, nil
}

// Unmount unmounts `target` and removes corresponding linear and verity targets when needed
func Unmount(ctx context.Context, devNumber uint32, target string, mappingInfo *prot.DeviceMappingInfo, verityInfo *prot.DeviceVerityInfo, securityPolicy securitypolicy.SecurityPolicyEnforcer) (err error) {
_, span := trace.StartSpan(ctx, "pmem::Unmount")
Expand Down