aboutsummaryrefslogtreecommitdiff
path: root/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go')
-rw-r--r--vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go700
1 files changed, 0 insertions, 700 deletions
diff --git a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go b/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
deleted file mode 100644
index 11835432d..000000000
--- a/vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
+++ /dev/null
@@ -1,700 +0,0 @@
-// +build linux
-
-/*
-Copyright 2014 The Kubernetes 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 mount
-
-import (
- "errors"
- "fmt"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "strconv"
- "strings"
- "syscall"
-
- "github.com/golang/glog"
- "golang.org/x/sys/unix"
- "k8s.io/apimachinery/pkg/util/sets"
- utilio "k8s.io/kubernetes/pkg/util/io"
- utilexec "k8s.io/utils/exec"
-)
-
-const (
- // How many times to retry for a consistent read of /proc/mounts.
- maxListTries = 3
- // Number of fields per line in /proc/mounts as per the fstab man page.
- expectedNumFieldsPerLine = 6
- // Location of the mount file to use
- procMountsPath = "/proc/mounts"
- // Location of the mountinfo file
- procMountInfoPath = "/proc/self/mountinfo"
- // 'fsck' found errors and corrected them
- fsckErrorsCorrected = 1
- // 'fsck' found errors but exited without correcting them
- fsckErrorsUncorrected = 4
-)
-
-// Mounter provides the default implementation of mount.Interface
-// for the linux platform. This implementation assumes that the
-// kubelet is running in the host's root mount namespace.
-type Mounter struct {
- mounterPath string
- withSystemd bool
-}
-
-// New returns a mount.Interface for the current system.
-// It provides options to override the default mounter behavior.
-// mounterPath allows using an alternative to `/bin/mount` for mounting.
-func New(mounterPath string) Interface {
- return &Mounter{
- mounterPath: mounterPath,
- withSystemd: detectSystemd(),
- }
-}
-
-// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
-// be an empty string in case it's not required, e.g. for remount, or for auto filesystem
-// type, where kernel handles fstype for you. The mount 'options' is a list of options,
-// currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is
-// required, call Mount with an empty string list or nil.
-func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
- // Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
- // All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
- mounterPath := ""
- bind, bindRemountOpts := isBind(options)
- if bind {
- err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, []string{"bind"})
- if err != nil {
- return err
- }
- return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts)
- }
- // The list of filesystems that require containerized mounter on GCI image cluster
- fsTypesNeedMounter := sets.NewString("nfs", "glusterfs", "ceph", "cifs")
- if fsTypesNeedMounter.Has(fstype) {
- mounterPath = mounter.mounterPath
- }
- return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options)
-}
-
-// doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
-func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error {
- mountArgs := makeMountArgs(source, target, fstype, options)
- if len(mounterPath) > 0 {
- mountArgs = append([]string{mountCmd}, mountArgs...)
- mountCmd = mounterPath
- }
-
- if m.withSystemd {
- // Try to run mount via systemd-run --scope. This will escape the
- // service where kubelet runs and any fuse daemons will be started in a
- // specific scope. kubelet service than can be restarted without killing
- // these fuse daemons.
- //
- // Complete command line (when mounterPath is not used):
- // systemd-run --description=... --scope -- mount -t <type> <what> <where>
- //
- // Expected flow:
- // * systemd-run creates a transient scope (=~ cgroup) and executes its
- // argument (/bin/mount) there.
- // * mount does its job, forks a fuse daemon if necessary and finishes.
- // (systemd-run --scope finishes at this point, returning mount's exit
- // code and stdout/stderr - thats one of --scope benefits).
- // * systemd keeps the fuse daemon running in the scope (i.e. in its own
- // cgroup) until the fuse daemon dies (another --scope benefit).
- // Kubelet service can be restarted and the fuse daemon survives.
- // * When the fuse daemon dies (e.g. during unmount) systemd removes the
- // scope automatically.
- //
- // systemd-mount is not used because it's too new for older distros
- // (CentOS 7, Debian Jessie).
- mountCmd, mountArgs = addSystemdScope("systemd-run", target, mountCmd, mountArgs)
- } else {
- // No systemd-run on the host (or we failed to check it), assume kubelet
- // does not run as a systemd service.
- // No code here, mountCmd and mountArgs are already populated.
- }
-
- glog.V(4).Infof("Mounting cmd (%s) with arguments (%s)", mountCmd, mountArgs)
- command := exec.Command(mountCmd, mountArgs...)
- output, err := command.CombinedOutput()
- if err != nil {
- args := strings.Join(mountArgs, " ")
- glog.Errorf("Mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n", err, mountCmd, args, string(output))
- return fmt.Errorf("mount failed: %v\nMounting command: %s\nMounting arguments: %s\nOutput: %s\n",
- err, mountCmd, args, string(output))
- }
- return err
-}
-
-// GetMountRefs finds all other references to the device referenced
-// by mountPath; returns a list of paths.
-func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
- mps, err := mounter.List()
- if err != nil {
- return nil, err
- }
- // Find the device name.
- deviceName := ""
- // If mountPath is symlink, need get its target path.
- slTarget, err := filepath.EvalSymlinks(mountPath)
- if err != nil {
- slTarget = mountPath
- }
- for i := range mps {
- if mps[i].Path == slTarget {
- deviceName = mps[i].Device
- break
- }
- }
-
- // Find all references to the device.
- var refs []string
- if deviceName == "" {
- glog.Warningf("could not determine device for path: %q", mountPath)
- } else {
- for i := range mps {
- if mps[i].Device == deviceName && mps[i].Path != slTarget {
- refs = append(refs, mps[i].Path)
- }
- }
- }
- return refs, nil
-}
-
-// detectSystemd returns true if OS runs with systemd as init. When not sure
-// (permission errors, ...), it returns false.
-// There may be different ways how to detect systemd, this one makes sure that
-// systemd-runs (needed by Mount()) works.
-func detectSystemd() bool {
- if _, err := exec.LookPath("systemd-run"); err != nil {
- glog.V(2).Infof("Detected OS without systemd")
- return false
- }
- // Try to run systemd-run --scope /bin/true, that should be enough
- // to make sure that systemd is really running and not just installed,
- // which happens when running in a container with a systemd-based image
- // but with different pid 1.
- cmd := exec.Command("systemd-run", "--description=Kubernetes systemd probe", "--scope", "true")
- output, err := cmd.CombinedOutput()
- if err != nil {
- glog.V(2).Infof("Cannot run systemd-run, assuming non-systemd OS")
- glog.V(4).Infof("systemd-run failed with: %v", err)
- glog.V(4).Infof("systemd-run output: %s", string(output))
- return false
- }
- glog.V(2).Infof("Detected OS with systemd")
- return true
-}
-
-// makeMountArgs makes the arguments to the mount(8) command.
-func makeMountArgs(source, target, fstype string, options []string) []string {
- // Build mount command as follows:
- // mount [-t $fstype] [-o $options] [$source] $target
- mountArgs := []string{}
- if len(fstype) > 0 {
- mountArgs = append(mountArgs, "-t", fstype)
- }
- if len(options) > 0 {
- mountArgs = append(mountArgs, "-o", strings.Join(options, ","))
- }
- if len(source) > 0 {
- mountArgs = append(mountArgs, source)
- }
- mountArgs = append(mountArgs, target)
-
- return mountArgs
-}
-
-// addSystemdScope adds "system-run --scope" to given command line
-func addSystemdScope(systemdRunPath, mountName, command string, args []string) (string, []string) {
- descriptionArg := fmt.Sprintf("--description=Kubernetes transient mount for %s", mountName)
- systemdRunArgs := []string{descriptionArg, "--scope", "--", command}
- return systemdRunPath, append(systemdRunArgs, args...)
-}
-
-// Unmount unmounts the target.
-func (mounter *Mounter) Unmount(target string) error {
- glog.V(4).Infof("Unmounting %s", target)
- command := exec.Command("umount", target)
- output, err := command.CombinedOutput()
- if err != nil {
- return fmt.Errorf("Unmount failed: %v\nUnmounting arguments: %s\nOutput: %s\n", err, target, string(output))
- }
- return nil
-}
-
-// List returns a list of all mounted filesystems.
-func (*Mounter) List() ([]MountPoint, error) {
- return listProcMounts(procMountsPath)
-}
-
-func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
- deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
- return ((mp.Path == dir) || (mp.Path == deletedDir))
-}
-
-func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) {
- return IsNotMountPoint(mounter, dir)
-}
-
-// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
-// It is fast but not necessarily ALWAYS correct. If the path is in fact
-// a bind mount from one part of a mount to another it will not be detected.
-// mkdir /tmp/a /tmp/b; mount --bin /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
-// will return true. When in fact /tmp/b is a mount point. If this situation
-// if of interest to you, don't use this function...
-func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
- stat, err := os.Stat(file)
- if err != nil {
- return true, err
- }
- rootStat, err := os.Lstat(filepath.Dir(strings.TrimSuffix(file, "/")))
- if err != nil {
- return true, err
- }
- // If the directory has a different device as parent, then it is a mountpoint.
- if stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev {
- return false, nil
- }
-
- return true, nil
-}
-
-// DeviceOpened checks if block device in use by calling Open with O_EXCL flag.
-// If pathname is not a device, log and return false with nil error.
-// If open returns errno EBUSY, return true with nil error.
-// If open returns nil, return false with nil error.
-// Otherwise, return false with error
-func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
- return exclusiveOpenFailsOnDevice(pathname)
-}
-
-// PathIsDevice uses FileInfo returned from os.Stat to check if path refers
-// to a device.
-func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
- pathType, err := mounter.GetFileType(pathname)
- isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev
- return isDevice, err
-}
-
-func exclusiveOpenFailsOnDevice(pathname string) (bool, error) {
- var isDevice bool
- finfo, err := os.Stat(pathname)
- if os.IsNotExist(err) {
- isDevice = false
- }
- // err in call to os.Stat
- if err != nil {
- return false, fmt.Errorf(
- "PathIsDevice failed for path %q: %v",
- pathname,
- err)
- }
- // path refers to a device
- if finfo.Mode()&os.ModeDevice != 0 {
- isDevice = true
- }
-
- if !isDevice {
- glog.Errorf("Path %q is not referring to a device.", pathname)
- return false, nil
- }
- fd, errno := unix.Open(pathname, unix.O_RDONLY|unix.O_EXCL, 0)
- // If the device is in use, open will return an invalid fd.
- // When this happens, it is expected that Close will fail and throw an error.
- defer unix.Close(fd)
- if errno == nil {
- // device not in use
- return false, nil
- } else if errno == unix.EBUSY {
- // device is in use
- return true, nil
- }
- // error during call to Open
- return false, errno
-}
-
-//GetDeviceNameFromMount: given a mount point, find the device name from its global mount point
-func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
- return getDeviceNameFromMount(mounter, mountPath, pluginDir)
-}
-
-// getDeviceNameFromMount find the device name from /proc/mounts in which
-// the mount path reference should match the given plugin directory. In case no mount path reference
-// matches, returns the volume name taken from its given mountPath
-func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
- refs, err := GetMountRefs(mounter, mountPath)
- if err != nil {
- glog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
- return "", err
- }
- if len(refs) == 0 {
- glog.V(4).Infof("Directory %s is not mounted", mountPath)
- return "", fmt.Errorf("directory %s is not mounted", mountPath)
- }
- basemountPath := path.Join(pluginDir, MountsInGlobalPDPath)
- for _, ref := range refs {
- if strings.HasPrefix(ref, basemountPath) {
- volumeID, err := filepath.Rel(basemountPath, ref)
- if err != nil {
- glog.Errorf("Failed to get volume id from mount %s - %v", mountPath, err)
- return "", err
- }
- return volumeID, nil
- }
- }
-
- return path.Base(mountPath), nil
-}
-
-func listProcMounts(mountFilePath string) ([]MountPoint, error) {
- content, err := utilio.ConsistentRead(mountFilePath, maxListTries)
- if err != nil {
- return nil, err
- }
- return parseProcMounts(content)
-}
-
-func parseProcMounts(content []byte) ([]MountPoint, error) {
- out := []MountPoint{}
- lines := strings.Split(string(content), "\n")
- for _, line := range lines {
- if line == "" {
- // the last split() item is empty string following the last \n
- continue
- }
- fields := strings.Fields(line)
- if len(fields) != expectedNumFieldsPerLine {
- return nil, fmt.Errorf("wrong number of fields (expected %d, got %d): %s", expectedNumFieldsPerLine, len(fields), line)
- }
-
- mp := MountPoint{
- Device: fields[0],
- Path: fields[1],
- Type: fields[2],
- Opts: strings.Split(fields[3], ","),
- }
-
- freq, err := strconv.Atoi(fields[4])
- if err != nil {
- return nil, err
- }
- mp.Freq = freq
-
- pass, err := strconv.Atoi(fields[5])
- if err != nil {
- return nil, err
- }
- mp.Pass = pass
-
- out = append(out, mp)
- }
- return out, nil
-}
-
-func (mounter *Mounter) MakeRShared(path string) error {
- return doMakeRShared(path, procMountInfoPath)
-}
-
-func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
- var pathType FileType
- finfo, err := os.Stat(pathname)
- if os.IsNotExist(err) {
- return pathType, fmt.Errorf("path %q does not exist", pathname)
- }
- // err in call to os.Stat
- if err != nil {
- return pathType, err
- }
-
- mode := finfo.Sys().(*syscall.Stat_t).Mode
- switch mode & syscall.S_IFMT {
- case syscall.S_IFSOCK:
- return FileTypeSocket, nil
- case syscall.S_IFBLK:
- return FileTypeBlockDev, nil
- case syscall.S_IFCHR:
- return FileTypeCharDev, nil
- case syscall.S_IFDIR:
- return FileTypeDirectory, nil
- case syscall.S_IFREG:
- return FileTypeFile, nil
- }
-
- return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
-}
-
-func (mounter *Mounter) MakeDir(pathname string) error {
- err := os.MkdirAll(pathname, os.FileMode(0755))
- if err != nil {
- if !os.IsExist(err) {
- return err
- }
- }
- return nil
-}
-
-func (mounter *Mounter) MakeFile(pathname string) error {
- f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))
- defer f.Close()
- if err != nil {
- if !os.IsExist(err) {
- return err
- }
- }
- return nil
-}
-
-func (mounter *Mounter) ExistsPath(pathname string) bool {
- _, err := os.Stat(pathname)
- if err != nil {
- return false
- }
- return true
-}
-
-// formatAndMount uses unix utils to format and mount the given disk
-func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
- readOnly := false
- for _, option := range options {
- if option == "ro" {
- readOnly = true
- break
- }
- }
-
- options = append(options, "defaults")
-
- if !readOnly {
- // Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
- glog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
- args := []string{"-a", source}
- out, err := mounter.Exec.Run("fsck", args...)
- if err != nil {
- ee, isExitError := err.(utilexec.ExitError)
- switch {
- case err == utilexec.ErrExecutableNotFound:
- glog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
- case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
- glog.Infof("Device %s has errors which were corrected by fsck.", source)
- case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
- return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out))
- case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
- glog.Infof("`fsck` error %s", string(out))
- }
- }
- }
-
- // Try to mount the disk
- glog.V(4).Infof("Attempting to mount disk: %s %s %s", fstype, source, target)
- mountErr := mounter.Interface.Mount(source, target, fstype, options)
- if mountErr != nil {
- // Mount failed. This indicates either that the disk is unformatted or
- // it contains an unexpected filesystem.
- existingFormat, err := mounter.GetDiskFormat(source)
- if err != nil {
- return err
- }
- if existingFormat == "" {
- if readOnly {
- // Don't attempt to format if mounting as readonly, return an error to reflect this.
- return errors.New("failed to mount unformatted volume as read only")
- }
-
- // Disk is unformatted so format it.
- args := []string{source}
- // Use 'ext4' as the default
- if len(fstype) == 0 {
- fstype = "ext4"
- }
-
- if fstype == "ext4" || fstype == "ext3" {
- args = []string{"-F", source}
- }
- glog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
- _, err := mounter.Exec.Run("mkfs."+fstype, args...)
- if err == nil {
- // the disk has been formatted successfully try to mount it again.
- glog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
- return mounter.Interface.Mount(source, target, fstype, options)
- }
- glog.Errorf("format of disk %q failed: type:(%q) target:(%q) options:(%q)error:(%v)", source, fstype, target, options, err)
- return err
- } else {
- // Disk is already formatted and failed to mount
- if len(fstype) == 0 || fstype == existingFormat {
- // This is mount error
- return mountErr
- } else {
- // Block device is formatted with unexpected filesystem, let the user know
- return fmt.Errorf("failed to mount the volume as %q, it already contains %s. Mount error: %v", fstype, existingFormat, mountErr)
- }
- }
- }
- return mountErr
-}
-
-// GetDiskFormat uses 'blkid' to see if the given disk is unformated
-func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
- args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
- glog.V(4).Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
- dataOut, err := mounter.Exec.Run("blkid", args...)
- output := string(dataOut)
- glog.V(4).Infof("Output: %q, err: %v", output, err)
-
- if err != nil {
- if exit, ok := err.(utilexec.ExitError); ok {
- if exit.ExitStatus() == 2 {
- // Disk device is unformatted.
- // For `blkid`, if the specified token (TYPE/PTTYPE, etc) was
- // not found, or no (specified) devices could be identified, an
- // exit code of 2 is returned.
- return "", nil
- }
- }
- glog.Errorf("Could not determine if disk %q is formatted (%v)", disk, err)
- return "", err
- }
-
- var fstype, pttype string
-
- lines := strings.Split(output, "\n")
- for _, l := range lines {
- if len(l) <= 0 {
- // Ignore empty line.
- continue
- }
- cs := strings.Split(l, "=")
- if len(cs) != 2 {
- return "", fmt.Errorf("blkid returns invalid output: %s", output)
- }
- // TYPE is filesystem type, and PTTYPE is partition table type, according
- // to https://www.kernel.org/pub/linux/utils/util-linux/v2.21/libblkid-docs/.
- if cs[0] == "TYPE" {
- fstype = cs[1]
- } else if cs[0] == "PTTYPE" {
- pttype = cs[1]
- }
- }
-
- if len(pttype) > 0 {
- glog.V(4).Infof("Disk %s detected partition table type: %s", pttype)
- // Returns a special non-empty string as filesystem type, then kubelet
- // will not format it.
- return "unknown data, probably partitions", nil
- }
-
- return fstype, nil
-}
-
-// isShared returns true, if given path is on a mount point that has shared
-// mount propagation.
-func isShared(path string, filename string) (bool, error) {
- infos, err := parseMountInfo(filename)
- if err != nil {
- return false, err
- }
-
- // process /proc/xxx/mountinfo in backward order and find the first mount
- // point that is prefix of 'path' - that's the mount where path resides
- var info *mountInfo
- for i := len(infos) - 1; i >= 0; i-- {
- if strings.HasPrefix(path, infos[i].mountPoint) {
- info = &infos[i]
- break
- }
- }
- if info == nil {
- return false, fmt.Errorf("cannot find mount point for %q", path)
- }
-
- // parse optional parameters
- for _, opt := range info.optional {
- if strings.HasPrefix(opt, "shared:") {
- return true, nil
- }
- }
- return false, nil
-}
-
-type mountInfo struct {
- mountPoint string
- // list of "optional parameters", mount propagation is one of them
- optional []string
-}
-
-// parseMountInfo parses /proc/xxx/mountinfo.
-func parseMountInfo(filename string) ([]mountInfo, error) {
- content, err := utilio.ConsistentRead(filename, maxListTries)
- if err != nil {
- return []mountInfo{}, err
- }
- contentStr := string(content)
- infos := []mountInfo{}
-
- for _, line := range strings.Split(contentStr, "\n") {
- if line == "" {
- // the last split() item is empty string following the last \n
- continue
- }
- fields := strings.Fields(line)
- if len(fields) < 7 {
- return nil, fmt.Errorf("wrong number of fields in (expected %d, got %d): %s", 8, len(fields), line)
- }
- info := mountInfo{
- mountPoint: fields[4],
- optional: []string{},
- }
- for i := 6; i < len(fields) && fields[i] != "-"; i++ {
- info.optional = append(info.optional, fields[i])
- }
- infos = append(infos, info)
- }
- return infos, nil
-}
-
-// doMakeRShared is common implementation of MakeRShared on Linux. It checks if
-// path is shared and bind-mounts it as rshared if needed. mountCmd and
-// mountArgs are expected to contain mount-like command, doMakeRShared will add
-// '--bind <path> <path>' and '--make-rshared <path>' to mountArgs.
-func doMakeRShared(path string, mountInfoFilename string) error {
- shared, err := isShared(path, mountInfoFilename)
- if err != nil {
- return err
- }
- if shared {
- glog.V(4).Infof("Directory %s is already on a shared mount", path)
- return nil
- }
-
- glog.V(2).Infof("Bind-mounting %q with shared mount propagation", path)
- // mount --bind /var/lib/kubelet /var/lib/kubelet
- if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_BIND, "" /*data*/); err != nil {
- return fmt.Errorf("failed to bind-mount %s: %v", path, err)
- }
-
- // mount --make-rshared /var/lib/kubelet
- if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_SHARED|syscall.MS_REC, "" /*data*/); err != nil {
- return fmt.Errorf("failed to make %s rshared: %v", path, err)
- }
-
- return nil
-}