Merge pull request #12190 from rhvgoyal/deferred-removal

Devicemapper: Provide deferred device removal capability
This commit is contained in:
Vincent Batts 2015-05-04 14:22:52 -07:00
commit 1bf233b404
5 changed files with 157 additions and 32 deletions

View file

@ -55,6 +55,7 @@ var (
ErrTaskGetDeps = errors.New("dm_task_get_deps failed")
ErrTaskGetInfo = errors.New("dm_task_get_info 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")
ErrNilCookie = errors.New("cookie ptr can't be nil")
ErrAttachLoopbackDevice = errors.New("loopback mounting failed")
@ -69,9 +70,11 @@ var (
ErrLoopbackSetCapacity = errors.New("Unable set loopback capacity")
ErrBusy = errors.New("Device is Busy")
ErrDeviceIdExists = errors.New("Device Id Exists")
ErrEnxio = errors.New("No such device or address")
dmSawBusy bool
dmSawExist bool
dmSawEnxio bool // No Such Device or Address
)
type (
@ -84,16 +87,17 @@ type (
Device []uint64
}
Info struct {
Exists int
Suspended int
LiveTable int
InactiveTable int
OpenCount int32
EventNr uint32
Major uint32
Minor uint32
ReadOnly int
TargetCount int32
Exists int
Suspended int
LiveTable int
InactiveTable int
OpenCount int32
EventNr uint32
Major uint32
Minor uint32
ReadOnly int
TargetCount int32
DeferredRemove int
}
TaskType int
AddNodeType int
@ -219,6 +223,14 @@ func (t *Task) GetInfo() (*Info, error) {
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) {
res := DmTaskGetDriverVersion(t.unmanaged)
if res == "" {
@ -371,6 +383,55 @@ func RemoveDevice(name string) error {
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) {
size, err := ioctlBlkGetSize64(file.Fd())
if err != nil {
@ -479,6 +540,17 @@ func GetInfo(name string) (*Info, error) {
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) {
task := TaskCreate(DeviceVersion)
if task == nil {

View file

@ -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") {
dmSawExist = true
}
if strings.Contains(msg, "No such device or address") {
dmSawEnxio = true
}
}
if dmLogger != nil {

View file

@ -90,28 +90,30 @@ const (
)
var (
DmGetLibraryVersion = dmGetLibraryVersionFct
DmGetNextTarget = dmGetNextTargetFct
DmLogInitVerbose = dmLogInitVerboseFct
DmSetDevDir = dmSetDevDirFct
DmTaskAddTarget = dmTaskAddTargetFct
DmTaskCreate = dmTaskCreateFct
DmTaskDestroy = dmTaskDestroyFct
DmTaskGetDeps = dmTaskGetDepsFct
DmTaskGetInfo = dmTaskGetInfoFct
DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
DmTaskRun = dmTaskRunFct
DmTaskSetAddNode = dmTaskSetAddNodeFct
DmTaskSetCookie = dmTaskSetCookieFct
DmTaskSetMessage = dmTaskSetMessageFct
DmTaskSetName = dmTaskSetNameFct
DmTaskSetRo = dmTaskSetRoFct
DmTaskSetSector = dmTaskSetSectorFct
DmUdevWait = dmUdevWaitFct
DmUdevSetSyncSupport = dmUdevSetSyncSupportFct
DmUdevGetSyncSupport = dmUdevGetSyncSupportFct
DmCookieSupported = dmCookieSupportedFct
LogWithErrnoInit = logWithErrnoInitFct
DmGetLibraryVersion = dmGetLibraryVersionFct
DmGetNextTarget = dmGetNextTargetFct
DmLogInitVerbose = dmLogInitVerboseFct
DmSetDevDir = dmSetDevDirFct
DmTaskAddTarget = dmTaskAddTargetFct
DmTaskCreate = dmTaskCreateFct
DmTaskDestroy = dmTaskDestroyFct
DmTaskGetDeps = dmTaskGetDepsFct
DmTaskGetInfo = dmTaskGetInfoFct
DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
DmTaskRun = dmTaskRunFct
DmTaskSetAddNode = dmTaskSetAddNodeFct
DmTaskSetCookie = dmTaskSetCookieFct
DmTaskSetMessage = dmTaskSetMessageFct
DmTaskSetName = dmTaskSetNameFct
DmTaskSetRo = dmTaskSetRoFct
DmTaskSetSector = dmTaskSetSectorFct
DmUdevWait = dmUdevWaitFct
DmUdevSetSyncSupport = dmUdevSetSyncSupportFct
DmUdevGetSyncSupport = dmUdevGetSyncSupportFct
DmCookieSupported = dmCookieSupportedFct
LogWithErrnoInit = logWithErrnoInitFct
DmTaskDeferredRemove = dmTaskDeferredRemoveFct
DmTaskGetInfoWithDeferred = dmTaskGetInfoWithDeferredFct
)
func free(p *C.char) {

View 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))
}

View 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
}