@@ -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
3859type 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