Skip to content

Commit a0739dc

Browse files
alex-mateiaustinvazquez
authored andcommitted
Use LOOP_CONFIGURE when creating loop devices
LOOP_CONFIGURE is a new ioctl that is a lot faster than the LOOP_SET_FD+LOOP_SET_STATUS64 calls Signed-off-by: Alexandru Matei <[email protected]> (cherry picked from commit a782fd6) Signed-off-by: Austin Vazquez <[email protected]>
1 parent 6f0f4df commit a0739dc

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

mount/losetup_linux.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ import (
2121
"fmt"
2222
"os"
2323
"strings"
24+
"syscall"
2425
"time"
26+
"unsafe"
2527

28+
kernel "github.com/containerd/containerd/contrib/seccomp/kernelversion"
2629
"github.com/containerd/containerd/pkg/randutil"
2730
"golang.org/x/sys/unix"
2831
)
@@ -32,8 +35,26 @@ const (
3235
loopDevFormat = "/dev/loop%d"
3336

3437
ebusyString = "device or resource busy"
38+
39+
loopConfigureIoctl = 0x4c0a
3540
)
3641

42+
type LoopConfig struct {
43+
Fd uint32
44+
BlockSize uint32
45+
Info unix.LoopInfo64
46+
Reserved [8]uint64
47+
}
48+
49+
func ioctlConfigure(fd int, value *LoopConfig) error {
50+
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(loopConfigureIoctl), uintptr(unsafe.Pointer(value)))
51+
if err == 0 {
52+
return nil
53+
}
54+
55+
return err
56+
}
57+
3758
// LoopParams parameters to control loop device setup
3859
type LoopParams struct {
3960
// Loop device should forbid write
@@ -84,6 +105,32 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) (_ *os.File, re
84105
}
85106
}()
86107

108+
fiveDotEight := kernel.KernelVersion{Kernel: 5, Major: 8}
109+
if ok, err := kernel.GreaterEqualThan(fiveDotEight); err == nil && ok {
110+
config := LoopConfig{
111+
Fd: uint32(back.Fd()),
112+
}
113+
114+
copy(config.Info.File_name[:], backingFile)
115+
if param.Readonly {
116+
config.Info.Flags |= unix.LO_FLAGS_READ_ONLY
117+
}
118+
119+
if param.Autoclear {
120+
config.Info.Flags |= unix.LO_FLAGS_AUTOCLEAR
121+
}
122+
123+
if param.Direct {
124+
config.Info.Flags |= unix.LO_FLAGS_DIRECT_IO
125+
}
126+
127+
if err := ioctlConfigure(int(loop.Fd()), &config); err != nil {
128+
return nil, fmt.Errorf("failed to configure loop device: %s: %w", loopDev, err)
129+
}
130+
131+
return loop, nil
132+
}
133+
87134
// 2. Set FD
88135
if err := unix.IoctlSetInt(int(loop.Fd()), unix.LOOP_SET_FD, int(back.Fd())); err != nil {
89136
return nil, fmt.Errorf("could not set loop fd for device: %s: %w", loopDev, err)

0 commit comments

Comments
 (0)