pkg/mount: wrap mount/umount errors
The errors returned from Mount and Unmount functions are raw syscall.Errno errors (like EPERM or EINVAL), which provides no context about what has happened and why. Similar to os.PathError type, introduce mount.Error type with some context. The error messages will now look like this: > mount /tmp/mount-tests/source:/tmp/mount-tests/target, flags: 0x1001: operation not permitted or > mount tmpfs:/tmp/mount-test-source-516297835: operation not permitted Before this patch, it was just > operation not permitted Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
parent
2c0f1b3e01
commit
8b67934cbc
|
|
@ -2,11 +2,47 @@ package mount
|
|||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
)
|
||||
|
||||
// mountError holds an error from a mount or unmount operation
|
||||
type mountError struct {
|
||||
op string
|
||||
source, target string
|
||||
flags uintptr
|
||||
data string
|
||||
err error
|
||||
}
|
||||
|
||||
// Error returns a string representation of mountError
|
||||
func (e *mountError) Error() string {
|
||||
out := e.op + " "
|
||||
|
||||
if e.source != "" {
|
||||
out += e.source + ":" + e.target
|
||||
} else {
|
||||
out += e.target
|
||||
}
|
||||
|
||||
if e.flags != uintptr(0) {
|
||||
out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
|
||||
}
|
||||
if e.data != "" {
|
||||
out += ", data: " + e.data
|
||||
}
|
||||
|
||||
out += ": " + e.err.Error()
|
||||
return out
|
||||
}
|
||||
|
||||
// Cause returns the underlying cause of the error
|
||||
func (e *mountError) Cause() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// GetMounts retrieves a list of mounts for the current running process.
|
||||
func GetMounts() ([]*Info, error) {
|
||||
return parseMountTable()
|
||||
|
|
|
|||
|
|
@ -35,20 +35,39 @@ func mount(device, target, mType string, flags uintptr, data string) error {
|
|||
// Initial call applying all non-propagation flags for mount
|
||||
// or remount with changed data
|
||||
if err := unix.Mount(device, target, mType, oflags, data); err != nil {
|
||||
return err
|
||||
return &mountError{
|
||||
op: "mount",
|
||||
source: device,
|
||||
target: target,
|
||||
flags: oflags,
|
||||
data: data,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flags&ptypes != 0 {
|
||||
// Change the propagation type.
|
||||
if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
|
||||
return err
|
||||
return &mountError{
|
||||
op: "remount",
|
||||
target: target,
|
||||
flags: flags & pflags,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if oflags&broflags == broflags {
|
||||
// Remount the bind to apply read only.
|
||||
return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "")
|
||||
if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil {
|
||||
return &mountError{
|
||||
op: "remount-ro",
|
||||
target: target,
|
||||
flags: oflags | unix.MS_REMOUNT,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -6,12 +6,17 @@ import "golang.org/x/sys/unix"
|
|||
|
||||
func unmount(target string, flags int) error {
|
||||
err := unix.Unmount(target, flags)
|
||||
if err == unix.EINVAL {
|
||||
if err == nil || err == unix.EINVAL {
|
||||
// Ignore "not mounted" error here. Note the same error
|
||||
// can be returned if flags are invalid, so this code
|
||||
// assumes that the flags value is always correct.
|
||||
err = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
return &mountError{
|
||||
op: "umount",
|
||||
target: target,
|
||||
flags: uintptr(flags),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue