devmapper: Move all "raw" libdevmapper wrappers to devmapper.go

This separates out the DeviceSet logic a bit better from the raw
device mapper operations.

devicemapper: Serialize addess to the devicemapper deviceset

This code is not safe to run in multiple threads at the same time,
and neither is libdevmapper.

DeviceMapper: Move deactivate into UnmountDevice

This way the deactivate is atomic wrt othe device mapper operations
and will not fail with EBUSY if someone else starts a devicemapper
operation inbetween unmount and deactivate.

devmapper: Fix loopback mounting regression

Some changes were added to attach_loop_device which added
a perror() in a place that caused it to override errno so that
a later errno != EBUSY failed. This fixes that and cleans up
the error reporting a bit.

devmapper: Build on old kernels without LOOP_CTL_GET_FREE define
This commit is contained in:
Alexander Larsson
2013-10-07 14:06:24 +02:00
committed by Guillaume J. Charmes
parent ea5b19cc01
commit b67c94a963
5 changed files with 345 additions and 306 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ type DeviceSet interface {
DeactivateDevice(hash string) error
RemoveDevice(hash string) error
MountDevice(hash, path string) error
UnmountDevice(hash, path string) error
UnmountDevice(hash, path string, deactivate bool) error
HasDevice(hash string) bool
HasInitializedDevice(hash string) bool
HasActivatedDevice(hash string) bool
+75 -284
View File
@@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"syscall"
"sync"
)
const (
@@ -36,6 +37,7 @@ type MetaData struct {
type DeviceSetDM struct {
MetaData
sync.Mutex
initialized bool
root string
devicePrefix string
@@ -77,74 +79,6 @@ func (devices *DeviceSetDM) getPoolDevName() string {
return getDevName(devices.getPoolName())
}
func (devices *DeviceSetDM) createTask(t TaskType, name string) (*Task, error) {
task := TaskCreate(t)
if task == nil {
return nil, fmt.Errorf("Can't create task of type %d", int(t))
}
if err := task.SetName(name); err != nil {
return nil, fmt.Errorf("Can't set task name %s", name)
}
return task, nil
}
func (devices *DeviceSetDM) getInfo(name string) (*Info, error) {
task, err := devices.createTask(DeviceInfo, name)
if task == nil {
return nil, err
}
if err := task.Run(); err != nil {
return nil, err
}
return task.GetInfo()
}
func (devices *DeviceSetDM) getStatus(name string) (uint64, uint64, string, string, error) {
task, err := devices.createTask(DeviceStatus, name)
if task == nil {
utils.Debugf("getStatus: Error createTask: %s", err)
return 0, 0, "", "", err
}
if err := task.Run(); err != nil {
utils.Debugf("getStatus: Error Run: %s", err)
return 0, 0, "", "", err
}
devinfo, err := task.GetInfo()
if err != nil {
utils.Debugf("getStatus: Error GetInfo: %s", err)
return 0, 0, "", "", err
}
if devinfo.Exists == 0 {
utils.Debugf("getStatus: Non existing device %s", name)
return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
}
_, start, length, target_type, params := task.GetNextTarget(0)
return start, length, target_type, params, nil
}
func (devices *DeviceSetDM) setTransactionId(oldId uint64, newId uint64) error {
task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running setTransactionId")
}
return nil
}
func (devices *DeviceSetDM) hasImage(name string) bool {
dirname := devices.loopbackDir()
filename := path.Join(dirname, name)
@@ -178,194 +112,6 @@ func (devices *DeviceSetDM) ensureImage(name string, size int64) (string, error)
return filename, nil
}
func (devices *DeviceSetDM) createPool(dataFile *os.File, metadataFile *os.File) error {
utils.Debugf("Activating device-mapper pool %s", devices.getPoolName())
task, err := devices.createTask(DeviceCreate, devices.getPoolName())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
size, err := GetBlockDeviceSize(dataFile)
if err != nil {
return fmt.Errorf("Can't get data size")
}
params := metadataFile.Name() + " " + dataFile.Name() + " 512 8192"
if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
return fmt.Errorf("Can't add target")
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceCreate")
}
UdevWait(cookie)
return nil
}
func (devices *DeviceSetDM) suspendDevice(info *DevInfo) error {
task, err := devices.createTask(DeviceSuspend, info.Name())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceSuspend")
}
return nil
}
func (devices *DeviceSetDM) resumeDevice(info *DevInfo) error {
task, err := devices.createTask(DeviceResume, info.Name())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceSuspend")
}
UdevWait(cookie)
return nil
}
func (devices *DeviceSetDM) createDevice(deviceId int) error {
task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("create_thin %d", deviceId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running createDevice")
}
return nil
}
func (devices *DeviceSetDM) createSnapDevice(deviceId int, baseInfo *DevInfo) error {
devinfo, _ := devices.getInfo(baseInfo.Name())
doSuspend := devinfo != nil && devinfo.Exists != 0
if doSuspend {
if err := devices.suspendDevice(baseInfo); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
}
task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
if task == nil {
devices.resumeDevice(baseInfo)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := task.SetSector(0); err != nil {
devices.resumeDevice(baseInfo)
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", deviceId, baseInfo.DeviceId)); err != nil {
devices.resumeDevice(baseInfo)
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
devices.resumeDevice(baseInfo)
return fmt.Errorf("Error running DeviceCreate")
}
if doSuspend {
if err := devices.resumeDevice(baseInfo); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
}
return nil
}
func (devices *DeviceSetDM) deleteDevice(deviceId int) error {
task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running deleteDevice")
}
return nil
}
func (devices *DeviceSetDM) removeDevice(name string) error {
task, err := devices.createTask(DeviceRemove, name)
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err = task.Run(); err != nil {
return fmt.Errorf("Error running removeDevice")
}
return nil
}
func (devices *DeviceSetDM) activateDevice(info *DevInfo) error {
task, err := devices.createTask(DeviceCreate, info.Name())
if task == nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
params := fmt.Sprintf("%s %d", devices.getPoolDevName(), info.DeviceId)
if err := task.AddTarget(0, info.Size/512, "thin", params); err != nil {
return fmt.Errorf("Can't add target")
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceCreate")
}
UdevWait(cookie)
return nil
}
func (devices *DeviceSetDM) allocateDeviceId() int {
// TODO: Add smarter reuse of deleted devices
id := devices.nextFreeDevice
@@ -412,7 +158,7 @@ func (devices *DeviceSetDM) saveMetadata() error {
}
if devices.NewTransactionId != devices.TransactionId {
if err = devices.setTransactionId(devices.TransactionId, devices.NewTransactionId); err != nil {
if err = setTransactionId(devices.getPoolDevName(), devices.TransactionId, devices.NewTransactionId); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
@@ -448,11 +194,11 @@ func (devices *DeviceSetDM) activateDeviceIfNeeded(hash string) error {
return fmt.Errorf("Unknown device %s", hash)
}
if devinfo, _ := devices.getInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
if devinfo, _ := getInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
return nil
}
return devices.activateDevice(info)
return activateDevice(devices.getPoolDevName(), info.Name(), info.DeviceId, info.Size)
}
func (devices *DeviceSetDM) createFilesystem(info *DevInfo) error {
@@ -470,7 +216,7 @@ func (devices *DeviceSetDM) createFilesystem(info *DevInfo) error {
}
func (devices *DeviceSetDM) loadMetaData() error {
_, _, _, params, err := devices.getStatus(devices.getPoolName())
_, _, _, params, err := getStatus(devices.getPoolName())
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
@@ -521,7 +267,7 @@ func (devices *DeviceSetDM) setupBaseImage() error {
if oldInfo != nil && !oldInfo.Initialized {
utils.Debugf("Removing uninitialized base image")
if err := devices.RemoveDevice(""); err != nil {
if err := devices.removeDevice(""); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
@@ -532,14 +278,14 @@ func (devices *DeviceSetDM) setupBaseImage() error {
id := devices.allocateDeviceId()
// Create initial device
if err := devices.createDevice(id); err != nil {
if err := createDevice(devices.getPoolDevName(), id); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
info, err := devices.registerDevice(id, "", defaultBaseFsSize)
if err != nil {
_ = devices.deleteDevice(id)
_ = deleteDevice(devices.getPoolDevName(), id)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
@@ -582,7 +328,7 @@ func setCloseOnExec(name string) {
}
func (devices *DeviceSetDM) initDevmapper() error {
info, err := devices.getInfo(devices.getPoolName())
info, err := getInfo(devices.getPoolName())
if info == nil {
utils.Debugf("Error device getInfo: %s", err)
return err
@@ -636,7 +382,7 @@ func (devices *DeviceSetDM) initDevmapper() error {
}
defer metadataFile.Close()
if err := devices.createPool(dataFile, metadataFile); err != nil {
if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
@@ -657,6 +403,9 @@ func (devices *DeviceSetDM) initDevmapper() error {
}
func (devices *DeviceSetDM) AddDevice(hash, baseHash string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("Error init: %s\n", err)
return err
@@ -674,33 +423,28 @@ func (devices *DeviceSetDM) AddDevice(hash, baseHash string) error {
deviceId := devices.allocateDeviceId()
if err := devices.createSnapDevice(deviceId, baseInfo); err != nil {
if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
utils.Debugf("Error creating snap device: %s\n", err)
return err
}
if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size); err != nil {
devices.deleteDevice(deviceId)
deleteDevice(devices.getPoolDevName(), deviceId)
utils.Debugf("Error registering device: %s\n", err)
return err
}
return nil
}
func (devices *DeviceSetDM) RemoveDevice(hash string) error {
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
func (devices *DeviceSetDM) removeDevice(hash string) error {
info := devices.Devices[hash]
if info == nil {
return fmt.Errorf("hash %s doesn't exists", hash)
}
devinfo, _ := devices.getInfo(info.Name())
devinfo, _ := getInfo(info.Name())
if devinfo != nil && devinfo.Exists != 0 {
if err := devices.removeDevice(info.Name()); err != nil {
if err := removeDevice(info.Name()); err != nil {
utils.Debugf("Error removing device: %s\n", err)
return err
}
@@ -714,7 +458,7 @@ func (devices *DeviceSetDM) RemoveDevice(hash string) error {
}
}
if err := devices.deleteDevice(info.DeviceId); err != nil {
if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
utils.Debugf("Error deleting device: %s\n", err)
return err
}
@@ -731,24 +475,32 @@ func (devices *DeviceSetDM) RemoveDevice(hash string) error {
return nil
}
func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
func (devices *DeviceSetDM) RemoveDevice(hash string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
return devices.removeDevice(hash)
}
func (devices *DeviceSetDM) deactivateDevice(hash string) error {
info := devices.Devices[hash]
if info == nil {
return fmt.Errorf("hash %s doesn't exists", hash)
}
devinfo, err := devices.getInfo(info.Name())
devinfo, err := getInfo(info.Name())
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if devinfo.Exists != 0 {
if err := devices.removeDevice(info.Name()); err != nil {
if err := removeDevice(info.Name()); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
@@ -757,7 +509,24 @@ func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
return nil
}
func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
utils.Debugf("DeactivateDevice %s", hash)
return devices.deactivateDevice(hash);
}
func (devices *DeviceSetDM) Shutdown() error {
devices.Lock()
defer devices.Unlock()
if !devices.initialized {
return nil
}
@@ -772,14 +541,14 @@ func (devices *DeviceSetDM) Shutdown() error {
}
for _, d := range devices.Devices {
if err := devices.DeactivateDevice(d.Hash); err != nil {
if err := devices.deactivateDevice(d.Hash); err != nil {
utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
}
}
pool := devices.getPoolDevName()
if devinfo, err := devices.getInfo(pool); err == nil && devinfo.Exists != 0 {
if err := devices.removeDevice(pool); err != nil {
if devinfo, err := getInfo(pool); err == nil && devinfo.Exists != 0 {
if err := removeDevice(pool); err != nil {
utils.Debugf("Shutdown deactivate %s , error: %s\n", pool, err)
}
}
@@ -788,6 +557,9 @@ func (devices *DeviceSetDM) Shutdown() error {
}
func (devices *DeviceSetDM) MountDevice(hash, path string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
@@ -815,7 +587,10 @@ func (devices *DeviceSetDM) MountDevice(hash, path string) error {
return nil
}
func (devices *DeviceSetDM) UnmountDevice(hash, path string) error {
func (devices *DeviceSetDM) UnmountDevice(hash, path string, deactivate bool) error {
devices.Lock()
defer devices.Unlock()
if err := syscall.Unmount(path, 0); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
@@ -827,10 +602,17 @@ func (devices *DeviceSetDM) UnmountDevice(hash, path string) error {
delete(devices.activeMounts, path)
}
if deactivate {
devices.deactivateDevice(hash)
}
return nil
}
func (devices *DeviceSetDM) HasDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
return false
}
@@ -838,6 +620,9 @@ func (devices *DeviceSetDM) HasDevice(hash string) bool {
}
func (devices *DeviceSetDM) HasInitializedDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
return false
}
@@ -847,6 +632,9 @@ func (devices *DeviceSetDM) HasInitializedDevice(hash string) bool {
}
func (devices *DeviceSetDM) HasActivatedDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
return false
}
@@ -855,11 +643,14 @@ func (devices *DeviceSetDM) HasActivatedDevice(hash string) bool {
if info == nil {
return false
}
devinfo, _ := devices.getInfo(info.Name())
devinfo, _ := getInfo(info.Name())
return devinfo != nil && devinfo.Exists != 0
}
func (devices *DeviceSetDM) SetInitialized(hash string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
+259 -4
View File
@@ -14,6 +14,10 @@ package devmapper
#include <linux/fs.h>
#include <errno.h>
#ifndef LOOP_CTL_GET_FREE
#define LOOP_CTL_GET_FREE 0x4C82
#endif
char* attach_loop_device(const char *filename, int *loop_fd_out)
{
struct loop_info64 loopinfo = {0};
@@ -56,19 +60,18 @@ char* attach_loop_device(const char *filename, int *loop_fd_out)
loop_fd = open(buf, O_RDWR);
if (loop_fd < 0 && errno == ENOENT) {
close(fd);
perror("open");
fprintf (stderr, "no available loopback device!");
return NULL;
} else if (loop_fd < 0)
continue;
if (ioctl (loop_fd, LOOP_SET_FD, (void *)(size_t)fd) < 0) {
perror("ioctl");
int errsv = errno;
close(loop_fd);
loop_fd = -1;
if (errno != EBUSY) {
if (errsv != EBUSY) {
close (fd);
fprintf (stderr, "cannot set up loopback device %s", buf);
fprintf (stderr, "cannot set up loopback device %s: %s", buf, strerror(errsv));
return NULL;
}
continue;
@@ -388,3 +391,255 @@ func RemoveDevice(name string) error {
func free(p *C.char) {
C.free(unsafe.Pointer(p))
}
func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error {
task, err := createTask(DeviceCreate, poolName)
if task == nil {
return err
}
size, err := GetBlockDeviceSize(dataFile)
if err != nil {
return fmt.Errorf("Can't get data size")
}
params := metadataFile.Name() + " " + dataFile.Name() + " 512 8192"
if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
return fmt.Errorf("Can't add target")
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceCreate")
}
UdevWait(cookie)
return nil
}
func createTask(t TaskType, name string) (*Task, error) {
task := TaskCreate(t)
if task == nil {
return nil, fmt.Errorf("Can't create task of type %d", int(t))
}
if err := task.SetName(name); err != nil {
return nil, fmt.Errorf("Can't set task name %s", name)
}
return task, nil
}
func getInfo(name string) (*Info, error) {
task, err := createTask(DeviceInfo, name)
if task == nil {
return nil, err
}
if err := task.Run(); err != nil {
return nil, err
}
return task.GetInfo()
}
func getStatus(name string) (uint64, uint64, string, string, error) {
task, err := createTask(DeviceStatus, name)
if task == nil {
utils.Debugf("getStatus: Error createTask: %s", err)
return 0, 0, "", "", err
}
if err := task.Run(); err != nil {
utils.Debugf("getStatus: Error Run: %s", err)
return 0, 0, "", "", err
}
devinfo, err := task.GetInfo()
if err != nil {
utils.Debugf("getStatus: Error GetInfo: %s", err)
return 0, 0, "", "", err
}
if devinfo.Exists == 0 {
utils.Debugf("getStatus: Non existing device %s", name)
return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
}
_, start, length, target_type, params := task.GetNextTarget(0)
return start, length, target_type, params, nil
}
func setTransactionId(poolName string, oldId uint64, newId uint64) error {
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running setTransactionId")
}
return nil
}
func suspendDevice(name string) error {
task, err := createTask(DeviceSuspend, name)
if task == nil {
return err
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceSuspend")
}
return nil
}
func resumeDevice(name string) error {
task, err := createTask(DeviceResume, name)
if task == nil {
return err
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceSuspend")
}
UdevWait(cookie)
return nil
}
func createDevice(poolName string, deviceId int) error {
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("create_thin %d", deviceId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running createDevice")
}
return nil
}
func deleteDevice(poolName string, deviceId int) error {
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
return err
}
if err := task.SetSector(0); err != nil {
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running deleteDevice")
}
return nil
}
func removeDevice(name string) error {
task, err := createTask(DeviceRemove, name)
if task == nil {
return err
}
if err = task.Run(); err != nil {
return fmt.Errorf("Error running removeDevice")
}
return nil
}
func activateDevice(poolName string, name string, deviceId int, size uint64) error {
task, err := createTask(DeviceCreate, name)
if task == nil {
return err
}
params := fmt.Sprintf("%s %d", poolName, deviceId)
if err := task.AddTarget(0, size/512, "thin", params); err != nil {
return fmt.Errorf("Can't add target")
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
return fmt.Errorf("Can't set cookie")
}
if err := task.Run(); err != nil {
return fmt.Errorf("Error running DeviceCreate")
}
UdevWait(cookie)
return nil
}
func (devices *DeviceSetDM) createSnapDevice(poolName string, deviceId int, baseName string, baseDeviceId int) error {
devinfo, _ := getInfo(baseName)
doSuspend := devinfo != nil && devinfo.Exists != 0
if doSuspend {
if err := suspendDevice(baseName); err != nil {
return err
}
}
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
if doSuspend {
resumeDevice(baseName)
}
return err
}
if err := task.SetSector(0); err != nil {
if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Can't set sector")
}
if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", deviceId, baseDeviceId)); err != nil {
if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Can't set message")
}
if err := task.Run(); err != nil {
if doSuspend {
resumeDevice(baseName)
}
return fmt.Errorf("Error running DeviceCreate")
}
if doSuspend {
if err := resumeDevice(baseName); err != nil {
return err
}
}
return nil
}
+8 -15
View File
@@ -391,14 +391,14 @@ func (image *Image) ensureImageDevice(devices DeviceSet) error {
if err := ioutil.WriteFile(path.Join(mountDir, ".docker-id"), []byte(image.ID), 0600); err != nil {
utils.Debugf("Error writing file: %s", err)
devices.UnmountDevice(image.ID, mountDir)
devices.UnmountDevice(image.ID, mountDir, true)
devices.RemoveDevice(image.ID)
return err
}
if err = image.applyLayer(layerPath(root), mountDir); err != nil {
utils.Debugf("Error applying layer: %s", err)
devices.UnmountDevice(image.ID, mountDir)
devices.UnmountDevice(image.ID, mountDir, true)
devices.RemoveDevice(image.ID)
return err
}
@@ -411,28 +411,24 @@ func (image *Image) ensureImageDevice(devices DeviceSet) error {
// part of the container changes
dockerinitLayer, err := image.getDockerInitLayer()
if err != nil {
devices.UnmountDevice(image.ID, mountDir)
devices.UnmountDevice(image.ID, mountDir, true)
devices.RemoveDevice(image.ID)
return err
}
if err := image.applyLayer(dockerinitLayer, mountDir); err != nil {
devices.UnmountDevice(image.ID, mountDir)
devices.UnmountDevice(image.ID, mountDir, true)
devices.RemoveDevice(image.ID)
return err
}
if err := devices.UnmountDevice(image.ID, mountDir); err != nil {
if err := devices.UnmountDevice(image.ID, mountDir, true); err != nil {
devices.RemoveDevice(image.ID)
return err
}
devices.SetInitialized(image.ID)
// No need to the device-mapper device to hang around once we've written
// the image, it can be enabled on-demand when needed
devices.DeactivateDevice(image.ID)
return nil
}
@@ -491,11 +487,11 @@ func (image *Image) Unmount(runtime *Runtime, root string, id string) error {
return err
}
if err = devices.UnmountDevice(id, root); err != nil {
if err = devices.UnmountDevice(id, root, true); err != nil {
return err
}
return devices.DeactivateDevice(id)
return nil
}
func (image *Image) Changes(runtime *Runtime, root, rw, id string) ([]Change, error) {
@@ -518,10 +514,7 @@ func (image *Image) Changes(runtime *Runtime, root, rw, id string) ([]Change, er
}
changes, err := ChangesDirs(root, rw)
devices.UnmountDevice(image.ID, rw)
if !wasActivated {
devices.DeactivateDevice(image.ID)
}
devices.UnmountDevice(image.ID, rw, !wasActivated)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -445,8 +445,8 @@ func (wrapper *DeviceSetWrapper) MountDevice(hash, path string) error {
return wrapper.wrapped.MountDevice(wrapper.wrap(hash), path)
}
func (wrapper *DeviceSetWrapper) UnmountDevice(hash, path string) error {
return wrapper.wrapped.UnmountDevice(wrapper.wrap(hash), path)
func (wrapper *DeviceSetWrapper) UnmountDevice(hash, path string, deactivate bool) error {
return wrapper.wrapped.UnmountDevice(wrapper.wrap(hash), path, deactivate)
}
func (wrapper *DeviceSetWrapper) HasDevice(hash string) bool {