Skip to content

Commit

Permalink
Merge pull request #1585 from stgraber/storage
Browse files Browse the repository at this point in the history
incusd/storage/drivers: Handle 4k sector sizes
  • Loading branch information
hallyn authored Jan 17, 2025
2 parents 2f92a78 + 2e1ff7e commit 155bb6f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 34 deletions.
20 changes: 20 additions & 0 deletions internal/server/storage/drivers/driver_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ func (d *common) moveGPTAltHeader(devPath string) error {
return nil
}

// Our images and VM drives use a 512 bytes sector size.
// If the underlying block device uses a different sector size, we
// need to fake the correct size through a loop device so sgdisk can
// correctly re-locate the partition tables.
if linux.IsBlockdevPath(devPath) {
blockSize, err := GetPhysicalBlockSize(devPath)
if err != nil {
return err
}

if blockSize != 512 {
devPath, err = loopDeviceSetupAlign(devPath)
if err != nil {
return err
}

defer func() { _ = loopDeviceAutoDetach(devPath) }()
}
}

_, err = subprocess.RunCommand(path, "--move-second-header", devPath)
if err == nil {
d.logger.Debug("Moved GPT alternative header to end of disk", logger.Ctx{"dev": devPath})
Expand Down
22 changes: 0 additions & 22 deletions internal/server/storage/drivers/driver_lvm_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import (
"path/filepath"
"strconv"
"strings"
"unsafe"

"golang.org/x/sys/unix"

internalInstance "github.com/lxc/incus/v6/internal/instance"
"github.com/lxc/incus/v6/internal/linux"
Expand Down Expand Up @@ -888,22 +885,3 @@ func (d *lvm) deactivateVolume(vol Volume) (bool, error) {

return false, nil
}

func (d *lvm) getBlockSize(path string) (int, error) {
// Open the block device.
f, err := os.Open(path)
if err != nil {
return -1, err
}

defer func() { _ = f.Close() }()

// Query the physical block size.
var res int32
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(f.Fd()), unix.BLKPBSZGET, uintptr(unsafe.Pointer(&res)))
if errno != 0 {
return -1, fmt.Errorf("Failed to BLKPBSZGET: %w", unix.Errno(errno))
}

return int(res), nil
}
12 changes: 0 additions & 12 deletions internal/server/storage/drivers/driver_lvm_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,6 @@ func (d *lvm) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
if err != nil {
return err
}

// Check the block size for image volumes.
if vol.volType == VolumeTypeImage {
blockSize, err := d.getBlockSize(devPath)
if err != nil {
return err
}

if blockSize != 512 {
return fmt.Errorf("Underlying storage uses %d bytes sector size when virtual machine images require 512 bytes", blockSize)
}
}
}

allowUnsafeResize := false
Expand Down
31 changes: 31 additions & 0 deletions internal/server/storage/drivers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"sort"
"strings"
"time"
"unsafe"

"golang.org/x/sys/unix"

Expand Down Expand Up @@ -797,6 +798,26 @@ func BlockDiskSizeBytes(blockDiskPath string) (int64, error) {
return fi.Size(), nil
}

// GetPhysicalBlockSize returns the physical block size for the device.
func GetPhysicalBlockSize(blockDiskPath string) (int, error) {
// Open the block device.
f, err := os.Open(blockDiskPath)
if err != nil {
return -1, err
}

defer func() { _ = f.Close() }()

// Query the physical block size.
var res int32
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(f.Fd()), unix.BLKPBSZGET, uintptr(unsafe.Pointer(&res)))
if errno != 0 {
return -1, fmt.Errorf("Failed to BLKPBSZGET: %w", unix.Errno(errno))
}

return int(res), nil
}

// OperationLockName returns the storage specific lock name to use with locking package.
func OperationLockName(operationName string, poolName string, volType VolumeType, contentType ContentType, volName string) string {
return fmt.Sprintf("%s/%s/%s/%s/%s", operationName, poolName, volType, contentType, volName)
Expand Down Expand Up @@ -841,6 +862,16 @@ func loopDeviceSetup(sourcePath string) (string, error) {
return strings.TrimSpace(out), nil
}

// loopDeviceSetupAlign creates a forced 512-byte aligned loop device.
func loopDeviceSetupAlign(sourcePath string) (string, error) {
out, err := subprocess.RunCommand("losetup", "-b", "512", "--find", "--nooverlap", "--show", sourcePath)
if err != nil {
return "", err
}

return strings.TrimSpace(out), nil
}

// loopFileAutoDetach enables auto detach mode for a loop device.
func loopDeviceAutoDetach(loopDevPath string) error {
_, err := subprocess.RunCommand("losetup", "--detach", loopDevPath)
Expand Down

0 comments on commit 155bb6f

Please sign in to comment.