8b5a2050f9
The loopback logic is not technically exclusive to the devicemapper driver. This reorganizes the code such that the loopback code is usable outside of the devicemapper package and driver. Signed-off-by: Vincent Batts <vbatts@redhat.com> Upstream-commit: af597527121c0ad973e9d0ae4f9cf970da1513cc Component: engine
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
// +build linux
|
|
|
|
package loopback
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
)
|
|
|
|
func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
|
|
loopInfo, err := ioctlLoopGetStatus64(file.Fd())
|
|
if err != nil {
|
|
logrus.Errorf("Error get loopback backing file: %s", err)
|
|
return 0, 0, ErrGetLoopbackBackingFile
|
|
}
|
|
return loopInfo.loDevice, loopInfo.loInode, nil
|
|
}
|
|
|
|
// SetCapacity reloads the size for the loopback device.
|
|
func SetCapacity(file *os.File) error {
|
|
if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil {
|
|
logrus.Errorf("Error loopbackSetCapacity: %s", err)
|
|
return ErrSetCapacity
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// FindLoopDeviceFor returns a loopback device file for the specified file which
|
|
// is backing file of a loop back device.
|
|
func FindLoopDeviceFor(file *os.File) *os.File {
|
|
stat, err := file.Stat()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
targetInode := stat.Sys().(*syscall.Stat_t).Ino
|
|
targetDevice := stat.Sys().(*syscall.Stat_t).Dev
|
|
|
|
for i := 0; true; i++ {
|
|
path := fmt.Sprintf("/dev/loop%d", i)
|
|
|
|
file, err := os.OpenFile(path, os.O_RDWR, 0)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
|
|
// Ignore all errors until the first not-exist
|
|
// we want to continue looking for the file
|
|
continue
|
|
}
|
|
|
|
dev, inode, err := getLoopbackBackingFile(file)
|
|
if err == nil && dev == targetDevice && inode == targetInode {
|
|
return file
|
|
}
|
|
file.Close()
|
|
}
|
|
|
|
return nil
|
|
}
|