Merge pull request #3256 from alexlarsson/blkdiscard
Discard all data on devicemapper devices when deleting them
This commit is contained in:
commit
a60f0a0754
|
@ -568,6 +568,15 @@ func (devices *DeviceSet) removeDevice(hash string) error {
|
||||||
return fmt.Errorf("hash %s doesn't exists", hash)
|
return fmt.Errorf("hash %s doesn't exists", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a workaround for the kernel not discarding block so
|
||||||
|
// on the thin pool when we remove a thinp device, so we do it
|
||||||
|
// manually
|
||||||
|
if err := devices.activateDeviceIfNeeded(hash); err == nil {
|
||||||
|
if err := BlockDeviceDiscard(info.DevName()); err != nil {
|
||||||
|
utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
devinfo, _ := getInfo(info.Name())
|
devinfo, _ := getInfo(info.Name())
|
||||||
if devinfo != nil && devinfo.Exists != 0 {
|
if devinfo != nil && devinfo.Exists != 0 {
|
||||||
if err := removeDevice(info.Name()); err != nil {
|
if err := removeDevice(info.Name()); err != nil {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DevmapperLogger interface {
|
type DevmapperLogger interface {
|
||||||
|
@ -288,6 +289,29 @@ func GetBlockDeviceSize(file *osFile) (uint64, error) {
|
||||||
return uint64(size), nil
|
return uint64(size), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BlockDeviceDiscard(path string) error {
|
||||||
|
file, err := osOpenFile(path, osORdWr, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
size, err := GetBlockDeviceSize(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ioctlBlkDiscard(file.Fd(), 0, size); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without this sometimes the remove of the device that happens after
|
||||||
|
// discard fails with EBUSY.
|
||||||
|
syscall.Sync()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// This is the programmatic example of "dmsetup create"
|
// This is the programmatic example of "dmsetup create"
|
||||||
func createPool(poolName string, dataFile, metadataFile *osFile) error {
|
func createPool(poolName string, dataFile, metadataFile *osFile) error {
|
||||||
task, err := createTask(DeviceCreate, poolName)
|
task, err := createTask(DeviceCreate, poolName)
|
||||||
|
|
|
@ -66,6 +66,7 @@ type (
|
||||||
// IOCTL consts
|
// IOCTL consts
|
||||||
const (
|
const (
|
||||||
BlkGetSize64 = C.BLKGETSIZE64
|
BlkGetSize64 = C.BLKGETSIZE64
|
||||||
|
BlkDiscard = C.BLKDISCARD
|
||||||
|
|
||||||
LoopSetFd = C.LOOP_SET_FD
|
LoopSetFd = C.LOOP_SET_FD
|
||||||
LoopCtlGetFree = C.LOOP_CTL_GET_FREE
|
LoopCtlGetFree = C.LOOP_CTL_GET_FREE
|
||||||
|
|
|
@ -641,6 +641,10 @@ func TestDriverRemove(t *testing.T) {
|
||||||
"DmTaskSetMessage",
|
"DmTaskSetMessage",
|
||||||
"DmTaskCreate",
|
"DmTaskCreate",
|
||||||
"DmTaskGetInfo",
|
"DmTaskGetInfo",
|
||||||
|
"DmTaskSetCookie",
|
||||||
|
"DmTaskSetTarget",
|
||||||
|
"DmTaskSetAddNode",
|
||||||
|
"DmUdevWait",
|
||||||
"Mounted",
|
"Mounted",
|
||||||
"sysUnmount",
|
"sysUnmount",
|
||||||
)
|
)
|
||||||
|
|
|
@ -58,3 +58,14 @@ func ioctlBlkGetSize64(fd uintptr) (int64, error) {
|
||||||
}
|
}
|
||||||
return size, nil
|
return size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ioctlBlkDiscard(fd uintptr, offset, length uint64) error {
|
||||||
|
var r [2]uint64
|
||||||
|
r[0] = offset
|
||||||
|
r[1] = length
|
||||||
|
|
||||||
|
if _, _, err := sysSyscall(sysSysIoctl, fd, BlkDiscard, uintptr(unsafe.Pointer(&r[0]))); err != 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue