From c383436af75e3b3db3dc42f12e76f53f766647e2 Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Mon, 6 Jul 2020 15:30:09 -0700 Subject: [PATCH] snapshots/devmapper: suspend a device to avoid data corruption According to https://github.com/torvalds/linux/blob/v5.7/Documentation/admin-guide/device-mapper/thin-provisioning.rst#internal-snapshots; > If the origin device that you wish to snapshot is active, you > must suspend it before creating the snapshot to avoid corruption. However the devmapper snapshotter was not doing that. Signed-off-by: Kazuyoshi Kato --- snapshots/devmapper/pool_device.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/snapshots/devmapper/pool_device.go b/snapshots/devmapper/pool_device.go index 52b045658..77ad456c1 100644 --- a/snapshots/devmapper/pool_device.go +++ b/snapshots/devmapper/pool_device.go @@ -306,6 +306,23 @@ func (p *PoolDevice) CreateSnapshotDevice(ctx context.Context, deviceName string return metaErr } + // The base device must be suspend before taking a snapshot to + // avoid corruption. + // https://github.com/torvalds/linux/blob/v5.7/Documentation/admin-guide/device-mapper/thin-provisioning.rst#internal-snapshots + if p.IsLoaded(deviceName) { + log.G(ctx).Debugf("suspending %q before taking its snapshot", deviceName) + suspendErr := p.SuspendDevice(ctx, deviceName) + if suspendErr != nil { + return suspendErr + } + defer func() { + err := p.ResumeDevice(ctx, deviceName) + if err != nil { + log.G(ctx).WithError(err).Errorf("failed to resume base device %q after taking its snapshot", baseInfo.Name) + } + }() + } + // Create thin device snapshot devErr = p.createSnapshot(ctx, baseInfo, snapInfo) if devErr != nil {