mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[syserror] Remove pkg syserror.
Removes package syserror and moves still relevant code to either linuxerr or to syserr (to be later removed). Internal errors are converted from random types to *errors.Error types used in linuxerr. Internal errors are in linuxerr/internal.go. PiperOrigin-RevId: 390724202
This commit is contained in:
committed by
gVisor bot
parent
868ed0e807
commit
ce58d71fd5
@@ -163,3 +163,26 @@ const (
|
||||
EDEADLOCK = EDEADLK
|
||||
ENONET = ENOENT
|
||||
)
|
||||
|
||||
// errnos for internal errors.
|
||||
const (
|
||||
// ERESTARTSYS is returned by an interrupted syscall to indicate that it
|
||||
// should be converted to EINTR if interrupted by a signal delivered to a
|
||||
// user handler without SA_RESTART set, and restarted otherwise.
|
||||
ERESTARTSYS = 512
|
||||
|
||||
// ERESTARTNOINTR is returned by an interrupted syscall to indicate that it
|
||||
// should always be restarted.
|
||||
ERESTARTNOINTR = 513
|
||||
|
||||
// ERESTARTNOHAND is returned by an interrupted syscall to indicate that it
|
||||
// should be converted to EINTR if interrupted by a signal delivered to a
|
||||
// user handler, and restarted otherwise.
|
||||
ERESTARTNOHAND = 514
|
||||
|
||||
// ERESTART_RESTARTBLOCK is returned by an interrupted syscall to indicate
|
||||
// that it should be restarted using a custom function. The interrupted
|
||||
// syscall must register a custom restart function by calling
|
||||
// Task.SetRestartSyscallFn.
|
||||
ERESTART_RESTARTBLOCK = 516
|
||||
)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ go_library(
|
||||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
"//pkg/context",
|
||||
"//pkg/syserror",
|
||||
"//pkg/errors/linuxerr",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
)
|
||||
|
||||
// Sleeper must be implemented by users of the abortable mutex to allow for
|
||||
@@ -33,7 +33,7 @@ type NoopSleeper = context.Context
|
||||
|
||||
// Block blocks until either receiving from ch succeeds (in which case it
|
||||
// returns nil) or sleeper is interrupted (in which case it returns
|
||||
// syserror.ErrInterrupted).
|
||||
// linuxerr.ErrInterrupted).
|
||||
func Block(sleeper Sleeper, ch <-chan struct{}) error {
|
||||
cancel := sleeper.SleepStart()
|
||||
select {
|
||||
@@ -42,7 +42,7 @@ func Block(sleeper Sleeper, ch <-chan struct{}) error {
|
||||
return nil
|
||||
case <-cancel:
|
||||
sleeper.SleepFinish(false)
|
||||
return syserror.ErrInterrupted
|
||||
return linuxerr.ErrInterrupted
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package(licenses = ["notice"])
|
||||
go_library(
|
||||
name = "linuxerr",
|
||||
srcs = [
|
||||
"internal.go",
|
||||
"linuxerr.go",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
@@ -22,7 +23,6 @@ go_test(
|
||||
":linuxerr",
|
||||
"//pkg/abi/linux/errno",
|
||||
"//pkg/errors",
|
||||
"//pkg/syserror",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2021 The gVisor 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 linuxerr
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux/errno"
|
||||
"gvisor.dev/gvisor/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrWouldBlock is an internal error used to indicate that an operation
|
||||
// cannot be satisfied immediately, and should be retried at a later
|
||||
// time, possibly when the caller has received a notification that the
|
||||
// operation may be able to complete. It is used by implementations of
|
||||
// the kio.File interface.
|
||||
ErrWouldBlock = errors.New(errno.EWOULDBLOCK, "request would block")
|
||||
|
||||
// ErrInterrupted is returned if a request is interrupted before it can
|
||||
// complete.
|
||||
ErrInterrupted = errors.New(errno.EINTR, "request was interrupted")
|
||||
|
||||
// ErrExceedsFileSizeLimit is returned if a request would exceed the
|
||||
// file's size limit.
|
||||
ErrExceedsFileSizeLimit = errors.New(errno.E2BIG, "exceeds file size limit")
|
||||
)
|
||||
|
||||
var errorMap = map[error]*errors.Error{
|
||||
ErrWouldBlock: EWOULDBLOCK,
|
||||
ErrInterrupted: EINTR,
|
||||
ErrExceedsFileSizeLimit: EFBIG,
|
||||
}
|
||||
|
||||
// errorUnwrappers is an array of unwrap functions to extract typed errors.
|
||||
var errorUnwrappers = []func(error) (*errors.Error, bool){}
|
||||
|
||||
// AddErrorUnwrapper registers an unwrap method that can extract a concrete error
|
||||
// from a typed, but not initialized, error.
|
||||
func AddErrorUnwrapper(unwrap func(e error) (*errors.Error, bool)) {
|
||||
errorUnwrappers = append(errorUnwrappers, unwrap)
|
||||
}
|
||||
|
||||
// TranslateError translates errors to errnos, it will return false if
|
||||
// the error was not registered.
|
||||
func TranslateError(from error) (*errors.Error, bool) {
|
||||
if err, ok := errorMap[from]; ok {
|
||||
return err, true
|
||||
}
|
||||
// Try to unwrap the error if we couldn't match an error
|
||||
// exactly. This might mean that a package has its own
|
||||
// error type.
|
||||
for _, unwrap := range errorUnwrappers {
|
||||
if err, ok := unwrap(from); ok {
|
||||
return err, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// These errors are significant because ptrace syscall exit tracing can
|
||||
// observe them.
|
||||
//
|
||||
// For all of the following errors, if the syscall is not interrupted by a
|
||||
// signal delivered to a user handler, the syscall is restarted.
|
||||
var (
|
||||
// ERESTARTSYS is returned by an interrupted syscall to indicate that it
|
||||
// should be converted to EINTR if interrupted by a signal delivered to a
|
||||
// user handler without SA_RESTART set, and restarted otherwise.
|
||||
ERESTARTSYS = errors.New(errno.ERESTARTSYS, "to be restarted if SA_RESTART is set")
|
||||
|
||||
// ERESTARTNOINTR is returned by an interrupted syscall to indicate that it
|
||||
// should always be restarted.
|
||||
ERESTARTNOINTR = errors.New(errno.ERESTARTNOINTR, "to be restarted")
|
||||
|
||||
// ERESTARTNOHAND is returned by an interrupted syscall to indicate that it
|
||||
// should be converted to EINTR if interrupted by a signal delivered to a
|
||||
// user handler, and restarted otherwise.
|
||||
ERESTARTNOHAND = errors.New(errno.ERESTARTNOHAND, "to be restarted if no handler")
|
||||
|
||||
// ERESTART_RESTARTBLOCK is returned by an interrupted syscall to indicate
|
||||
// that it should be restarted using a custom function. The interrupted
|
||||
// syscall must register a custom restart function by calling
|
||||
// Task.SetRestartSyscallFn.
|
||||
ERESTART_RESTARTBLOCK = errors.New(errno.ERESTART_RESTARTBLOCK, "interrupted by signal")
|
||||
)
|
||||
|
||||
var restartMap = map[int]*errors.Error{
|
||||
-int(errno.ERESTARTSYS): ERESTARTSYS,
|
||||
-int(errno.ERESTARTNOINTR): ERESTARTNOINTR,
|
||||
-int(errno.ERESTARTNOHAND): ERESTARTNOHAND,
|
||||
-int(errno.ERESTART_RESTARTBLOCK): ERESTART_RESTARTBLOCK,
|
||||
}
|
||||
|
||||
// IsRestartError checks if a given error is a restart error.
|
||||
func IsRestartError(err error) bool {
|
||||
switch err {
|
||||
case ERESTARTSYS, ERESTARTNOINTR, ERESTARTNOHAND, ERESTART_RESTARTBLOCK:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// SyscallRestartErrorFromReturn returns the SyscallRestartErrno represented by
|
||||
// rv, the value in a syscall return register.
|
||||
func SyscallRestartErrorFromReturn(rv uintptr) (*errors.Error, bool) {
|
||||
err, ok := restartMap[int(rv)]
|
||||
return err, ok
|
||||
}
|
||||
@@ -12,10 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package syserror_test
|
||||
package linuxerr_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"syscall"
|
||||
@@ -25,7 +26,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux/errno"
|
||||
gErrors "gvisor.dev/gvisor/pkg/errors"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
var globalError error
|
||||
@@ -42,12 +42,6 @@ func BenchmarkAssignLinuxerr(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAssignSyserror(b *testing.B) {
|
||||
for i := b.N; i > 0; i-- {
|
||||
globalError = linuxerr.ENOMSG
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareUnix(b *testing.B) {
|
||||
globalError = unix.EAGAIN
|
||||
j := 0
|
||||
@@ -68,16 +62,6 @@ func BenchmarkCompareLinuxerr(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSyserror(b *testing.B) {
|
||||
globalError = linuxerr.EAGAIN
|
||||
j := 0
|
||||
for i := b.N; i > 0; i-- {
|
||||
if globalError == linuxerr.EACCES {
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSwitchUnix(b *testing.B) {
|
||||
globalError = unix.EPERM
|
||||
j := 0
|
||||
@@ -108,21 +92,6 @@ func BenchmarkSwitchLinuxerr(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSwitchSyserror(b *testing.B) {
|
||||
globalError = linuxerr.EPERM
|
||||
j := 0
|
||||
for i := b.N; i > 0; i-- {
|
||||
switch globalError {
|
||||
case linuxerr.EACCES:
|
||||
j++
|
||||
case linuxerr.EINTR:
|
||||
j += 2
|
||||
case linuxerr.EAGAIN:
|
||||
j += 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReturnUnix(b *testing.B) {
|
||||
var localError error
|
||||
f := func() error {
|
||||
@@ -170,47 +139,40 @@ func BenchmarkConvertUnixLinuxerrZero(b *testing.B) {
|
||||
}
|
||||
|
||||
type translationTestTable struct {
|
||||
fn string
|
||||
errIn error
|
||||
syscallErrorIn unix.Errno
|
||||
expectedBool bool
|
||||
expectedTranslation unix.Errno
|
||||
expectedTranslation *gErrors.Error
|
||||
}
|
||||
|
||||
func TestErrorTranslation(t *testing.T) {
|
||||
myError := errors.New("My test error")
|
||||
myError2 := errors.New("Another test error")
|
||||
testTable := []translationTestTable{
|
||||
{"TranslateError", myError, 0, false, 0},
|
||||
{"TranslateError", myError2, 0, false, 0},
|
||||
{"AddErrorTranslation", myError, unix.EAGAIN, true, 0},
|
||||
{"AddErrorTranslation", myError, unix.EAGAIN, false, 0},
|
||||
{"AddErrorTranslation", myError, unix.EPERM, false, 0},
|
||||
{"TranslateError", myError, 0, true, unix.EAGAIN},
|
||||
{"TranslateError", myError2, 0, false, 0},
|
||||
{"AddErrorTranslation", myError2, unix.EPERM, true, 0},
|
||||
{"AddErrorTranslation", myError2, unix.EPERM, false, 0},
|
||||
{"AddErrorTranslation", myError2, unix.EAGAIN, false, 0},
|
||||
{"TranslateError", myError, 0, true, unix.EAGAIN},
|
||||
{"TranslateError", myError2, 0, true, unix.EPERM},
|
||||
{
|
||||
errIn: linuxerr.ENOENT,
|
||||
},
|
||||
{
|
||||
errIn: unix.ENOENT,
|
||||
},
|
||||
{
|
||||
errIn: linuxerr.ErrInterrupted,
|
||||
expectedBool: true,
|
||||
expectedTranslation: linuxerr.EINTR,
|
||||
},
|
||||
{
|
||||
errIn: linuxerr.ERESTART_RESTARTBLOCK,
|
||||
},
|
||||
{
|
||||
errIn: errors.New("some new error"),
|
||||
},
|
||||
}
|
||||
for _, tt := range testTable {
|
||||
switch tt.fn {
|
||||
case "TranslateError":
|
||||
err, ok := syserror.TranslateError(tt.errIn)
|
||||
if ok != tt.expectedBool {
|
||||
t.Fatalf("%v(%v) => %v expected %v", tt.fn, tt.errIn, ok, tt.expectedBool)
|
||||
t.Run(fmt.Sprintf("err: %v %T", tt.errIn, tt.errIn), func(t *testing.T) {
|
||||
err, ok := linuxerr.TranslateError(tt.errIn)
|
||||
if (!tt.expectedBool && err != nil) || (tt.expectedBool != ok) {
|
||||
t.Fatalf("%v => %v %v expected %v err: nil", tt.errIn, err, ok, tt.expectedBool)
|
||||
} else if err != tt.expectedTranslation {
|
||||
t.Fatalf("%v(%v) (error) => %v expected %v", tt.fn, tt.errIn, err, tt.expectedTranslation)
|
||||
t.Fatalf("%v => %v expected %v", tt.errIn, err, tt.expectedTranslation)
|
||||
}
|
||||
case "AddErrorTranslation":
|
||||
ok := syserror.AddErrorTranslation(tt.errIn, tt.syscallErrorIn)
|
||||
if ok != tt.expectedBool {
|
||||
t.Fatalf("%v(%v) => %v expected %v", tt.fn, tt.errIn, ok, tt.expectedBool)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("Unknown function %v", tt.fn)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -19,7 +19,8 @@ go_library(
|
||||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/syserror",
|
||||
"//pkg/errors",
|
||||
"//pkg/errors/linuxerr",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -21,7 +21,8 @@ import (
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/errors"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
)
|
||||
|
||||
// SegvError is returned when a safecopy function receives SIGSEGV.
|
||||
@@ -137,12 +138,12 @@ func init() {
|
||||
if err := ReplaceSignalHandler(unix.SIGBUS, addrOfSignalHandler(), &savedSigBusHandler); err != nil {
|
||||
panic(fmt.Sprintf("Unable to set handler for SIGBUS: %v", err))
|
||||
}
|
||||
syserror.AddErrorUnwrapper(func(e error) (unix.Errno, bool) {
|
||||
linuxerr.AddErrorUnwrapper(func(e error) (*errors.Error, bool) {
|
||||
switch e.(type) {
|
||||
case SegvError, BusError, AlignmentError:
|
||||
return unix.EFAULT, true
|
||||
return linuxerr.EFAULT, true
|
||||
default:
|
||||
return 0, false
|
||||
return nil, false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ go_library(
|
||||
"//pkg/sentry/usage",
|
||||
"//pkg/state",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
|
||||
@@ -22,7 +22,6 @@ go_library(
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/fs/fsutil",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
@@ -46,7 +45,6 @@ go_test(
|
||||
"//pkg/hostarch",
|
||||
"//pkg/sentry/contexttest",
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"@com_github_google_uuid//:go_default_library",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
@@ -142,7 +141,7 @@ func (p *pipeOperations) Read(ctx context.Context, file *fs.File, dst usermem.IO
|
||||
n, err := dst.CopyOutFrom(ctx, safemem.FromIOReader{secio.FullReader{p.file}})
|
||||
total := int64(bufN) + n
|
||||
if err != nil && isBlockError(err) {
|
||||
return total, syserror.ErrWouldBlock
|
||||
return total, linuxerr.ErrWouldBlock
|
||||
}
|
||||
return total, err
|
||||
}
|
||||
@@ -151,13 +150,13 @@ func (p *pipeOperations) Read(ctx context.Context, file *fs.File, dst usermem.IO
|
||||
func (p *pipeOperations) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
|
||||
n, err := src.CopyInTo(ctx, safemem.FromIOWriter{p.file})
|
||||
if err != nil && isBlockError(err) {
|
||||
return n, syserror.ErrWouldBlock
|
||||
return n, linuxerr.ErrWouldBlock
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// isBlockError unwraps os errors and checks if they are caused by EAGAIN or
|
||||
// EWOULDBLOCK. This is so they can be transformed into syserror.ErrWouldBlock.
|
||||
// EWOULDBLOCK. This is so they can be transformed into linuxerr.ErrWouldBlock.
|
||||
func isBlockError(err error) bool {
|
||||
if linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err) {
|
||||
return true
|
||||
|
||||
@@ -21,9 +21,9 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
// NonBlockingOpener is a generic host file opener used to retry opening host
|
||||
@@ -40,7 +40,7 @@ func Open(ctx context.Context, opener NonBlockingOpener, flags fs.FileFlags) (fs
|
||||
p := &pipeOpenState{}
|
||||
canceled := false
|
||||
for {
|
||||
if file, err := p.TryOpen(ctx, opener, flags); err != syserror.ErrWouldBlock {
|
||||
if file, err := p.TryOpen(ctx, opener, flags); err != linuxerr.ErrWouldBlock {
|
||||
return file, err
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func Open(ctx context.Context, opener NonBlockingOpener, flags fs.FileFlags) (fs
|
||||
if p.hostFile != nil {
|
||||
p.hostFile.Close()
|
||||
}
|
||||
return nil, syserror.ErrInterrupted
|
||||
return nil, linuxerr.ErrInterrupted
|
||||
}
|
||||
|
||||
cancel := ctx.SleepStart()
|
||||
@@ -106,13 +106,13 @@ func (p *pipeOpenState) TryOpen(ctx context.Context, opener NonBlockingOpener, f
|
||||
}
|
||||
return newPipeOperations(ctx, opener, flags, f, nil)
|
||||
|
||||
// Handle opening O_WRONLY blocking: convert ENXIO to syserror.ErrWouldBlock.
|
||||
// Handle opening O_WRONLY blocking: convert ENXIO to linuxerr.ErrWouldBlock.
|
||||
// See TryOpenWriteOnly for more details.
|
||||
case flags.Write:
|
||||
return p.TryOpenWriteOnly(ctx, opener)
|
||||
|
||||
default:
|
||||
// Handle opening O_RDONLY blocking: convert EOF from read to syserror.ErrWouldBlock.
|
||||
// Handle opening O_RDONLY blocking: convert EOF from read to linuxerr.ErrWouldBlock.
|
||||
// See TryOpenReadOnly for more details.
|
||||
return p.TryOpenReadOnly(ctx, opener)
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (p *pipeOpenState) TryOpen(ctx context.Context, opener NonBlockingOpener, f
|
||||
|
||||
// TryOpenReadOnly tries to open a host pipe read only but only returns a fs.File when
|
||||
// there is a coordinating writer. Call TryOpenReadOnly repeatedly on the same pipeOpenState
|
||||
// until syserror.ErrWouldBlock is no longer returned.
|
||||
// until linuxerr.ErrWouldBlock is no longer returned.
|
||||
//
|
||||
// How it works:
|
||||
//
|
||||
@@ -150,7 +150,7 @@ func (p *pipeOpenState) TryOpenReadOnly(ctx context.Context, opener NonBlockingO
|
||||
if n == 0 {
|
||||
// EOF means that we're not ready yet.
|
||||
if rerr == nil || rerr == io.EOF {
|
||||
return nil, syserror.ErrWouldBlock
|
||||
return nil, linuxerr.ErrWouldBlock
|
||||
}
|
||||
// Any error that is not EWOULDBLOCK also means we're not
|
||||
// ready yet, and probably never will be ready. In this
|
||||
@@ -175,16 +175,16 @@ func (p *pipeOpenState) TryOpenReadOnly(ctx context.Context, opener NonBlockingO
|
||||
|
||||
// TryOpenWriteOnly tries to open a host pipe write only but only returns a fs.File when
|
||||
// there is a coordinating reader. Call TryOpenWriteOnly repeatedly on the same pipeOpenState
|
||||
// until syserror.ErrWouldBlock is no longer returned.
|
||||
// until linuxerr.ErrWouldBlock is no longer returned.
|
||||
//
|
||||
// How it works:
|
||||
//
|
||||
// Opening a pipe write only will return ENXIO until readers are available. Converts the ENXIO
|
||||
// to an syserror.ErrWouldBlock, to tell callers to retry.
|
||||
// to an linuxerr.ErrWouldBlock, to tell callers to retry.
|
||||
func (*pipeOpenState) TryOpenWriteOnly(ctx context.Context, opener NonBlockingOpener) (*pipeOperations, error) {
|
||||
hostFile, err := opener.NonBlockingOpen(ctx, fs.PermMask{Write: true})
|
||||
if unwrapError(err) == unix.ENXIO {
|
||||
return nil, syserror.ErrWouldBlock
|
||||
return nil, linuxerr.ErrWouldBlock
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/contexttest"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
@@ -146,18 +145,18 @@ func TestTryOpen(t *testing.T) {
|
||||
err: unix.ENOENT,
|
||||
},
|
||||
{
|
||||
desc: "Blocking Write only returns with syserror.ErrWouldBlock",
|
||||
desc: "Blocking Write only returns with linuxerr.ErrWouldBlock",
|
||||
makePipe: true,
|
||||
flags: fs.FileFlags{Write: true},
|
||||
expectFile: false,
|
||||
err: syserror.ErrWouldBlock,
|
||||
err: linuxerr.ErrWouldBlock,
|
||||
},
|
||||
{
|
||||
desc: "Blocking Read only returns with syserror.ErrWouldBlock",
|
||||
desc: "Blocking Read only returns with linuxerr.ErrWouldBlock",
|
||||
makePipe: true,
|
||||
flags: fs.FileFlags{Read: true},
|
||||
expectFile: false,
|
||||
err: syserror.ErrWouldBlock,
|
||||
err: linuxerr.ErrWouldBlock,
|
||||
},
|
||||
} {
|
||||
name := pipename()
|
||||
@@ -316,7 +315,7 @@ func TestCopiedReadAheadBuffer(t *testing.T) {
|
||||
// another writer comes along. This means we can open the same pipe write only
|
||||
// with no problems + write to it, given that opener.Open already tried to open
|
||||
// the pipe RDONLY and succeeded, which we know happened if TryOpen returns
|
||||
// syserror.ErrwouldBlock.
|
||||
// linuxerr.ErrwouldBlock.
|
||||
//
|
||||
// This simulates the open(RDONLY) <-> open(WRONLY)+write race we care about, but
|
||||
// does not cause our test to be racy (which would be terrible).
|
||||
@@ -328,8 +327,8 @@ func TestCopiedReadAheadBuffer(t *testing.T) {
|
||||
pipeOps.Release(ctx)
|
||||
t.Fatalf("open(%s, %o) got file, want nil", name, unix.O_RDONLY)
|
||||
}
|
||||
if err != syserror.ErrWouldBlock {
|
||||
t.Fatalf("open(%s, %o) got error %v, want %v", name, unix.O_RDONLY, err, syserror.ErrWouldBlock)
|
||||
if err != linuxerr.ErrWouldBlock {
|
||||
t.Fatalf("open(%s, %o) got error %v, want %v", name, unix.O_RDONLY, err, linuxerr.ErrWouldBlock)
|
||||
}
|
||||
|
||||
// Then open the same pipe write only and write some bytes to it. The next
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/contexttest"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
@@ -238,7 +237,7 @@ func TestPipeRequest(t *testing.T) {
|
||||
context: &Readv{Dst: usermem.BytesIOSequence(make([]byte, 10))},
|
||||
flags: fs.FileFlags{Read: true},
|
||||
keepOpenPartner: true,
|
||||
err: syserror.ErrWouldBlock,
|
||||
err: linuxerr.ErrWouldBlock,
|
||||
},
|
||||
{
|
||||
desc: "Writev on pipe from empty buffer returns nil",
|
||||
@@ -410,8 +409,8 @@ func TestPipeReadsAccumulate(t *testing.T) {
|
||||
n, err := p.Read(ctx, file, iov, 0)
|
||||
total := n
|
||||
iov = iov.DropFirst64(n)
|
||||
if err != syserror.ErrWouldBlock {
|
||||
t.Fatalf("Readv got error %v, want %v", err, syserror.ErrWouldBlock)
|
||||
if err != linuxerr.ErrWouldBlock {
|
||||
t.Fatalf("Readv got error %v, want %v", err, linuxerr.ErrWouldBlock)
|
||||
}
|
||||
|
||||
// Write a few more bytes to allow us to read more/accumulate.
|
||||
@@ -479,8 +478,8 @@ func TestPipeWritesAccumulate(t *testing.T) {
|
||||
}
|
||||
iov := usermem.BytesIOSequence(writeBuffer)
|
||||
n, err := p.Write(ctx, file, iov, 0)
|
||||
if err != syserror.ErrWouldBlock {
|
||||
t.Fatalf("Writev got error %v, want %v", err, syserror.ErrWouldBlock)
|
||||
if err != linuxerr.ErrWouldBlock {
|
||||
t.Fatalf("Writev got error %v, want %v", err, linuxerr.ErrWouldBlock)
|
||||
}
|
||||
if n != int64(pipeSize) {
|
||||
t.Fatalf("Writev partial write, got: %v, want %v", n, pipeSize)
|
||||
|
||||
+23
-24
@@ -28,7 +28,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/memmap"
|
||||
"gvisor.dev/gvisor/pkg/sentry/uniqueid"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
@@ -196,10 +195,10 @@ func (f *File) EventUnregister(e *waiter.Entry) {
|
||||
// offset to the value returned by f.FileOperations.Seek if the operation
|
||||
// is successful.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if seeking was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if seeking was interrupted.
|
||||
func (f *File) Seek(ctx context.Context, whence SeekWhence, offset int64) (int64, error) {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -218,10 +217,10 @@ func (f *File) Seek(ctx context.Context, whence SeekWhence, offset int64) (int64
|
||||
// Readdir unconditionally updates the access time on the File's Inode,
|
||||
// see fs/readdir.c:iterate_dir.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if reading was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if reading was interrupted.
|
||||
func (f *File) Readdir(ctx context.Context, serializer DentrySerializer) error {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return syserror.ErrInterrupted
|
||||
return linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -233,13 +232,13 @@ func (f *File) Readdir(ctx context.Context, serializer DentrySerializer) error {
|
||||
// Readv calls f.FileOperations.Read with f as the File, advancing the file
|
||||
// offset if f.FileOperations.Read returns bytes read > 0.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if reading was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if reading was interrupted.
|
||||
func (f *File) Readv(ctx context.Context, dst usermem.IOSequence) (int64, error) {
|
||||
start := fsmetric.StartReadWait()
|
||||
defer fsmetric.FinishReadWait(fsmetric.ReadWait, start)
|
||||
|
||||
if !f.mu.Lock(ctx) {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
|
||||
fsmetric.Reads.Increment()
|
||||
@@ -261,7 +260,7 @@ func (f *File) Preadv(ctx context.Context, dst usermem.IOSequence, offset int64)
|
||||
defer fsmetric.FinishReadWait(fsmetric.ReadWait, start)
|
||||
|
||||
if !f.mu.Lock(ctx) {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
|
||||
fsmetric.Reads.Increment()
|
||||
@@ -277,10 +276,10 @@ func (f *File) Preadv(ctx context.Context, dst usermem.IOSequence, offset int64)
|
||||
// unavoidably racy for network file systems. Writev also truncates src
|
||||
// to avoid overrunning the current file size limit if necessary.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if writing was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if writing was interrupted.
|
||||
func (f *File) Writev(ctx context.Context, src usermem.IOSequence) (int64, error) {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
unlockAppendMu := f.Dirent.Inode.lockAppendMu(f.Flags().Append)
|
||||
// Handle append mode.
|
||||
@@ -298,7 +297,7 @@ func (f *File) Writev(ctx context.Context, src usermem.IOSequence) (int64, error
|
||||
case ok && limit == 0:
|
||||
unlockAppendMu()
|
||||
f.mu.Unlock()
|
||||
return 0, syserror.ErrExceedsFileSizeLimit
|
||||
return 0, linuxerr.ErrExceedsFileSizeLimit
|
||||
case ok:
|
||||
src = src.TakeFirst64(limit)
|
||||
}
|
||||
@@ -336,7 +335,7 @@ func (f *File) Pwritev(ctx context.Context, src usermem.IOSequence, offset int64
|
||||
limit, ok := f.checkLimit(ctx, offset)
|
||||
switch {
|
||||
case ok && limit == 0:
|
||||
return 0, syserror.ErrExceedsFileSizeLimit
|
||||
return 0, linuxerr.ErrExceedsFileSizeLimit
|
||||
case ok:
|
||||
src = src.TakeFirst64(limit)
|
||||
}
|
||||
@@ -382,10 +381,10 @@ func (f *File) checkLimit(ctx context.Context, offset int64) (int64, bool) {
|
||||
|
||||
// Fsync calls f.FileOperations.Fsync with f as the File.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if syncing was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if syncing was interrupted.
|
||||
func (f *File) Fsync(ctx context.Context, start int64, end int64, syncType SyncType) error {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return syserror.ErrInterrupted
|
||||
return linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -394,10 +393,10 @@ func (f *File) Fsync(ctx context.Context, start int64, end int64, syncType SyncT
|
||||
|
||||
// Flush calls f.FileOperations.Flush with f as the File.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if syncing was interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if syncing was interrupted.
|
||||
func (f *File) Flush(ctx context.Context) error {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return syserror.ErrInterrupted
|
||||
return linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -406,10 +405,10 @@ func (f *File) Flush(ctx context.Context) error {
|
||||
|
||||
// ConfigureMMap calls f.FileOperations.ConfigureMMap with f as the File.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if interrupted.
|
||||
func (f *File) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return syserror.ErrInterrupted
|
||||
return linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -418,10 +417,10 @@ func (f *File) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
|
||||
|
||||
// UnstableAttr calls f.FileOperations.UnstableAttr with f as the File.
|
||||
//
|
||||
// Returns syserror.ErrInterrupted if interrupted.
|
||||
// Returns linuxerr.ErrInterrupted if interrupted.
|
||||
func (f *File) UnstableAttr(ctx context.Context) (UnstableAttr, error) {
|
||||
if !f.mu.Lock(ctx) {
|
||||
return UnstableAttr{}, syserror.ErrInterrupted
|
||||
return UnstableAttr{}, linuxerr.ErrInterrupted
|
||||
}
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@@ -496,7 +495,7 @@ type lockedReader struct {
|
||||
// Read implements io.Reader.Read.
|
||||
func (r *lockedReader) Read(buf []byte) (int, error) {
|
||||
if r.Ctx.Interrupted() {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
n, err := r.File.FileOperations.Read(r.Ctx, r.File, usermem.BytesIOSequence(buf), r.Offset)
|
||||
r.Offset += n
|
||||
@@ -506,7 +505,7 @@ func (r *lockedReader) Read(buf []byte) (int, error) {
|
||||
// ReadAt implements io.Reader.ReadAt.
|
||||
func (r *lockedReader) ReadAt(buf []byte, offset int64) (int, error) {
|
||||
if r.Ctx.Interrupted() {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
n, err := r.File.FileOperations.Read(r.Ctx, r.File, usermem.BytesIOSequence(buf), offset)
|
||||
return int(n), err
|
||||
@@ -531,7 +530,7 @@ type lockedWriter struct {
|
||||
// Write implements io.Writer.Write.
|
||||
func (w *lockedWriter) Write(buf []byte) (int, error) {
|
||||
if w.Ctx.Interrupted() {
|
||||
return 0, syserror.ErrInterrupted
|
||||
return 0, linuxerr.ErrInterrupted
|
||||
}
|
||||
n, err := w.WriteAt(buf, w.Offset)
|
||||
w.Offset += int64(n)
|
||||
@@ -550,7 +549,7 @@ func (w *lockedWriter) WriteAt(buf []byte, offset int64) (int, error) {
|
||||
// contract. Enforce that here.
|
||||
for written < len(buf) {
|
||||
if w.Ctx.Interrupted() {
|
||||
return written, syserror.ErrInterrupted
|
||||
return written, linuxerr.ErrInterrupted
|
||||
}
|
||||
var n int64
|
||||
n, err = w.File.FileOperations.Write(w.Ctx, w.File, usermem.BytesIOSequence(buf[written:]), offset+int64(written))
|
||||
|
||||
@@ -120,7 +120,7 @@ type FileOperations interface {
|
||||
// Files with !FileFlags.Pwrite.
|
||||
//
|
||||
// If only part of src could be written, Write must return an error
|
||||
// indicating why (e.g. syserror.ErrWouldBlock).
|
||||
// indicating why (e.g. linuxerr.ErrWouldBlock).
|
||||
//
|
||||
// Write does not check permissions nor flags.
|
||||
//
|
||||
|
||||
@@ -90,7 +90,6 @@ go_library(
|
||||
"//pkg/sentry/usage",
|
||||
"//pkg/state",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
|
||||
@@ -26,6 +26,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fd",
|
||||
"//pkg/hostarch",
|
||||
@@ -48,7 +49,6 @@ go_library(
|
||||
"//pkg/sentry/socket/unix/transport",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserr",
|
||||
"//pkg/syserror",
|
||||
"//pkg/unet",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
gErr "gvisor.dev/gvisor/pkg/errors"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
@@ -32,7 +33,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/host"
|
||||
"gvisor.dev/gvisor/pkg/sentry/memmap"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
// inodeOperations implements fs.InodeOperations.
|
||||
@@ -719,12 +719,12 @@ func (i *inodeOperations) configureMMap(file *fs.File, opts *memmap.MMapOpts) er
|
||||
}
|
||||
|
||||
func init() {
|
||||
syserror.AddErrorUnwrapper(func(err error) (unix.Errno, bool) {
|
||||
linuxerr.AddErrorUnwrapper(func(err error) (*gErr.Error, bool) {
|
||||
if _, ok := err.(p9.ErrSocket); ok {
|
||||
// Treat as an I/O error.
|
||||
return unix.EIO, true
|
||||
return linuxerr.EIO, true
|
||||
}
|
||||
return 0, false
|
||||
return nil, false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ go_library(
|
||||
"//pkg/sentry/uniqueid",
|
||||
"//pkg/sync",
|
||||
"//pkg/syserr",
|
||||
"//pkg/syserror",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/unet",
|
||||
"//pkg/usermem",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user