74e35aace0
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>
63 lines
1.4 KiB
Go
63 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
|
|
}
|