From 8451d03d8ef7457f82112179cd3e300c05a08d3d Mon Sep 17 00:00:00 2001 From: Liu Hua Date: Mon, 23 Oct 2017 21:00:22 +0800 Subject: [PATCH 1/2] Devicemapper: ignore Nodata errors when delete thin device if thin device is deteled and the metadata exists, you can not delete related containers. This patch ignore Nodata errors for thin device deletion Signed-off-by: Liu Hua --- pkg/devicemapper/devmapper.go | 13 ++++++++++--- pkg/devicemapper/devmapper_log.go | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pkg/devicemapper/devmapper.go b/pkg/devicemapper/devmapper.go index 48618765fb..c72992f7a1 100644 --- a/pkg/devicemapper/devmapper.go +++ b/pkg/devicemapper/devmapper.go @@ -67,12 +67,14 @@ var ( ErrBusy = errors.New("Device is Busy") ErrDeviceIDExists = errors.New("Device Id Exists") ErrEnxio = errors.New("No such device or address") + ErrEnoData = errors.New("No data available") ) var ( - dmSawBusy bool - dmSawExist bool - dmSawEnxio bool // No Such Device or Address + dmSawBusy bool + dmSawExist bool + dmSawEnxio bool // No Such Device or Address + dmSawEnoData bool // No data available ) type ( @@ -708,10 +710,15 @@ func DeleteDevice(poolName string, deviceID int) error { } dmSawBusy = false + dmSawEnoData = false if err := task.run(); err != nil { if dmSawBusy { return ErrBusy } + if dmSawEnoData { + logrus.Debugf("devicemapper: Device(id: %d) from pool(%s) does not exist", deviceID, poolName) + return nil + } return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err) } return nil diff --git a/pkg/devicemapper/devmapper_log.go b/pkg/devicemapper/devmapper_log.go index f2ac7da87c..1da75101cf 100644 --- a/pkg/devicemapper/devmapper_log.go +++ b/pkg/devicemapper/devmapper_log.go @@ -55,6 +55,9 @@ func DevmapperLogCallback(level C.int, file *C.char, line, dmErrnoOrClass C.int, if strings.Contains(msg, "No such device or address") { dmSawEnxio = true } + if strings.Contains(msg, "No data available") { + dmSawEnoData = true + } } if dmLogger != nil { From 7c6ef28042c20fdad23cd461ab49b9cfa0c757df Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Tue, 2 Jan 2018 23:55:33 -0500 Subject: [PATCH 2/2] Add test case for 35333: Devicemapper: ignore Nodata errors when delete thin device This fix adds a test case for 35333: Devicemapper: ignore Nodata errors when delete thin device Signed-off-by: Yong Tang --- integration/container/stop_test.go | 74 ++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 integration/container/stop_test.go diff --git a/integration/container/stop_test.go b/integration/container/stop_test.go new file mode 100644 index 0000000000..feecc6901f --- /dev/null +++ b/integration/container/stop_test.go @@ -0,0 +1,74 @@ +package container + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" + "github.com/docker/docker/integration/util/request" + "github.com/gotestyourself/gotestyourself/icmd" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/gotestyourself/gotestyourself/skip" + "github.com/stretchr/testify/require" +) + +func TestDeleteDevicemapper(t *testing.T) { + skip.IfCondition(t, testEnv.DaemonInfo.Driver != "devicemapper") + + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + foo, err := client.ContainerCreate(ctx, + &container.Config{ + Cmd: []string{"echo"}, + Image: "busybox", + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "foo", + ) + require.NoError(t, err) + + err = client.ContainerStart(ctx, foo.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + inspect, err := client.ContainerInspect(ctx, foo.ID) + require.NoError(t, err) + + poll.WaitOn(t, containerIsStopped(ctx, client, foo.ID), poll.WithDelay(100*time.Millisecond)) + + deviceID := inspect.GraphDriver.Data["DeviceId"] + + // Find pool name from device name + deviceName := inspect.GraphDriver.Data["DeviceName"] + devicePrefix := deviceName[:strings.LastIndex(deviceName, "-")] + devicePool := fmt.Sprintf("/dev/mapper/%s-pool", devicePrefix) + + result := icmd.RunCommand("dmsetup", "message", devicePool, "0", fmt.Sprintf("delete %s", deviceID)) + result.Assert(t, icmd.Success) + + err = client.ContainerRemove(ctx, foo.ID, types.ContainerRemoveOptions{}) + require.NoError(t, err) +} + +func containerIsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result { + return func(log poll.LogT) poll.Result { + inspect, err := client.ContainerInspect(ctx, containerID) + + switch { + case err != nil: + return poll.Error(err) + case !inspect.State.Running: + return poll.Success() + default: + return poll.Continue("waiting for container to be stopped") + } + } +}