Internal change.

PiperOrigin-RevId: 235053594
Change-Id: Ie3d7b11843d0710184a2463886c7034e8f5305d1
This commit is contained in:
Googler
2019-02-21 13:08:34 -08:00
committed by Shentubot
parent b2a5ad047a
commit 532f4b2fba
3 changed files with 73 additions and 17 deletions
+29 -1
View File
@@ -18,6 +18,7 @@ import (
"math"
"sync"
"sync/atomic"
"time"
"gvisor.googlesource.com/gvisor/pkg/amutex"
"gvisor.googlesource.com/gvisor/pkg/log"
@@ -33,7 +34,22 @@ import (
"gvisor.googlesource.com/gvisor/pkg/waiter"
)
var reads = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
var (
// RecordWaitTime controls writing metrics for filesystem reads. Enabling this comes at a small
// CPU cost due to performing two monotonic clock reads per read call.
RecordWaitTime = false
reads = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
readWait = metric.MustCreateNewUint64Metric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
)
// IncrementWait increments the given wait time metric, if enabled.
func IncrementWait(m *metric.Uint64Metric, start time.Time) {
if !RecordWaitTime {
return
}
m.IncrementBy(uint64(time.Since(start)))
}
// FileMaxOffset is the maximum possible file offset.
const FileMaxOffset = math.MaxInt64
@@ -236,7 +252,12 @@ func (f *File) Readdir(ctx context.Context, serializer DentrySerializer) error {
//
// Returns syserror.ErrInterrupted if reading was interrupted.
func (f *File) Readv(ctx context.Context, dst usermem.IOSequence) (int64, error) {
var start time.Time
if RecordWaitTime {
start = time.Now()
}
if !f.mu.Lock(ctx) {
IncrementWait(readWait, start)
return 0, syserror.ErrInterrupted
}
@@ -246,6 +267,7 @@ func (f *File) Readv(ctx context.Context, dst usermem.IOSequence) (int64, error)
atomic.AddInt64(&f.offset, n)
}
f.mu.Unlock()
IncrementWait(readWait, start)
return n, err
}
@@ -255,13 +277,19 @@ func (f *File) Readv(ctx context.Context, dst usermem.IOSequence) (int64, error)
//
// Otherwise same as Readv.
func (f *File) Preadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
var start time.Time
if RecordWaitTime {
start = time.Now()
}
if !f.mu.Lock(ctx) {
IncrementWait(readWait, start)
return 0, syserror.ErrInterrupted
}
reads.Increment()
n, err := f.FileOperations.Read(ctx, f, dst, offset)
f.mu.Unlock()
IncrementWait(readWait, start)
return n, err
}
+32 -13
View File
@@ -17,6 +17,7 @@ package gofer
import (
"fmt"
"syscall"
"time"
"gvisor.googlesource.com/gvisor/pkg/log"
"gvisor.googlesource.com/gvisor/pkg/metric"
@@ -32,11 +33,13 @@ import (
)
var (
opensWX = metric.MustCreateNewUint64Metric("/gofer/opened_write_execute_file", true /* sync */, "Number of times a writable+executable file was opened from a gofer.")
opens9P = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a 9P file was opened from a gofer.")
opensHost = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a host file was opened from a gofer.")
reads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
readsHost = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
opensWX = metric.MustCreateNewUint64Metric("/gofer/opened_write_execute_file", true /* sync */, "Number of times a writable+executable file was opened from a gofer.")
opens9P = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a 9P file was opened from a gofer.")
opensHost = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a host file was opened from a gofer.")
reads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
readWait9P = metric.MustCreateNewUint64Metric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
readsHost = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
readWaitHost = metric.MustCreateNewUint64Metric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
)
// fileOperations implements fs.FileOperations for a remote file system.
@@ -232,22 +235,38 @@ func (f *fileOperations) Write(ctx context.Context, file *fs.File, src usermem.I
return src.CopyInTo(ctx, f.handles.readWriterAt(ctx, offset))
}
// Read implements fs.FileOperations.Read.
func (f *fileOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if fs.IsDir(file.Dirent.Inode.StableAttr) {
// Not all remote file systems enforce this so this client does.
return 0, syserror.EISDIR
}
// incrementReadCounters increments the read counters for the read starting at the given time. We
// use this function rather than using a defer in Read() to avoid the performance hit of defer.
func (f *fileOperations) incrementReadCounters(start time.Time) {
if f.handles.Host != nil {
readsHost.Increment()
fs.IncrementWait(readWaitHost, start)
} else {
reads9P.Increment()
fs.IncrementWait(readWait9P, start)
}
}
// Read implements fs.FileOperations.Read.
func (f *fileOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
var start time.Time
if fs.RecordWaitTime {
start = time.Now()
}
if fs.IsDir(file.Dirent.Inode.StableAttr) {
// Not all remote file systems enforce this so this client does.
f.incrementReadCounters(start)
return 0, syserror.EISDIR
}
if f.inodeOperations.session().cachePolicy.useCachingInodeOps(file.Dirent.Inode) {
return f.inodeOperations.cachingInodeOps.Read(ctx, file, dst, offset)
n, err := f.inodeOperations.cachingInodeOps.Read(ctx, file, dst, offset)
f.incrementReadCounters(start)
return n, err
}
return dst.CopyOutFrom(ctx, f.handles.readWriterAt(ctx, offset))
n, err := dst.CopyOutFrom(ctx, f.handles.readWriterAt(ctx, offset))
f.incrementReadCounters(start)
return n, err
}
// Fsync implements fs.FileOperations.Fsync.
+12 -3
View File
@@ -17,6 +17,7 @@ package tmpfs
import (
"io"
"sync"
"time"
"gvisor.googlesource.com/gvisor/pkg/metric"
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
@@ -31,9 +32,10 @@ import (
)
var (
opensRO = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
opensW = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
reads = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
opensRO = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
opensW = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
reads = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
readWait = metric.MustCreateNewUint64Metric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
)
// fileInodeOperations implements fs.InodeOperations for a regular tmpfs file.
@@ -249,9 +251,14 @@ func (*fileInodeOperations) StatFS(context.Context) (fs.Info, error) {
}
func (f *fileInodeOperations) read(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
var start time.Time
if fs.RecordWaitTime {
start = time.Now()
}
reads.Increment()
// Zero length reads for tmpfs are no-ops.
if dst.NumBytes() == 0 {
fs.IncrementWait(readWait, start)
return 0, nil
}
@@ -268,6 +275,7 @@ func (f *fileInodeOperations) read(ctx context.Context, dst usermem.IOSequence,
size := f.attr.Size
f.dataMu.RUnlock()
if offset >= size {
fs.IncrementWait(readWait, start)
return 0, io.EOF
}
@@ -276,6 +284,7 @@ func (f *fileInodeOperations) read(ctx context.Context, dst usermem.IOSequence,
f.attrMu.Lock()
f.attr.AccessTime = ktime.NowFromContext(ctx)
f.attrMu.Unlock()
fs.IncrementWait(readWait, start)
return n, err
}