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, ¶ms), 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 }