github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/pkg/loopback/loopback.go (about) 1 //go:build linux && cgo 2 // +build linux,cgo 3 4 package loopback // import "github.com/docker/docker/pkg/loopback" 5 6 import ( 7 "fmt" 8 "os" 9 10 "github.com/sirupsen/logrus" 11 "golang.org/x/sys/unix" 12 ) 13 14 func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) { 15 loopInfo, err := ioctlLoopGetStatus64(file.Fd()) 16 if err != nil { 17 logrus.Errorf("Error get loopback backing file: %s", err) 18 return 0, 0, ErrGetLoopbackBackingFile 19 } 20 return loopInfo.Device, loopInfo.Inode, nil 21 } 22 23 // SetCapacity reloads the size for the loopback device. 24 func SetCapacity(file *os.File) error { 25 if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil { 26 logrus.Errorf("Error loopbackSetCapacity: %s", err) 27 return ErrSetCapacity 28 } 29 return nil 30 } 31 32 // FindLoopDeviceFor returns a loopback device file for the specified file which 33 // is backing file of a loop back device. 34 func FindLoopDeviceFor(file *os.File) *os.File { 35 var stat unix.Stat_t 36 err := unix.Stat(file.Name(), &stat) 37 if err != nil { 38 return nil 39 } 40 targetInode := stat.Ino 41 // the type is 32bit on mips 42 targetDevice := uint64(stat.Dev) //nolint: unconvert 43 44 for i := 0; true; i++ { 45 path := fmt.Sprintf("/dev/loop%d", i) 46 47 file, err := os.OpenFile(path, os.O_RDWR, 0) 48 if err != nil { 49 if os.IsNotExist(err) { 50 return nil 51 } 52 53 // Ignore all errors until the first not-exist 54 // we want to continue looking for the file 55 continue 56 } 57 58 dev, inode, err := getLoopbackBackingFile(file) 59 if err == nil && dev == targetDevice && inode == targetInode { 60 return file 61 } 62 file.Close() 63 } 64 65 return nil 66 }