github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/pkg/mount/mount.go (about)

     1  package mount
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  )
     7  
     8  // GetMounts retrieves a list of mounts for the current running process.
     9  func GetMounts() ([]*Info, error) {
    10  	return parseMountTable()
    11  }
    12  
    13  // Mounted determines if a specified mountpoint has been mounted.
    14  // On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab.
    15  func Mounted(mountpoint string) (bool, error) {
    16  	entries, err := parseMountTable()
    17  	if err != nil {
    18  		return false, err
    19  	}
    20  
    21  	// Search the table for the mountpoint
    22  	for _, e := range entries {
    23  		if e.Mountpoint == mountpoint {
    24  			return true, nil
    25  		}
    26  	}
    27  	return false, nil
    28  }
    29  
    30  // Mount will mount filesystem according to the specified configuration, on the
    31  // condition that the target path is *not* already mounted. Options must be
    32  // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
    33  // flags.go for supported option flags.
    34  func Mount(device, target, mType, options string) error {
    35  	flag, _ := parseOptions(options)
    36  	if flag&REMOUNT != REMOUNT {
    37  		if mounted, err := Mounted(target); err != nil || mounted {
    38  			return err
    39  		}
    40  	}
    41  	return ForceMount(device, target, mType, options)
    42  }
    43  
    44  // ForceMount will mount a filesystem according to the specified configuration,
    45  // *regardless* if the target path is not already mounted. Options must be
    46  // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
    47  // flags.go for supported option flags.
    48  func ForceMount(device, target, mType, options string) error {
    49  	flag, data := parseOptions(options)
    50  	return mount(device, target, mType, uintptr(flag), data)
    51  }
    52  
    53  // Unmount lazily unmounts a filesystem on supported platforms, otherwise
    54  // does a normal unmount.
    55  func Unmount(target string) error {
    56  	if mounted, err := Mounted(target); err != nil || !mounted {
    57  		return err
    58  	}
    59  	return unmount(target, mntDetach)
    60  }
    61  
    62  // RecursiveUnmount unmounts the target and all mounts underneath, starting with
    63  // the deepsest mount first.
    64  func RecursiveUnmount(target string) error {
    65  	mounts, err := GetMounts()
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	// Make the deepest mount be first
    71  	sort.Sort(sort.Reverse(byMountpoint(mounts)))
    72  
    73  	for i, m := range mounts {
    74  		if !strings.HasPrefix(m.Mountpoint, target) {
    75  			continue
    76  		}
    77  		if err := Unmount(m.Mountpoint); err != nil && i == len(mounts)-1 {
    78  			if mounted, err := Mounted(m.Mountpoint); err != nil || mounted {
    79  				return err
    80  			}
    81  			// Ignore errors for submounts and continue trying to unmount others
    82  			// The final unmount should fail if there ane any submounts remaining
    83  		}
    84  	}
    85  	return nil
    86  }