osbase/loop: clean up code
We no longer need to use unsafe or raw syscalls here.
Change-Id: I10a504be20c949bf41e7af5b33f4439b1580f1cc
Reviewed-on: https://review.monogon.dev/c/monogon/+/3808
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/osbase/loop/loop.go b/osbase/loop/loop.go
index b302c0b..d30bdce 100644
--- a/osbase/loop/loop.go
+++ b/osbase/loop/loop.go
@@ -31,8 +31,6 @@
"math/bits"
"os"
"sync"
- "syscall"
- "unsafe"
"golang.org/x/sys/unix"
)
@@ -45,39 +43,10 @@
)
const (
- // LOOP_CONFIGURE from @linux//include/uapi/linux:loop.h
- loopConfigure = 0x4C0A
// LOOP_MAJOR from @linux//include/uapi/linux:major.h
loopMajor = 7
)
-// struct loop_config from @linux//include/uapi/linux:loop.h
-type loopConfig struct {
- fd uint32
- // blockSize is a power of 2 between 512 and os.Getpagesize(), defaults
- // reasonably
- blockSize uint32
- info loopInfo64
- _reserved [64]byte
-}
-
-// struct loop_info64 from @linux//include/uapi/linux:loop.h
-type loopInfo64 struct {
- device uint64
- inode uint64
- rdevice uint64
- offset uint64 // used
- sizeLimit uint64 // used
- number uint32
- encryptType uint32
- encryptKeySize uint32
- flags uint32 // Flags from Flag constant
- filename [64]byte // used
- cryptname [64]byte
- encryptkey [32]byte
- init [2]uint64
-}
-
type Config struct {
// Block size of the loop device in bytes. Power of 2 between 512 and page
// size. Zero defaults to an reasonable block size.
@@ -145,13 +114,12 @@
return nil, fmt.Errorf("failed to access loop control device: %w", err)
}
for {
- devNum, _, errno := syscall.Syscall(unix.SYS_IOCTL, loopControlFd.Fd(), unix.LOOP_CTL_GET_FREE, 0)
- if errno != unix.Errno(0) {
- return nil, fmt.Errorf("failed to allocate loop device: %w", os.NewSyscallError("ioctl(LOOP_CTL_GET_FREE)", errno))
+ devNum, err := unix.IoctlRetInt(int(loopControlFd.Fd()), unix.LOOP_CTL_GET_FREE)
+ if err != nil {
+ return nil, fmt.Errorf("failed to allocate loop device: %w", os.NewSyscallError("ioctl(LOOP_CTL_GET_FREE)", err))
}
dev, err := os.OpenFile(fmt.Sprintf("/dev/loop%v", devNum), os.O_RDWR|os.O_EXCL, 0)
- var pe *os.PathError
- if errors.As(err, &pe) && errors.Is(pe.Err, unix.EBUSY) {
+ if errors.Is(err, unix.EBUSY) {
// We have lost the race, get a new device
continue
}
@@ -159,18 +127,19 @@
return nil, fmt.Errorf("failed to open newly-allocated loop device: %w", err)
}
- var config loopConfig
- config.fd = uint32(f.Fd())
- config.blockSize = c.BlockSize
- config.info.flags = c.Flags
- config.info.offset = c.Offset
- config.info.sizeLimit = c.SizeLimit
+ var config unix.LoopConfig
+ config.Fd = uint32(f.Fd())
+ config.Size = c.BlockSize
+ config.Info.Flags = c.Flags
+ config.Info.Offset = c.Offset
+ config.Info.Sizelimit = c.SizeLimit
- if _, _, err := syscall.Syscall(unix.SYS_IOCTL, dev.Fd(), loopConfigure, uintptr(unsafe.Pointer(&config))); err != 0 {
- if err == unix.EBUSY {
- // We have lost the race, get a new device
- continue
- }
+ err = unix.IoctlLoopConfigure(int(dev.Fd()), &config)
+ if errors.Is(err, unix.EBUSY) {
+ // We have lost the race, get a new device
+ continue
+ }
+ if err != nil {
return nil, os.NewSyscallError("ioctl(LOOP_CONFIGURE)", err)
}
return &Device{dev: dev, num: uint32(devNum)}, nil
@@ -184,16 +153,15 @@
if err != nil {
return nil, fmt.Errorf("failed to open device: %w", err)
}
- var loopInfo loopInfo64
- _, _, errNo := syscall.Syscall(unix.SYS_IOCTL, potentialDevice.Fd(), unix.LOOP_GET_STATUS64, uintptr(unsafe.Pointer(&loopInfo)))
- if errNo == syscall.Errno(0) {
- return &Device{dev: potentialDevice, num: loopInfo.number}, nil
+ loopInfo, err := unix.IoctlLoopGetStatus64(int(potentialDevice.Fd()))
+ if err == nil {
+ return &Device{dev: potentialDevice, num: loopInfo.Number}, nil
}
potentialDevice.Close()
- if errNo == syscall.EINVAL {
+ if errors.Is(err, unix.EINVAL) {
return nil, errors.New("not a loop device")
}
- return nil, fmt.Errorf("failed to determine state of potential loop device: %w", errNo)
+ return nil, fmt.Errorf("failed to determine state of potential loop device: %w", err)
}
func (d *Device) ensureOpen() error {