diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index 1a17cffe6..b336e51f4 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -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() diff --git a/pkg/mount/mounter_linux.go b/pkg/mount/mounter_linux.go index efdfc7dc0..594cd0881 100644 --- a/pkg/mount/mounter_linux.go +++ b/pkg/mount/mounter_linux.go @@ -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 diff --git a/pkg/mount/unmount_unix.go b/pkg/mount/unmount_unix.go index 6cc3c5747..1d1afeee2 100644 --- a/pkg/mount/unmount_unix.go +++ b/pkg/mount/unmount_unix.go @@ -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, + } }