diff --git a/pkg/zfs/xfs_util.go b/pkg/zfs/xfs_util.go new file mode 100644 index 0000000..256779c --- /dev/null +++ b/pkg/zfs/xfs_util.go @@ -0,0 +1,90 @@ +/* +Copyright 2020 The OpenEBS Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package zfs + +import ( + "os" + "os/exec" + + "github.com/Sirupsen/logrus" + "strings" +) + +func xfs_temp_mount(volume string) error { + device := ZFS_DEVPATH + volume + pvol := strings.Split(volume, "/") + + // create a temporary directory to mount the xfs file system + tmpdir := "/tmp/" + pvol[1] + err := os.Mkdir(tmpdir, 0755) + if err != nil { + logrus.Errorf("xfs: failed to create tmpdir %s error: %s", tmpdir, err.Error()) + return err + } + + // mount with nouuid, so that it can play the log + cmd := exec.Command("mount", "-o", "nouuid", device, tmpdir) + out, err := cmd.CombinedOutput() + if err != nil { + logrus.Errorf("xfs: failed to mount volume %s=>%s error: %s", device, tmpdir, string(out)) + return err + } + + // log has been replayed, unmount the volume + cmd = exec.Command("umount", tmpdir) + out, err = cmd.CombinedOutput() + if err != nil { + logrus.Errorf("xfs: failed to umount tmpdir %s error: %s", tmpdir, string(out)) + return err + } + + // remove the directory + err = os.Remove(tmpdir) + if err != nil { + logrus.Errorf("xfs: failed to remove tmpdir %s error: %s", tmpdir, err.Error()) + return err + } + return nil +} + +/* +* We have to generate a new UUID for the cloned volumes with xfs filesystem +* otherwise system won't let anyone mount it if UUID is same. Here, since cloned +* volume refers to the same block because of the way ZFS clone works, it will +* also have the same UUID. +* There might be something there in the xfs log, we have to clear them +* so that filesystem is clean and we can generate the UUID for it. + */ +func xfs_generate_uuid(volume string) error { + device := ZFS_DEVPATH + volume + + // temporary mount the volume with nouuid to replay the logs + err := xfs_temp_mount(volume) + if err != nil { + return err + } + + // for mounting the cloned volume for xfs, a new UUID has to be generated + cmd := exec.Command("xfs_admin", "-U", "generate", device) + out, err := cmd.CombinedOutput() + if err != nil { + logrus.Errorf("xfs: uuid generate failed %s error: %s", volume, string(out)) + return err + } + logrus.Infof("xfs: generated UUID for the cloned volume %s \n %v", volume, string(out)) + return nil +} diff --git a/pkg/zfs/zfs_util.go b/pkg/zfs/zfs_util.go index bcae020..cefb3b1 100644 --- a/pkg/zfs/zfs_util.go +++ b/pkg/zfs/zfs_util.go @@ -362,14 +362,7 @@ func CreateClone(vol *apis.ZFSVolume) error { } if vol.Spec.FsType == "xfs" { - // for mounting the cloned volume for xfs, a new UUID has to be generated - device := ZFS_DEVPATH + volume - cmd := exec.Command("xfs_admin", "-U", "generate", device) - out, err := cmd.CombinedOutput() - if err != nil { - logrus.Errorf("zfspv: Clone XFS uuid generate failed error: %s", string(out)) - return err - } + return xfs_generate_uuid(volume) } return nil }