github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/pkg/devicemapper/devmapper.go (about)

     1  // +build linux,cgo
     2  
     3  package devicemapper // import "github.com/docker/docker/pkg/devicemapper"
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"os"
     9  	"runtime"
    10  	"unsafe"
    11  
    12  	"github.com/sirupsen/logrus"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  // Same as DM_DEVICE_* enum values from libdevmapper.h
    17  // nolint: deadcode
    18  const (
    19  	deviceCreate TaskType = iota
    20  	deviceReload
    21  	deviceRemove
    22  	deviceRemoveAll
    23  	deviceSuspend
    24  	deviceResume
    25  	deviceInfo
    26  	deviceDeps
    27  	deviceRename
    28  	deviceVersion
    29  	deviceStatus
    30  	deviceTable
    31  	deviceWaitevent
    32  	deviceList
    33  	deviceClear
    34  	deviceMknodes
    35  	deviceListVersions
    36  	deviceTargetMsg
    37  	deviceSetGeometry
    38  )
    39  
    40  const (
    41  	addNodeOnResume AddNodeType = iota
    42  	addNodeOnCreate
    43  )
    44  
    45  // List of errors returned when using devicemapper.
    46  var (
    47  	ErrTaskRun              = errors.New("dm_task_run failed")
    48  	ErrTaskSetName          = errors.New("dm_task_set_name failed")
    49  	ErrTaskSetMessage       = errors.New("dm_task_set_message failed")
    50  	ErrTaskSetAddNode       = errors.New("dm_task_set_add_node failed")
    51  	ErrTaskSetRo            = errors.New("dm_task_set_ro failed")
    52  	ErrTaskAddTarget        = errors.New("dm_task_add_target failed")
    53  	ErrTaskSetSector        = errors.New("dm_task_set_sector failed")
    54  	ErrTaskGetDeps          = errors.New("dm_task_get_deps failed")
    55  	ErrTaskGetInfo          = errors.New("dm_task_get_info failed")
    56  	ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed")
    57  	ErrTaskDeferredRemove   = errors.New("dm_task_deferred_remove failed")
    58  	ErrTaskSetCookie        = errors.New("dm_task_set_cookie failed")
    59  	ErrNilCookie            = errors.New("cookie ptr can't be nil")
    60  	ErrGetBlockSize         = errors.New("Can't get block size")
    61  	ErrUdevWait             = errors.New("wait on udev cookie failed")
    62  	ErrSetDevDir            = errors.New("dm_set_dev_dir failed")
    63  	ErrGetLibraryVersion    = errors.New("dm_get_library_version failed")
    64  	ErrCreateRemoveTask     = errors.New("Can't create task of type deviceRemove")
    65  	ErrRunRemoveDevice      = errors.New("running RemoveDevice failed")
    66  	ErrInvalidAddNode       = errors.New("Invalid AddNode type")
    67  	ErrBusy                 = errors.New("Device is Busy")
    68  	ErrDeviceIDExists       = errors.New("Device Id Exists")
    69  	ErrEnxio                = errors.New("No such device or address")
    70  	ErrEnoData              = errors.New("No data available")
    71  )
    72  
    73  var (
    74  	dmSawBusy    bool
    75  	dmSawExist   bool
    76  	dmSawEnxio   bool // No Such Device or Address
    77  	dmSawEnoData bool // No data available
    78  )
    79  
    80  type (
    81  	// Task represents a devicemapper task (like lvcreate, etc.) ; a task is needed for each ioctl
    82  	// command to execute.
    83  	Task struct {
    84  		unmanaged *cdmTask
    85  	}
    86  	// Deps represents dependents (layer) of a device.
    87  	Deps struct {
    88  		Count  uint32
    89  		Filler uint32
    90  		Device []uint64
    91  	}
    92  	// Info represents information about a device.
    93  	Info struct {
    94  		Exists         int
    95  		Suspended      int
    96  		LiveTable      int
    97  		InactiveTable  int
    98  		OpenCount      int32
    99  		EventNr        uint32
   100  		Major          uint32
   101  		Minor          uint32
   102  		ReadOnly       int
   103  		TargetCount    int32
   104  		DeferredRemove int
   105  	}
   106  	// TaskType represents a type of task
   107  	TaskType int
   108  	// AddNodeType represents a type of node to be added
   109  	AddNodeType int
   110  )
   111  
   112  // DeviceIDExists returns whether error conveys the information about device Id already
   113  // exist or not. This will be true if device creation or snap creation
   114  // operation fails if device or snap device already exists in pool.
   115  // Current implementation is little crude as it scans the error string
   116  // for exact pattern match. Replacing it with more robust implementation
   117  // is desirable.
   118  func DeviceIDExists(err error) bool {
   119  	return fmt.Sprint(err) == fmt.Sprint(ErrDeviceIDExists)
   120  }
   121  
   122  func (t *Task) destroy() {
   123  	if t != nil {
   124  		DmTaskDestroy(t.unmanaged)
   125  		runtime.SetFinalizer(t, nil)
   126  	}
   127  }
   128  
   129  // TaskCreateNamed is a convenience function for TaskCreate when a name
   130  // will be set on the task as well
   131  func TaskCreateNamed(t TaskType, name string) (*Task, error) {
   132  	task := TaskCreate(t)
   133  	if task == nil {
   134  		return nil, fmt.Errorf("devicemapper: Can't create task of type %d", int(t))
   135  	}
   136  	if err := task.setName(name); err != nil {
   137  		return nil, fmt.Errorf("devicemapper: Can't set task name %s", name)
   138  	}
   139  	return task, nil
   140  }
   141  
   142  // TaskCreate initializes a devicemapper task of tasktype
   143  func TaskCreate(tasktype TaskType) *Task {
   144  	Ctask := DmTaskCreate(int(tasktype))
   145  	if Ctask == nil {
   146  		return nil
   147  	}
   148  	task := &Task{unmanaged: Ctask}
   149  	runtime.SetFinalizer(task, (*Task).destroy)
   150  	return task
   151  }
   152  
   153  func (t *Task) run() error {
   154  	if res := DmTaskRun(t.unmanaged); res != 1 {
   155  		return ErrTaskRun
   156  	}
   157  	runtime.KeepAlive(t)
   158  	return nil
   159  }
   160  
   161  func (t *Task) setName(name string) error {
   162  	if res := DmTaskSetName(t.unmanaged, name); res != 1 {
   163  		return ErrTaskSetName
   164  	}
   165  	return nil
   166  }
   167  
   168  func (t *Task) setMessage(message string) error {
   169  	if res := DmTaskSetMessage(t.unmanaged, message); res != 1 {
   170  		return ErrTaskSetMessage
   171  	}
   172  	return nil
   173  }
   174  
   175  func (t *Task) setSector(sector uint64) error {
   176  	if res := DmTaskSetSector(t.unmanaged, sector); res != 1 {
   177  		return ErrTaskSetSector
   178  	}
   179  	return nil
   180  }
   181  
   182  func (t *Task) setCookie(cookie *uint, flags uint16) error {
   183  	if cookie == nil {
   184  		return ErrNilCookie
   185  	}
   186  	if res := DmTaskSetCookie(t.unmanaged, cookie, flags); res != 1 {
   187  		return ErrTaskSetCookie
   188  	}
   189  	return nil
   190  }
   191  
   192  func (t *Task) setAddNode(addNode AddNodeType) error {
   193  	if addNode != addNodeOnResume && addNode != addNodeOnCreate {
   194  		return ErrInvalidAddNode
   195  	}
   196  	if res := DmTaskSetAddNode(t.unmanaged, addNode); res != 1 {
   197  		return ErrTaskSetAddNode
   198  	}
   199  	return nil
   200  }
   201  
   202  func (t *Task) setRo() error {
   203  	if res := DmTaskSetRo(t.unmanaged); res != 1 {
   204  		return ErrTaskSetRo
   205  	}
   206  	return nil
   207  }
   208  
   209  func (t *Task) addTarget(start, size uint64, ttype, params string) error {
   210  	if res := DmTaskAddTarget(t.unmanaged, start, size,
   211  		ttype, params); res != 1 {
   212  		return ErrTaskAddTarget
   213  	}
   214  	return nil
   215  }
   216  
   217  func (t *Task) getDeps() (*Deps, error) {
   218  	var deps *Deps
   219  	if deps = DmTaskGetDeps(t.unmanaged); deps == nil {
   220  		return nil, ErrTaskGetDeps
   221  	}
   222  	return deps, nil
   223  }
   224  
   225  func (t *Task) getInfo() (*Info, error) {
   226  	info := &Info{}
   227  	if res := DmTaskGetInfo(t.unmanaged, info); res != 1 {
   228  		return nil, ErrTaskGetInfo
   229  	}
   230  	return info, nil
   231  }
   232  
   233  func (t *Task) getInfoWithDeferred() (*Info, error) {
   234  	info := &Info{}
   235  	if res := DmTaskGetInfoWithDeferred(t.unmanaged, info); res != 1 {
   236  		return nil, ErrTaskGetInfo
   237  	}
   238  	return info, nil
   239  }
   240  
   241  func (t *Task) getDriverVersion() (string, error) {
   242  	res := DmTaskGetDriverVersion(t.unmanaged)
   243  	if res == "" {
   244  		return "", ErrTaskGetDriverVersion
   245  	}
   246  	return res, nil
   247  }
   248  
   249  func (t *Task) getNextTarget(next unsafe.Pointer) (nextPtr unsafe.Pointer, start uint64,
   250  	length uint64, targetType string, params string) {
   251  
   252  	return DmGetNextTarget(t.unmanaged, next, &start, &length,
   253  			&targetType, &params),
   254  		start, length, targetType, params
   255  }
   256  
   257  // UdevWait waits for any processes that are waiting for udev to complete the specified cookie.
   258  func UdevWait(cookie *uint) error {
   259  	if res := DmUdevWait(*cookie); res != 1 {
   260  		logrus.Debugf("devicemapper: Failed to wait on udev cookie %d, %d", *cookie, res)
   261  		return ErrUdevWait
   262  	}
   263  	return nil
   264  }
   265  
   266  // SetDevDir sets the dev folder for the device mapper library (usually /dev).
   267  func SetDevDir(dir string) error {
   268  	if res := DmSetDevDir(dir); res != 1 {
   269  		logrus.Debug("devicemapper: Error dm_set_dev_dir")
   270  		return ErrSetDevDir
   271  	}
   272  	return nil
   273  }
   274  
   275  // GetLibraryVersion returns the device mapper library version.
   276  func GetLibraryVersion() (string, error) {
   277  	var version string
   278  	if res := DmGetLibraryVersion(&version); res != 1 {
   279  		return "", ErrGetLibraryVersion
   280  	}
   281  	return version, nil
   282  }
   283  
   284  // UdevSyncSupported returns whether device-mapper is able to sync with udev
   285  //
   286  // This is essential otherwise race conditions can arise where both udev and
   287  // device-mapper attempt to create and destroy devices.
   288  func UdevSyncSupported() bool {
   289  	return DmUdevGetSyncSupport() != 0
   290  }
   291  
   292  // UdevSetSyncSupport allows setting whether the udev sync should be enabled.
   293  // The return bool indicates the state of whether the sync is enabled.
   294  func UdevSetSyncSupport(enable bool) bool {
   295  	if enable {
   296  		DmUdevSetSyncSupport(1)
   297  	} else {
   298  		DmUdevSetSyncSupport(0)
   299  	}
   300  
   301  	return UdevSyncSupported()
   302  }
   303  
   304  // CookieSupported returns whether the version of device-mapper supports the
   305  // use of cookie's in the tasks.
   306  // This is largely a lower level call that other functions use.
   307  func CookieSupported() bool {
   308  	return DmCookieSupported() != 0
   309  }
   310  
   311  // RemoveDevice is a useful helper for cleaning up a device.
   312  func RemoveDevice(name string) error {
   313  	task, err := TaskCreateNamed(deviceRemove, name)
   314  	if task == nil {
   315  		return err
   316  	}
   317  
   318  	cookie := new(uint)
   319  	if err := task.setCookie(cookie, 0); err != nil {
   320  		return fmt.Errorf("devicemapper: Can not set cookie: %s", err)
   321  	}
   322  	defer UdevWait(cookie)
   323  
   324  	dmSawBusy = false // reset before the task is run
   325  	dmSawEnxio = false
   326  	if err = task.run(); err != nil {
   327  		if dmSawBusy {
   328  			return ErrBusy
   329  		}
   330  		if dmSawEnxio {
   331  			return ErrEnxio
   332  		}
   333  		return fmt.Errorf("devicemapper: Error running RemoveDevice %s", err)
   334  	}
   335  
   336  	return nil
   337  }
   338  
   339  // RemoveDeviceDeferred is a useful helper for cleaning up a device, but deferred.
   340  func RemoveDeviceDeferred(name string) error {
   341  	logrus.Debugf("devicemapper: RemoveDeviceDeferred START(%s)", name)
   342  	defer logrus.Debugf("devicemapper: RemoveDeviceDeferred END(%s)", name)
   343  	task, err := TaskCreateNamed(deviceRemove, name)
   344  	if task == nil {
   345  		return err
   346  	}
   347  
   348  	if err := DmTaskDeferredRemove(task.unmanaged); err != 1 {
   349  		return ErrTaskDeferredRemove
   350  	}
   351  
   352  	// set a task cookie and disable library fallback, or else libdevmapper will
   353  	// disable udev dm rules and delete the symlink under /dev/mapper by itself,
   354  	// even if the removal is deferred by the kernel.
   355  	cookie := new(uint)
   356  	flags := uint16(DmUdevDisableLibraryFallback)
   357  	if err := task.setCookie(cookie, flags); err != nil {
   358  		return fmt.Errorf("devicemapper: Can not set cookie: %s", err)
   359  	}
   360  
   361  	// libdevmapper and udev relies on System V semaphore for synchronization,
   362  	// semaphores created in `task.setCookie` will be cleaned up in `UdevWait`.
   363  	// So these two function call must come in pairs, otherwise semaphores will
   364  	// be leaked, and the  limit of number of semaphores defined in `/proc/sys/kernel/sem`
   365  	// will be reached, which will eventually make all following calls to 'task.SetCookie'
   366  	// fail.
   367  	// this call will not wait for the deferred removal's final executing, since no
   368  	// udev event will be generated, and the semaphore's value will not be incremented
   369  	// by udev, what UdevWait is just cleaning up the semaphore.
   370  	defer UdevWait(cookie)
   371  
   372  	dmSawEnxio = false
   373  	if err = task.run(); err != nil {
   374  		if dmSawEnxio {
   375  			return ErrEnxio
   376  		}
   377  		return fmt.Errorf("devicemapper: Error running RemoveDeviceDeferred %s", err)
   378  	}
   379  
   380  	return nil
   381  }
   382  
   383  // CancelDeferredRemove cancels a deferred remove for a device.
   384  func CancelDeferredRemove(deviceName string) error {
   385  	task, err := TaskCreateNamed(deviceTargetMsg, deviceName)
   386  	if task == nil {
   387  		return err
   388  	}
   389  
   390  	if err := task.setSector(0); err != nil {
   391  		return fmt.Errorf("devicemapper: Can't set sector %s", err)
   392  	}
   393  
   394  	if err := task.setMessage(fmt.Sprintf("@cancel_deferred_remove")); err != nil {
   395  		return fmt.Errorf("devicemapper: Can't set message %s", err)
   396  	}
   397  
   398  	dmSawBusy = false
   399  	dmSawEnxio = false
   400  	if err := task.run(); err != nil {
   401  		// A device might be being deleted already
   402  		if dmSawBusy {
   403  			return ErrBusy
   404  		} else if dmSawEnxio {
   405  			return ErrEnxio
   406  		}
   407  		return fmt.Errorf("devicemapper: Error running CancelDeferredRemove %s", err)
   408  
   409  	}
   410  	return nil
   411  }
   412  
   413  // GetBlockDeviceSize returns the size of a block device identified by the specified file.
   414  func GetBlockDeviceSize(file *os.File) (uint64, error) {
   415  	size, err := ioctlBlkGetSize64(file.Fd())
   416  	if err != nil {
   417  		logrus.Errorf("devicemapper: Error getblockdevicesize: %s", err)
   418  		return 0, ErrGetBlockSize
   419  	}
   420  	return uint64(size), nil
   421  }
   422  
   423  // BlockDeviceDiscard runs discard for the given path.
   424  // This is used as a workaround for the kernel not discarding block so
   425  // on the thin pool when we remove a thinp device, so we do it
   426  // manually
   427  func BlockDeviceDiscard(path string) error {
   428  	file, err := os.OpenFile(path, os.O_RDWR, 0)
   429  	if err != nil {
   430  		return err
   431  	}
   432  	defer file.Close()
   433  
   434  	size, err := GetBlockDeviceSize(file)
   435  	if err != nil {
   436  		return err
   437  	}
   438  
   439  	if err := ioctlBlkDiscard(file.Fd(), 0, size); err != nil {
   440  		return err
   441  	}
   442  
   443  	// Without this sometimes the remove of the device that happens after
   444  	// discard fails with EBUSY.
   445  	unix.Sync()
   446  
   447  	return nil
   448  }
   449  
   450  // CreatePool is the programmatic example of "dmsetup create".
   451  // It creates a device with the specified poolName, data and metadata file and block size.
   452  func CreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error {
   453  	task, err := TaskCreateNamed(deviceCreate, poolName)
   454  	if task == nil {
   455  		return err
   456  	}
   457  
   458  	size, err := GetBlockDeviceSize(dataFile)
   459  	if err != nil {
   460  		return fmt.Errorf("devicemapper: Can't get data size %s", err)
   461  	}
   462  
   463  	params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize)
   464  	if err := task.addTarget(0, size/512, "thin-pool", params); err != nil {
   465  		return fmt.Errorf("devicemapper: Can't add target %s", err)
   466  	}
   467  
   468  	cookie := new(uint)
   469  	flags := uint16(DmUdevDisableSubsystemRulesFlag | DmUdevDisableDiskRulesFlag | DmUdevDisableOtherRulesFlag)
   470  	if err := task.setCookie(cookie, flags); err != nil {
   471  		return fmt.Errorf("devicemapper: Can't set cookie %s", err)
   472  	}
   473  	defer UdevWait(cookie)
   474  
   475  	if err := task.run(); err != nil {
   476  		return fmt.Errorf("devicemapper: Error running deviceCreate (CreatePool) %s", err)
   477  	}
   478  
   479  	return nil
   480  }
   481  
   482  // ReloadPool is the programmatic example of "dmsetup reload".
   483  // It reloads the table with the specified poolName, data and metadata file and block size.
   484  func ReloadPool(poolName string, dataFile, metadataFile *os.File, poolBlockSize uint32) error {
   485  	task, err := TaskCreateNamed(deviceReload, poolName)
   486  	if task == nil {
   487  		return err
   488  	}
   489  
   490  	size, err := GetBlockDeviceSize(dataFile)
   491  	if err != nil {
   492  		return fmt.Errorf("devicemapper: Can't get data size %s", err)
   493  	}
   494  
   495  	params := fmt.Sprintf("%s %s %d 32768 1 skip_block_zeroing", metadataFile.Name(), dataFile.Name(), poolBlockSize)
   496  	if err := task.addTarget(0, size/512, "thin-pool", params); err != nil {
   497  		return fmt.Errorf("devicemapper: Can't add target %s", err)
   498  	}
   499  
   500  	if err := task.run(); err != nil {
   501  		return fmt.Errorf("devicemapper: Error running ReloadPool %s", err)
   502  	}
   503  
   504  	return nil
   505  }
   506  
   507  // GetDeps is the programmatic example of "dmsetup deps".
   508  // It outputs a list of devices referenced by the live table for the specified device.
   509  func GetDeps(name string) (*Deps, error) {
   510  	task, err := TaskCreateNamed(deviceDeps, name)
   511  	if task == nil {
   512  		return nil, err
   513  	}
   514  	if err := task.run(); err != nil {
   515  		return nil, err
   516  	}
   517  	return task.getDeps()
   518  }
   519  
   520  // GetInfo is the programmatic example of "dmsetup info".
   521  // It outputs some brief information about the device.
   522  func GetInfo(name string) (*Info, error) {
   523  	task, err := TaskCreateNamed(deviceInfo, name)
   524  	if task == nil {
   525  		return nil, err
   526  	}
   527  	if err := task.run(); err != nil {
   528  		return nil, err
   529  	}
   530  	return task.getInfo()
   531  }
   532  
   533  // GetInfoWithDeferred is the programmatic example of "dmsetup info", but deferred.
   534  // It outputs some brief information about the device.
   535  func GetInfoWithDeferred(name string) (*Info, error) {
   536  	task, err := TaskCreateNamed(deviceInfo, name)
   537  	if task == nil {
   538  		return nil, err
   539  	}
   540  	if err := task.run(); err != nil {
   541  		return nil, err
   542  	}
   543  	return task.getInfoWithDeferred()
   544  }
   545  
   546  // GetDriverVersion is the programmatic example of "dmsetup version".
   547  // It outputs version information of the driver.
   548  func GetDriverVersion() (string, error) {
   549  	task := TaskCreate(deviceVersion)
   550  	if task == nil {
   551  		return "", fmt.Errorf("devicemapper: Can't create deviceVersion task")
   552  	}
   553  	if err := task.run(); err != nil {
   554  		return "", err
   555  	}
   556  	return task.getDriverVersion()
   557  }
   558  
   559  // GetStatus is the programmatic example of "dmsetup status".
   560  // It outputs status information for the specified device name.
   561  func GetStatus(name string) (uint64, uint64, string, string, error) {
   562  	task, err := TaskCreateNamed(deviceStatus, name)
   563  	if task == nil {
   564  		logrus.Debugf("devicemapper: GetStatus() Error TaskCreateNamed: %s", err)
   565  		return 0, 0, "", "", err
   566  	}
   567  	if err := task.run(); err != nil {
   568  		logrus.Debugf("devicemapper: GetStatus() Error Run: %s", err)
   569  		return 0, 0, "", "", err
   570  	}
   571  
   572  	devinfo, err := task.getInfo()
   573  	if err != nil {
   574  		logrus.Debugf("devicemapper: GetStatus() Error GetInfo: %s", err)
   575  		return 0, 0, "", "", err
   576  	}
   577  	if devinfo.Exists == 0 {
   578  		logrus.Debugf("devicemapper: GetStatus() Non existing device %s", name)
   579  		return 0, 0, "", "", fmt.Errorf("devicemapper: Non existing device %s", name)
   580  	}
   581  
   582  	_, start, length, targetType, params := task.getNextTarget(unsafe.Pointer(nil))
   583  	return start, length, targetType, params, nil
   584  }
   585  
   586  // GetTable is the programmatic example for "dmsetup table".
   587  // It outputs the current table for the specified device name.
   588  func GetTable(name string) (uint64, uint64, string, string, error) {
   589  	task, err := TaskCreateNamed(deviceTable, name)
   590  	if task == nil {
   591  		logrus.Debugf("devicemapper: GetTable() Error TaskCreateNamed: %s", err)
   592  		return 0, 0, "", "", err
   593  	}
   594  	if err := task.run(); err != nil {
   595  		logrus.Debugf("devicemapper: GetTable() Error Run: %s", err)
   596  		return 0, 0, "", "", err
   597  	}
   598  
   599  	devinfo, err := task.getInfo()
   600  	if err != nil {
   601  		logrus.Debugf("devicemapper: GetTable() Error GetInfo: %s", err)
   602  		return 0, 0, "", "", err
   603  	}
   604  	if devinfo.Exists == 0 {
   605  		logrus.Debugf("devicemapper: GetTable() Non existing device %s", name)
   606  		return 0, 0, "", "", fmt.Errorf("devicemapper: Non existing device %s", name)
   607  	}
   608  
   609  	_, start, length, targetType, params := task.getNextTarget(unsafe.Pointer(nil))
   610  	return start, length, targetType, params, nil
   611  }
   612  
   613  // SetTransactionID sets a transaction id for the specified device name.
   614  func SetTransactionID(poolName string, oldID uint64, newID uint64) error {
   615  	task, err := TaskCreateNamed(deviceTargetMsg, poolName)
   616  	if task == nil {
   617  		return err
   618  	}
   619  
   620  	if err := task.setSector(0); err != nil {
   621  		return fmt.Errorf("devicemapper: Can't set sector %s", err)
   622  	}
   623  
   624  	if err := task.setMessage(fmt.Sprintf("set_transaction_id %d %d", oldID, newID)); err != nil {
   625  		return fmt.Errorf("devicemapper: Can't set message %s", err)
   626  	}
   627  
   628  	if err := task.run(); err != nil {
   629  		return fmt.Errorf("devicemapper: Error running SetTransactionID %s", err)
   630  	}
   631  	return nil
   632  }
   633  
   634  // SuspendDevice is the programmatic example of "dmsetup suspend".
   635  // It suspends the specified device.
   636  func SuspendDevice(name string) error {
   637  	task, err := TaskCreateNamed(deviceSuspend, name)
   638  	if task == nil {
   639  		return err
   640  	}
   641  	if err := task.run(); err != nil {
   642  		return fmt.Errorf("devicemapper: Error running deviceSuspend %s", err)
   643  	}
   644  	return nil
   645  }
   646  
   647  // ResumeDevice is the programmatic example of "dmsetup resume".
   648  // It un-suspends the specified device.
   649  func ResumeDevice(name string) error {
   650  	task, err := TaskCreateNamed(deviceResume, name)
   651  	if task == nil {
   652  		return err
   653  	}
   654  
   655  	cookie := new(uint)
   656  	if err := task.setCookie(cookie, 0); err != nil {
   657  		return fmt.Errorf("devicemapper: Can't set cookie %s", err)
   658  	}
   659  	defer UdevWait(cookie)
   660  
   661  	if err := task.run(); err != nil {
   662  		return fmt.Errorf("devicemapper: Error running deviceResume %s", err)
   663  	}
   664  
   665  	return nil
   666  }
   667  
   668  // CreateDevice creates a device with the specified poolName with the specified device id.
   669  func CreateDevice(poolName string, deviceID int) error {
   670  	logrus.Debugf("devicemapper: CreateDevice(poolName=%v, deviceID=%v)", poolName, deviceID)
   671  	task, err := TaskCreateNamed(deviceTargetMsg, poolName)
   672  	if task == nil {
   673  		return err
   674  	}
   675  
   676  	if err := task.setSector(0); err != nil {
   677  		return fmt.Errorf("devicemapper: Can't set sector %s", err)
   678  	}
   679  
   680  	if err := task.setMessage(fmt.Sprintf("create_thin %d", deviceID)); err != nil {
   681  		return fmt.Errorf("devicemapper: Can't set message %s", err)
   682  	}
   683  
   684  	dmSawExist = false // reset before the task is run
   685  	if err := task.run(); err != nil {
   686  		// Caller wants to know about ErrDeviceIDExists so that it can try with a different device id.
   687  		if dmSawExist {
   688  			return ErrDeviceIDExists
   689  		}
   690  
   691  		return fmt.Errorf("devicemapper: Error running CreateDevice %s", err)
   692  
   693  	}
   694  	return nil
   695  }
   696  
   697  // DeleteDevice deletes a device with the specified poolName with the specified device id.
   698  func DeleteDevice(poolName string, deviceID int) error {
   699  	task, err := TaskCreateNamed(deviceTargetMsg, poolName)
   700  	if task == nil {
   701  		return err
   702  	}
   703  
   704  	if err := task.setSector(0); err != nil {
   705  		return fmt.Errorf("devicemapper: Can't set sector %s", err)
   706  	}
   707  
   708  	if err := task.setMessage(fmt.Sprintf("delete %d", deviceID)); err != nil {
   709  		return fmt.Errorf("devicemapper: Can't set message %s", err)
   710  	}
   711  
   712  	dmSawBusy = false
   713  	dmSawEnoData = false
   714  	if err := task.run(); err != nil {
   715  		if dmSawBusy {
   716  			return ErrBusy
   717  		}
   718  		if dmSawEnoData {
   719  			logrus.Debugf("devicemapper: Device(id: %d) from pool(%s) does not exist", deviceID, poolName)
   720  			return nil
   721  		}
   722  		return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err)
   723  	}
   724  	return nil
   725  }
   726  
   727  // ActivateDevice activates the device identified by the specified
   728  // poolName, name and deviceID with the specified size.
   729  func ActivateDevice(poolName string, name string, deviceID int, size uint64) error {
   730  	return activateDevice(poolName, name, deviceID, size, "")
   731  }
   732  
   733  // ActivateDeviceWithExternal activates the device identified by the specified
   734  // poolName, name and deviceID with the specified size.
   735  func ActivateDeviceWithExternal(poolName string, name string, deviceID int, size uint64, external string) error {
   736  	return activateDevice(poolName, name, deviceID, size, external)
   737  }
   738  
   739  func activateDevice(poolName string, name string, deviceID int, size uint64, external string) error {
   740  	task, err := TaskCreateNamed(deviceCreate, name)
   741  	if task == nil {
   742  		return err
   743  	}
   744  
   745  	var params string
   746  	if len(external) > 0 {
   747  		params = fmt.Sprintf("%s %d %s", poolName, deviceID, external)
   748  	} else {
   749  		params = fmt.Sprintf("%s %d", poolName, deviceID)
   750  	}
   751  	if err := task.addTarget(0, size/512, "thin", params); err != nil {
   752  		return fmt.Errorf("devicemapper: Can't add target %s", err)
   753  	}
   754  	if err := task.setAddNode(addNodeOnCreate); err != nil {
   755  		return fmt.Errorf("devicemapper: Can't add node %s", err)
   756  	}
   757  
   758  	cookie := new(uint)
   759  	if err := task.setCookie(cookie, 0); err != nil {
   760  		return fmt.Errorf("devicemapper: Can't set cookie %s", err)
   761  	}
   762  
   763  	defer UdevWait(cookie)
   764  
   765  	if err := task.run(); err != nil {
   766  		return fmt.Errorf("devicemapper: Error running deviceCreate (ActivateDevice) %s", err)
   767  	}
   768  
   769  	return nil
   770  }
   771  
   772  // CreateSnapDeviceRaw creates a snapshot device. Caller needs to suspend and resume the origin device if it is active.
   773  func CreateSnapDeviceRaw(poolName string, deviceID int, baseDeviceID int) error {
   774  	task, err := TaskCreateNamed(deviceTargetMsg, poolName)
   775  	if task == nil {
   776  		return err
   777  	}
   778  
   779  	if err := task.setSector(0); err != nil {
   780  		return fmt.Errorf("devicemapper: Can't set sector %s", err)
   781  	}
   782  
   783  	if err := task.setMessage(fmt.Sprintf("create_snap %d %d", deviceID, baseDeviceID)); err != nil {
   784  		return fmt.Errorf("devicemapper: Can't set message %s", err)
   785  	}
   786  
   787  	dmSawExist = false // reset before the task is run
   788  	if err := task.run(); err != nil {
   789  		// Caller wants to know about ErrDeviceIDExists so that it can try with a different device id.
   790  		if dmSawExist {
   791  			return ErrDeviceIDExists
   792  		}
   793  		return fmt.Errorf("devicemapper: Error running deviceCreate (CreateSnapDeviceRaw) %s", err)
   794  	}
   795  
   796  	return nil
   797  }
   798  
   799  // CreateSnapDevice creates a snapshot based on the device identified by the baseName and baseDeviceId,
   800  func CreateSnapDevice(poolName string, deviceID int, baseName string, baseDeviceID int) error {
   801  	devinfo, _ := GetInfo(baseName)
   802  	doSuspend := devinfo != nil && devinfo.Exists != 0
   803  
   804  	if doSuspend {
   805  		if err := SuspendDevice(baseName); err != nil {
   806  			return err
   807  		}
   808  	}
   809  
   810  	if err := CreateSnapDeviceRaw(poolName, deviceID, baseDeviceID); err != nil {
   811  		if doSuspend {
   812  			if err2 := ResumeDevice(baseName); err2 != nil {
   813  				return fmt.Errorf("CreateSnapDeviceRaw Error: (%v): ResumeDevice Error: (%v)", err, err2)
   814  			}
   815  		}
   816  		return err
   817  	}
   818  
   819  	if doSuspend {
   820  		if err := ResumeDevice(baseName); err != nil {
   821  			return err
   822  		}
   823  	}
   824  
   825  	return nil
   826  }