1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

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 Solomon Hykes
parent 1804fcba93
commit c77697a45c
5 changed files with 345 additions and 306 deletions

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

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

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
}

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
}

View file

@ -356,8 +356,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 {