summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deviceset.go2
-rw-r--r--devmapper/deviceset_devmapper.go359
-rw-r--r--devmapper/devmapper.go263
-rw-r--r--image.go23
-rw-r--r--utils_test.go4
5 files changed, 345 insertions, 306 deletions
diff --git a/deviceset.go b/deviceset.go
index b2a968738c..21d5fd4d2f 100644
--- a/deviceset.go
+++ b/deviceset.go
@@ -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
diff --git a/devmapper/deviceset_devmapper.go b/devmapper/deviceset_devmapper.go
index b789f94aa3..d0d4fbf85c 100644
--- a/devmapper/deviceset_devmapper.go
+++ b/devmapper/deviceset_devmapper.go
@@ -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
diff --git a/devmapper/devmapper.go b/devmapper/devmapper.go
index 02922e836b..e4db906637 100644
--- a/devmapper/devmapper.go
+++ b/devmapper/devmapper.go
@@ -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
+}
diff --git a/image.go b/image.go
index a937c74086..6a1191ef1b 100644
--- a/image.go
+++ b/image.go
@@ -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
}
diff --git a/utils_test.go b/utils_test.go
index 8348bc4fed..1232c1ff46 100644
--- a/utils_test.go
+++ b/utils_test.go
@@ -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 {