summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorZach Koopmans <zkoopmans@google.com>2021-06-17 17:51:36 -0700
committergVisor bot <gvisor-bot@google.com>2021-06-17 17:54:11 -0700
commit1f2ce9f46100d6ff958f7c257d3c0a949ede4f4c (patch)
tree18db716601274c9e8bf1e0b9149113d9da3526b2
parentbc27a991851fdffa59f028eecfc22bdd17ccaa55 (diff)
[syserror] Change p9 server to use linuxerr.
Change the p9 server to use *errors.Error defined in pkg linuxerr. Done separate from the client so that we ensure different p9 server/client versions work with each other. PiperOrigin-RevId: 380084491
-rw-r--r--pkg/errors/linuxerr/linuxerr.go3
-rw-r--r--pkg/p9/BUILD3
-rw-r--r--pkg/p9/handlers.go42
-rw-r--r--pkg/p9/server.go19
4 files changed, 61 insertions, 6 deletions
diff --git a/pkg/errors/linuxerr/linuxerr.go b/pkg/errors/linuxerr/linuxerr.go
index 23d9f9f75..bbdcdecd0 100644
--- a/pkg/errors/linuxerr/linuxerr.go
+++ b/pkg/errors/linuxerr/linuxerr.go
@@ -27,6 +27,7 @@ import (
const maxErrno uint32 = errno.EHWPOISON + 1
var (
+ NOERROR = errors.New(errno.NOERRNO, "not an error")
EPERM = errors.New(errno.EPERM, "operation not permitted")
ENOENT = errors.New(errno.ENOENT, "no such file or directory")
ESRCH = errors.New(errno.ESRCH, "no such process")
@@ -176,7 +177,7 @@ var errNotValidError = errors.New(errno.Errno(maxErrno), "not a valid error")
// errnos (especially uint32(sycall.Errno)) and *Error.
var errorSlice = []*errors.Error{
// Errno values from include/uapi/asm-generic/errno-base.h.
- errno.NOERRNO: nil,
+ errno.NOERRNO: NOERROR,
errno.EPERM: EPERM,
errno.ENOENT: ENOENT,
errno.ESRCH: ESRCH,
diff --git a/pkg/p9/BUILD b/pkg/p9/BUILD
index b2291ef97..2b22b2203 100644
--- a/pkg/p9/BUILD
+++ b/pkg/p9/BUILD
@@ -22,6 +22,9 @@ go_library(
"version.go",
],
deps = [
+ "//pkg/abi/linux/errno",
+ "//pkg/errors",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdchannel",
"//pkg/flipcall",
diff --git a/pkg/p9/handlers.go b/pkg/p9/handlers.go
index 758e11b13..161b451cc 100644
--- a/pkg/p9/handlers.go
+++ b/pkg/p9/handlers.go
@@ -23,6 +23,9 @@ import (
"sync/atomic"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
+ "gvisor.dev/gvisor/pkg/errors"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/log"
)
@@ -62,6 +65,45 @@ func newErr(err error) *Rlerror {
return &Rlerror{Error: uint32(ExtractErrno(err))}
}
+// ExtractLinuxerrErrno extracts a *errors.Error from a error, best effort.
+// TODO(b/34162363): Merge this with ExtractErrno.
+func ExtractLinuxerrErrno(err error) *errors.Error {
+ switch err {
+ case os.ErrNotExist:
+ return linuxerr.ENOENT
+ case os.ErrExist:
+ return linuxerr.EEXIST
+ case os.ErrPermission:
+ return linuxerr.EACCES
+ case os.ErrInvalid:
+ return linuxerr.EINVAL
+ }
+
+ // Attempt to unwrap.
+ switch e := err.(type) {
+ case *errors.Error:
+ return e
+ case unix.Errno:
+ return linuxerr.ErrorFromErrno(errno.Errno(e))
+ case *os.PathError:
+ return ExtractLinuxerrErrno(e.Err)
+ case *os.SyscallError:
+ return ExtractLinuxerrErrno(e.Err)
+ case *os.LinkError:
+ return ExtractLinuxerrErrno(e.Err)
+ }
+
+ // Default case.
+ log.Warningf("unknown error: %v", err)
+ return linuxerr.EIO
+}
+
+// newErrFromLinuxerr returns an Rlerror from the linuxerr list.
+// TODO(b/34162363): Merge this with newErr.
+func newErrFromLinuxerr(err error) *Rlerror {
+ return &Rlerror{Error: uint32(ExtractLinuxerrErrno(err).Errno())}
+}
+
// handler is implemented for server-handled messages.
//
// See server.go for call information.
diff --git a/pkg/p9/server.go b/pkg/p9/server.go
index ff1172ed6..241ab44ef 100644
--- a/pkg/p9/server.go
+++ b/pkg/p9/server.go
@@ -19,7 +19,8 @@ import (
"runtime/debug"
"sync/atomic"
- "golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/fdchannel"
"gvisor.dev/gvisor/pkg/flipcall"
@@ -483,7 +484,7 @@ func (cs *connState) lookupChannel(id uint32) *channel {
func (cs *connState) handle(m message) (r message) {
if !cs.reqGate.Enter() {
// connState.stop() has been called; the connection is shutting down.
- r = newErr(unix.ECONNRESET)
+ r = newErrFromLinuxerr(linuxerr.ECONNRESET)
return
}
defer func() {
@@ -498,15 +499,23 @@ func (cs *connState) handle(m message) (r message) {
// Wrap in an EFAULT error; we don't really have a
// better way to describe this kind of error. It will
// usually manifest as a result of the test framework.
- r = newErr(unix.EFAULT)
+ r = newErrFromLinuxerr(linuxerr.EFAULT)
}
}()
if handler, ok := m.(handler); ok {
// Call the message handler.
r = handler.handle(cs)
+ // TODO(b/34162363):This is only here to make sure the server works with
+ // only linuxerr Errors, as the handlers work with both client and server.
+ // It will be removed a followup, when all the unix.Errno errors are
+ // replaced with linuxerr.
+ if rlError, ok := r.(*Rlerror); ok {
+ e := linuxerr.ErrorFromErrno(errno.Errno(rlError.Error))
+ r = newErrFromLinuxerr(e)
+ }
} else {
// Produce an ENOSYS error.
- r = newErr(unix.ENOSYS)
+ r = newErrFromLinuxerr(linuxerr.ENOSYS)
}
return
}
@@ -553,7 +562,7 @@ func (cs *connState) handleRequest() bool {
// If it's not a connection error, but some other protocol error,
// we can send a response immediately.
cs.sendMu.Lock()
- err := send(cs.conn, tag, newErr(err))
+ err := send(cs.conn, tag, newErrFromLinuxerr(err))
cs.sendMu.Unlock()
if err != nil {
log.Debugf("p9.send: %v", err)