From d57976e48344f77fbdd951a170115e13a03bbd18 Mon Sep 17 00:00:00 2001 From: Pawan Date: Wed, 22 Apr 2020 12:07:25 +0530 Subject: [PATCH] fix(zfspv): fixing data loss in case of pod deletion looks like a bug in ZFS as when you change the mountpoint property to none, ZFS automatically umounts the file system. When we delete the pod, we get the unmount request for the old pod and mount request for the new pod. Unmount is done by the driver by setting mountpoint to none and the driver assumes that unmount has done and proceeded to delete the mountpath, but here zfs has not unmounted the dataset ``` $ sudo zfs get all zfspv-pool/pvc-3fe69b0e-9f91-4c6e-8e5c-eb4218468765 | grep mount zfspv-pool/pvc-3fe69b0e-9f91-4c6e-8e5c-eb4218468765 mounted yes - zfspv-pool/pvc-3fe69b0e-9f91-4c6e-8e5c-eb4218468765 mountpoint none local zfspv-pool/pvc-3fe69b0e-9f91-4c6e-8e5c-eb4218468765 canmount on ``` here, the driver will assume that dataset has been unmouted and proceed to delete the mountpath and it will delete the data as part of cleaning up for the NodeUnPublish request. Shifting to use zfs umount instead of doing zfs set mountpoint=none for umounting the dataset. Also the driver is using os.RemoveAll which is very risky as it will clean child also, since the mountpoint is not supposed to have anything, just os.Remove is sufficient and it will fail if there is anything there. Signed-off-by: Pawan --- pkg/zfs/mount.go | 3 +-- pkg/zfs/zfs_util.go | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkg/zfs/mount.go b/pkg/zfs/mount.go index 464b50b..a9b8c88 100644 --- a/pkg/zfs/mount.go +++ b/pkg/zfs/mount.go @@ -78,9 +78,8 @@ func UmountVolume(vol *apis.ZFSVolume, targetPath string, } } - if err := os.RemoveAll(targetPath); err != nil { + if err := os.Remove(targetPath); err != nil { logrus.Errorf("zfspv: failed to remove mount path Error: %v", err) - return err } logrus.Infof("umount done path %v", targetPath) diff --git a/pkg/zfs/zfs_util.go b/pkg/zfs/zfs_util.go index a00d668..c2c911b 100644 --- a/pkg/zfs/zfs_util.go +++ b/pkg/zfs/zfs_util.go @@ -422,8 +422,22 @@ func MountZFSDataset(vol *apis.ZFSVolume, mountpath string) error { // UmountZFSDataset umounts the dataset func UmountZFSDataset(vol *apis.ZFSVolume) error { volume := vol.Spec.PoolName + "/" + vol.Name + var MountVolArg []string + MountVolArg = append(MountVolArg, "umount", volume) + cmd := exec.Command(ZFSVolCmd, MountVolArg...) + out, err := cmd.CombinedOutput() + if err != nil { + logrus.Errorf("zfs: could not umount the dataset %v cmd %v error: %s", + volume, MountVolArg, string(out)) + return err + } + // ignoring the failure of setting the mountpoint to none + // as the dataset has already been umounted, now the new pod + // can mount it and it will change that to desired mountpath + // and try to mount it if not mounted + SetDatasetMountProp(volume, "none") - return SetDatasetMountProp(volume, "none") + return nil } // GetVolumeProperty gets zfs properties for the volume