2020-03-26 20:52:53 +05:30
|
|
|
/*
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-11-25 18:49:51 +05:30
|
|
|
package xfs
|
2020-03-26 20:52:53 +05:30
|
|
|
|
|
|
|
|
import (
|
2020-11-25 18:49:51 +05:30
|
|
|
"github.com/openebs/zfs-localpv/pkg/mount"
|
2020-03-26 20:52:53 +05:30
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
2020-07-15 19:14:24 +05:30
|
|
|
"path/filepath"
|
2020-03-26 20:52:53 +05:30
|
|
|
|
|
|
|
|
"strings"
|
2020-06-29 12:18:33 +05:30
|
|
|
|
|
|
|
|
"k8s.io/klog"
|
2020-03-26 20:52:53 +05:30
|
|
|
)
|
|
|
|
|
|
2020-11-25 18:49:51 +05:30
|
|
|
func xfsTempMount(device string) error {
|
|
|
|
|
pvol := strings.Split(device, "/")
|
|
|
|
|
volname := pvol[len(pvol)-1]
|
2020-03-26 20:52:53 +05:30
|
|
|
|
2020-07-15 19:14:24 +05:30
|
|
|
// evaluate the symlink to get the dev path for volume
|
|
|
|
|
dev, err := filepath.EvalSymlinks(device)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-26 20:52:53 +05:30
|
|
|
// create a temporary directory to mount the xfs file system
|
2020-11-25 18:49:51 +05:30
|
|
|
tmpdir := "/tmp/" + volname
|
2020-07-15 19:14:24 +05:30
|
|
|
err = os.Mkdir(tmpdir, 0755)
|
|
|
|
|
if os.IsNotExist(err) {
|
2020-06-29 12:18:33 +05:30
|
|
|
klog.Errorf("xfs: failed to create tmpdir %s error: %s", tmpdir, err.Error())
|
2020-03-26 20:52:53 +05:30
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-15 19:14:24 +05:30
|
|
|
/*
|
|
|
|
|
* Device might have already mounted at the tmp path but umount might have failed
|
|
|
|
|
* in previous attempt. Checking here if device is not mounted then only attempt
|
|
|
|
|
* to mount it, otherwise proceed with the umount.
|
|
|
|
|
*/
|
2020-11-25 18:49:51 +05:30
|
|
|
curMounts, err := mount.GetMounts(dev)
|
2020-03-26 20:52:53 +05:30
|
|
|
if err != nil {
|
2020-07-15 19:14:24 +05:30
|
|
|
klog.Errorf("xfs: get mounts failed dev: %s err: %v", device, err.Error())
|
2020-03-26 20:52:53 +05:30
|
|
|
return err
|
2020-07-15 19:14:24 +05:30
|
|
|
} else if len(curMounts) == 0 {
|
|
|
|
|
// 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 {
|
2020-11-25 18:49:51 +05:30
|
|
|
klog.Errorf("xfs: failed to mount device %s => %s error: %s", device, tmpdir, string(out))
|
2020-07-15 19:14:24 +05:30
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
klog.Infof("xfs: device already mounted %s => [%v]", device, curMounts)
|
2020-03-26 20:52:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// log has been replayed, unmount the volume
|
2020-07-15 19:14:24 +05:30
|
|
|
cmd := exec.Command("umount", tmpdir)
|
|
|
|
|
out, err := cmd.CombinedOutput()
|
2020-03-26 20:52:53 +05:30
|
|
|
if err != nil {
|
2020-06-29 12:18:33 +05:30
|
|
|
klog.Errorf("xfs: failed to umount tmpdir %s error: %s", tmpdir, string(out))
|
2020-03-26 20:52:53 +05:30
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-15 19:14:24 +05:30
|
|
|
// remove the tmp directory
|
2020-03-26 20:52:53 +05:30
|
|
|
err = os.Remove(tmpdir)
|
|
|
|
|
if err != nil {
|
2020-07-15 19:14:24 +05:30
|
|
|
// don't return error, reconciliation is not needed as umount is done
|
2020-06-29 12:18:33 +05:30
|
|
|
klog.Errorf("xfs: failed to remove tmpdir %s error: %s", tmpdir, err.Error())
|
2020-03-26 20:52:53 +05:30
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-11-25 18:49:51 +05:30
|
|
|
// GenerateUUID generates a new UUID for the given device
|
|
|
|
|
func GenerateUUID(device string) error {
|
2020-03-26 20:52:53 +05:30
|
|
|
// temporary mount the volume with nouuid to replay the logs
|
2020-11-25 18:49:51 +05:30
|
|
|
err := xfsTempMount(device)
|
2020-03-26 20:52:53 +05:30
|
|
|
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 {
|
2020-11-25 18:49:51 +05:30
|
|
|
klog.Errorf("xfs: uuid generate failed for device %s error: %s", device, string(out))
|
2020-03-26 20:52:53 +05:30
|
|
|
return err
|
|
|
|
|
}
|
2020-11-25 18:49:51 +05:30
|
|
|
klog.Infof("xfs: generated UUID for the device %s \n %v", device, string(out))
|
2020-03-26 20:52:53 +05:30
|
|
|
return nil
|
|
|
|
|
}
|