github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/pkg/devicemapper/devmapper.go (about)

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