Merge pull request #12190 from rhvgoyal/deferred-removal
Devicemapper: Provide deferred device removal capability
This commit is contained in:
commit
1bf233b404
5 changed files with 157 additions and 32 deletions
|
@ -55,6 +55,7 @@ var (
|
||||||
ErrTaskGetDeps = errors.New("dm_task_get_deps failed")
|
ErrTaskGetDeps = errors.New("dm_task_get_deps failed")
|
||||||
ErrTaskGetInfo = errors.New("dm_task_get_info failed")
|
ErrTaskGetInfo = errors.New("dm_task_get_info failed")
|
||||||
ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed")
|
ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed")
|
||||||
|
ErrTaskDeferredRemove = errors.New("dm_task_deferred_remove failed")
|
||||||
ErrTaskSetCookie = errors.New("dm_task_set_cookie failed")
|
ErrTaskSetCookie = errors.New("dm_task_set_cookie failed")
|
||||||
ErrNilCookie = errors.New("cookie ptr can't be nil")
|
ErrNilCookie = errors.New("cookie ptr can't be nil")
|
||||||
ErrAttachLoopbackDevice = errors.New("loopback mounting failed")
|
ErrAttachLoopbackDevice = errors.New("loopback mounting failed")
|
||||||
|
@ -69,9 +70,11 @@ var (
|
||||||
ErrLoopbackSetCapacity = errors.New("Unable set loopback capacity")
|
ErrLoopbackSetCapacity = errors.New("Unable set loopback capacity")
|
||||||
ErrBusy = errors.New("Device is Busy")
|
ErrBusy = errors.New("Device is Busy")
|
||||||
ErrDeviceIdExists = errors.New("Device Id Exists")
|
ErrDeviceIdExists = errors.New("Device Id Exists")
|
||||||
|
ErrEnxio = errors.New("No such device or address")
|
||||||
|
|
||||||
dmSawBusy bool
|
dmSawBusy bool
|
||||||
dmSawExist bool
|
dmSawExist bool
|
||||||
|
dmSawEnxio bool // No Such Device or Address
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -84,16 +87,17 @@ type (
|
||||||
Device []uint64
|
Device []uint64
|
||||||
}
|
}
|
||||||
Info struct {
|
Info struct {
|
||||||
Exists int
|
Exists int
|
||||||
Suspended int
|
Suspended int
|
||||||
LiveTable int
|
LiveTable int
|
||||||
InactiveTable int
|
InactiveTable int
|
||||||
OpenCount int32
|
OpenCount int32
|
||||||
EventNr uint32
|
EventNr uint32
|
||||||
Major uint32
|
Major uint32
|
||||||
Minor uint32
|
Minor uint32
|
||||||
ReadOnly int
|
ReadOnly int
|
||||||
TargetCount int32
|
TargetCount int32
|
||||||
|
DeferredRemove int
|
||||||
}
|
}
|
||||||
TaskType int
|
TaskType int
|
||||||
AddNodeType int
|
AddNodeType int
|
||||||
|
@ -219,6 +223,14 @@ func (t *Task) GetInfo() (*Info, error) {
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Task) GetInfoWithDeferred() (*Info, error) {
|
||||||
|
info := &Info{}
|
||||||
|
if res := DmTaskGetInfoWithDeferred(t.unmanaged, info); res != 1 {
|
||||||
|
return nil, ErrTaskGetInfo
|
||||||
|
}
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Task) GetDriverVersion() (string, error) {
|
func (t *Task) GetDriverVersion() (string, error) {
|
||||||
res := DmTaskGetDriverVersion(t.unmanaged)
|
res := DmTaskGetDriverVersion(t.unmanaged)
|
||||||
if res == "" {
|
if res == "" {
|
||||||
|
@ -371,6 +383,55 @@ func RemoveDevice(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RemoveDeviceDeferred(name string) error {
|
||||||
|
logrus.Debugf("[devmapper] RemoveDeviceDeferred START(%s)", name)
|
||||||
|
defer logrus.Debugf("[devmapper] RemoveDeviceDeferred END(%s)", name)
|
||||||
|
task, err := TaskCreateNamed(DeviceRemove, name)
|
||||||
|
if task == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DmTaskDeferredRemove(task.unmanaged); err != 1 {
|
||||||
|
return ErrTaskDeferredRemove
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = task.Run(); err != nil {
|
||||||
|
return fmt.Errorf("Error running RemoveDeviceDeferred %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Useful helper for cleanup
|
||||||
|
func CancelDeferredRemove(deviceName string) error {
|
||||||
|
task, err := TaskCreateNamed(DeviceTargetMsg, deviceName)
|
||||||
|
if task == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := task.SetSector(0); err != nil {
|
||||||
|
return fmt.Errorf("Can't set sector %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := task.SetMessage(fmt.Sprintf("@cancel_deferred_remove")); err != nil {
|
||||||
|
return fmt.Errorf("Can't set message %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dmSawBusy = false
|
||||||
|
dmSawEnxio = false
|
||||||
|
if err := task.Run(); err != nil {
|
||||||
|
// A device might be being deleted already
|
||||||
|
if dmSawBusy {
|
||||||
|
return ErrBusy
|
||||||
|
} else if dmSawEnxio {
|
||||||
|
return ErrEnxio
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Error running CancelDeferredRemove %s", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetBlockDeviceSize(file *os.File) (uint64, error) {
|
func GetBlockDeviceSize(file *os.File) (uint64, error) {
|
||||||
size, err := ioctlBlkGetSize64(file.Fd())
|
size, err := ioctlBlkGetSize64(file.Fd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -479,6 +540,17 @@ func GetInfo(name string) (*Info, error) {
|
||||||
return task.GetInfo()
|
return task.GetInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetInfoWithDeferred(name string) (*Info, error) {
|
||||||
|
task, err := TaskCreateNamed(DeviceInfo, name)
|
||||||
|
if task == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := task.Run(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return task.GetInfoWithDeferred()
|
||||||
|
}
|
||||||
|
|
||||||
func GetDriverVersion() (string, error) {
|
func GetDriverVersion() (string, error) {
|
||||||
task := TaskCreate(DeviceVersion)
|
task := TaskCreate(DeviceVersion)
|
||||||
if task == nil {
|
if task == nil {
|
||||||
|
|
|
@ -22,6 +22,10 @@ func DevmapperLogCallback(level C.int, file *C.char, line C.int, dm_errno_or_cla
|
||||||
if strings.Contains(msg, "File exists") {
|
if strings.Contains(msg, "File exists") {
|
||||||
dmSawExist = true
|
dmSawExist = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.Contains(msg, "No such device or address") {
|
||||||
|
dmSawEnxio = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dmLogger != nil {
|
if dmLogger != nil {
|
||||||
|
|
|
@ -90,28 +90,30 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DmGetLibraryVersion = dmGetLibraryVersionFct
|
DmGetLibraryVersion = dmGetLibraryVersionFct
|
||||||
DmGetNextTarget = dmGetNextTargetFct
|
DmGetNextTarget = dmGetNextTargetFct
|
||||||
DmLogInitVerbose = dmLogInitVerboseFct
|
DmLogInitVerbose = dmLogInitVerboseFct
|
||||||
DmSetDevDir = dmSetDevDirFct
|
DmSetDevDir = dmSetDevDirFct
|
||||||
DmTaskAddTarget = dmTaskAddTargetFct
|
DmTaskAddTarget = dmTaskAddTargetFct
|
||||||
DmTaskCreate = dmTaskCreateFct
|
DmTaskCreate = dmTaskCreateFct
|
||||||
DmTaskDestroy = dmTaskDestroyFct
|
DmTaskDestroy = dmTaskDestroyFct
|
||||||
DmTaskGetDeps = dmTaskGetDepsFct
|
DmTaskGetDeps = dmTaskGetDepsFct
|
||||||
DmTaskGetInfo = dmTaskGetInfoFct
|
DmTaskGetInfo = dmTaskGetInfoFct
|
||||||
DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
|
DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
|
||||||
DmTaskRun = dmTaskRunFct
|
DmTaskRun = dmTaskRunFct
|
||||||
DmTaskSetAddNode = dmTaskSetAddNodeFct
|
DmTaskSetAddNode = dmTaskSetAddNodeFct
|
||||||
DmTaskSetCookie = dmTaskSetCookieFct
|
DmTaskSetCookie = dmTaskSetCookieFct
|
||||||
DmTaskSetMessage = dmTaskSetMessageFct
|
DmTaskSetMessage = dmTaskSetMessageFct
|
||||||
DmTaskSetName = dmTaskSetNameFct
|
DmTaskSetName = dmTaskSetNameFct
|
||||||
DmTaskSetRo = dmTaskSetRoFct
|
DmTaskSetRo = dmTaskSetRoFct
|
||||||
DmTaskSetSector = dmTaskSetSectorFct
|
DmTaskSetSector = dmTaskSetSectorFct
|
||||||
DmUdevWait = dmUdevWaitFct
|
DmUdevWait = dmUdevWaitFct
|
||||||
DmUdevSetSyncSupport = dmUdevSetSyncSupportFct
|
DmUdevSetSyncSupport = dmUdevSetSyncSupportFct
|
||||||
DmUdevGetSyncSupport = dmUdevGetSyncSupportFct
|
DmUdevGetSyncSupport = dmUdevGetSyncSupportFct
|
||||||
DmCookieSupported = dmCookieSupportedFct
|
DmCookieSupported = dmCookieSupportedFct
|
||||||
LogWithErrnoInit = logWithErrnoInitFct
|
LogWithErrnoInit = logWithErrnoInitFct
|
||||||
|
DmTaskDeferredRemove = dmTaskDeferredRemoveFct
|
||||||
|
DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct
|
||||||
)
|
)
|
||||||
|
|
||||||
func free(p *C.char) {
|
func free(p *C.char) {
|
||||||
|
|
33
devicemapper/devmapper_wrapper_deferred_remove.go
Normal file
33
devicemapper/devmapper_wrapper_deferred_remove.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// +build linux,!libdm_no_deferred_remove
|
||||||
|
|
||||||
|
package devicemapper
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -L. -ldevmapper
|
||||||
|
#include <libdevmapper.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const LibraryDeferredRemovalSupport = true
|
||||||
|
|
||||||
|
func dmTaskDeferredRemoveFct(task *CDmTask) int {
|
||||||
|
return int(C.dm_task_deferred_remove((*C.struct_dm_task)(task)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func dmTaskGetInfoWithDeferredFct(task *CDmTask, info *Info) int {
|
||||||
|
Cinfo := C.struct_dm_info{}
|
||||||
|
defer func() {
|
||||||
|
info.Exists = int(Cinfo.exists)
|
||||||
|
info.Suspended = int(Cinfo.suspended)
|
||||||
|
info.LiveTable = int(Cinfo.live_table)
|
||||||
|
info.InactiveTable = int(Cinfo.inactive_table)
|
||||||
|
info.OpenCount = int32(Cinfo.open_count)
|
||||||
|
info.EventNr = uint32(Cinfo.event_nr)
|
||||||
|
info.Major = uint32(Cinfo.major)
|
||||||
|
info.Minor = uint32(Cinfo.minor)
|
||||||
|
info.ReadOnly = int(Cinfo.read_only)
|
||||||
|
info.TargetCount = int32(Cinfo.target_count)
|
||||||
|
info.DeferredRemove = int(Cinfo.deferred_remove)
|
||||||
|
}()
|
||||||
|
return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo))
|
||||||
|
}
|
14
devicemapper/devmapper_wrapper_no_deferred_remove.go
Normal file
14
devicemapper/devmapper_wrapper_no_deferred_remove.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// +build linux,libdm_no_deferred_remove
|
||||||
|
|
||||||
|
package devicemapper
|
||||||
|
|
||||||
|
const LibraryDeferredRemovalSupport = false
|
||||||
|
|
||||||
|
func dmTaskDeferredRemoveFct(task *CDmTask) int {
|
||||||
|
// Error. Nobody should be calling it.
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func dmTaskGetInfoWithDeferredFct(task *CDmTask, info *Info) int {
|
||||||
|
return -1
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue