pkg/loopback: use ioctl helpers from x/sys/unix

Use the IoctlRetInt, IoctlSetInt and IoctlLoopSetStatus64 helper
functions defined in the golang.org/x/sys/unix package instead of
manually wrapping these using a locally defined function.

Inspired by 3cc3d8a560

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-10-08 21:20:29 +02:00
parent 6742f74e0e
commit c7c02eea81
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
4 changed files with 12 additions and 96 deletions

View file

@ -15,12 +15,12 @@ import (
// Loopback related errors
var (
ErrAttachLoopbackDevice = errors.New("loopback attach failed")
ErrGetLoopbackBackingFile = errors.New("Unable to get loopback backing file")
ErrSetCapacity = errors.New("Unable set loopback capacity")
ErrGetLoopbackBackingFile = errors.New("unable to get loopback backing file")
ErrSetCapacity = errors.New("unable set loopback capacity")
)
func stringToLoopName(src string) [LoNameSize]uint8 {
var dst [LoNameSize]uint8
func stringToLoopName(src string) [unix.LO_NAME_SIZE]uint8 {
var dst [unix.LO_NAME_SIZE]uint8
copy(dst[:], src[:])
return dst
}
@ -31,12 +31,7 @@ func getNextFreeLoopbackIndex() (int, error) {
return 0, err
}
defer f.Close()
index, err := ioctlLoopCtlGetFree(f.Fd())
if index < 0 {
index = 0
}
return index, err
return unix.IoctlRetInt(int(f.Fd()), unix.LOOP_CTL_GET_FREE)
}
func openNextAvailableLoopback(index int, sparseFile *os.File) (loopFile *os.File, err error) {
@ -66,7 +61,7 @@ func openNextAvailableLoopback(index int, sparseFile *os.File) (loopFile *os.Fil
}
// Try to attach to the loop file
if err := ioctlLoopSetFd(loopFile.Fd(), sparseFile.Fd()); err != nil {
if err = unix.IoctlSetInt(int(loopFile.Fd()), unix.LOOP_SET_FD, int(sparseFile.Fd())); err != nil {
loopFile.Close()
// If the error is EBUSY, then try the next loopback
@ -119,14 +114,14 @@ func AttachLoopDevice(sparseName string) (loop *os.File, err error) {
loopInfo := &unix.LoopInfo64{
File_name: stringToLoopName(loopFile.Name()),
Offset: 0,
Flags: LoFlagsAutoClear,
Flags: unix.LO_FLAGS_AUTOCLEAR,
}
if err := ioctlLoopSetStatus64(loopFile.Fd(), loopInfo); err != nil {
if err = unix.IoctlLoopSetStatus64(int(loopFile.Fd()), loopInfo); err != nil {
logrus.Errorf("Cannot set up loopback device info: %s", err)
// If the call failed, then free the loopback device
if err := ioctlLoopClrFd(loopFile.Fd()); err != nil {
if err = unix.IoctlSetInt(int(loopFile.Fd()), unix.LOOP_CLR_FD, 0); err != nil {
logrus.Error("Error while cleaning up the loopback device")
}
loopFile.Close()

View file

@ -1,53 +0,0 @@
//go:build linux
// +build linux
package loopback // import "github.com/docker/docker/pkg/loopback"
import (
"unsafe"
"golang.org/x/sys/unix"
)
func ioctlLoopCtlGetFree(fd uintptr) (int, error) {
// The ioctl interface for /dev/loop-control (since Linux 3.1) is a bit
// off compared to what you'd expect: instead of writing an integer to a
// parameter pointer like unix.IoctlGetInt() expects, it returns the first
// available loop device index directly.
ioctlReturn, _, err := unix.Syscall(unix.SYS_IOCTL, fd, LoopCtlGetFree, 0)
if err != 0 {
return 0, err
}
return int(ioctlReturn), nil
}
func ioctlLoopSetFd(loopFd, sparseFd uintptr) error {
return unix.IoctlSetInt(int(loopFd), unix.LOOP_SET_FD, int(sparseFd))
}
func ioctlLoopSetStatus64(loopFd uintptr, loopInfo *unix.LoopInfo64) error {
if _, _, err := unix.Syscall(unix.SYS_IOCTL, loopFd, unix.LOOP_SET_STATUS64, uintptr(unsafe.Pointer(loopInfo))); err != 0 {
return err
}
return nil
}
func ioctlLoopClrFd(loopFd uintptr) error {
if _, _, err := unix.Syscall(unix.SYS_IOCTL, loopFd, unix.LOOP_CLR_FD, 0); err != 0 {
return err
}
return nil
}
func ioctlLoopGetStatus64(loopFd uintptr) (*unix.LoopInfo64, error) {
loopInfo := &unix.LoopInfo64{}
if _, _, err := unix.Syscall(unix.SYS_IOCTL, loopFd, unix.LOOP_GET_STATUS64, uintptr(unsafe.Pointer(loopInfo))); err != 0 {
return nil, err
}
return loopInfo, nil
}
func ioctlLoopSetCapacity(loopFd uintptr, value int) error {
return unix.IoctlSetInt(int(loopFd), unix.LOOP_SET_CAPACITY, value)
}

View file

@ -1,25 +0,0 @@
//go:build linux
// +build linux
package loopback // import "github.com/docker/docker/pkg/loopback"
import "golang.org/x/sys/unix"
// IOCTL consts
const (
LoopSetFd = unix.LOOP_SET_FD
LoopCtlGetFree = unix.LOOP_CTL_GET_FREE
LoopGetStatus64 = unix.LOOP_GET_STATUS64
LoopSetStatus64 = unix.LOOP_SET_STATUS64
LoopClrFd = unix.LOOP_CLR_FD
LoopSetCapacity = unix.LOOP_SET_CAPACITY
)
// LOOP consts.
const (
LoFlagsAutoClear = unix.LO_FLAGS_AUTOCLEAR
LoFlagsReadOnly = unix.LO_FLAGS_READ_ONLY
LoFlagsPartScan = unix.LO_FLAGS_PARTSCAN
LoKeySize = unix.LO_KEY_SIZE
LoNameSize = unix.LO_NAME_SIZE
)

View file

@ -12,7 +12,7 @@ import (
)
func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
loopInfo, err := ioctlLoopGetStatus64(file.Fd())
loopInfo, err := unix.IoctlLoopGetStatus64(int(file.Fd()))
if err != nil {
logrus.Errorf("Error get loopback backing file: %s", err)
return 0, 0, ErrGetLoopbackBackingFile
@ -22,7 +22,7 @@ func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
// SetCapacity reloads the size for the loopback device.
func SetCapacity(file *os.File) error {
if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil {
if err := unix.IoctlSetInt(int(file.Fd()), unix.LOOP_SET_CAPACITY, 0); err != nil {
logrus.Errorf("Error loopbackSetCapacity: %s", err)
return ErrSetCapacity
}
@ -38,8 +38,7 @@ func FindLoopDeviceFor(file *os.File) *os.File {
return nil
}
targetInode := stat.Ino
// the type is 32bit on mips
targetDevice := uint64(stat.Dev) //nolint: unconvert
targetDevice := uint64(stat.Dev) //nolint: unconvert // the type is 32bit on mips
for i := 0; true; i++ {
path := fmt.Sprintf("/dev/loop%d", i)