1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
// Copyright 2020 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 fsmetric defines filesystem metrics that are used by both VFS1 and
// VFS2.
//
// TODO(gvisor.dev/issue/1624): Once VFS1 is deleted, inline these metrics into
// VFS2.
package fsmetric
import (
"time"
"gvisor.dev/gvisor/pkg/metric"
)
// RecordWaitTime enables the ReadWait, GoferReadWait9P, GoferReadWaitHost, and
// TmpfsReadWait metrics. Enabling this comes at a CPU cost due to performing
// three clock reads per read call.
//
// Note that this is only performed in the direct read path, and may not be
// consistently applied for other forms of reads, such as splice.
var RecordWaitTime = false
// Metrics that apply to all filesystems.
var (
Opens = metric.MustCreateNewUint64Metric("/fs/opens", false /* sync */, "Number of file opens.")
Reads = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
ReadWait = metric.MustCreateNewUint64NanosecondsMetric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
)
// Metrics that only apply to fs/gofer and fsimpl/gofer.
var (
GoferOpensWX = metric.MustCreateNewUint64Metric("/gofer/opened_write_execute_file", true /* sync */, "Number of times a executable file was opened writably from a gofer.")
GoferOpens9P = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a file was opened from a gofer and did not have a host file descriptor.")
GoferOpensHost = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a file was opened from a gofer and did have a host file descriptor.")
GoferReads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
GoferReadWait9P = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
GoferReadsHost = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
GoferReadWaitHost = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
)
// Metrics that only apply to fs/tmpfs and fsimpl/tmpfs.
var (
TmpfsOpensRO = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
TmpfsOpensW = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
TmpfsReads = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
TmpfsReadWait = metric.MustCreateNewUint64NanosecondsMetric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
)
// StartReadWait indicates the beginning of a file read.
func StartReadWait() time.Time {
if !RecordWaitTime {
return time.Time{}
}
return time.Now()
}
// FinishReadWait indicates the end of a file read whose time is accounted by
// m. start must be the value returned by the corresponding call to
// StartReadWait.
//
// FinishReadWait is marked nosplit for performance since it's often called
// from defer statements, which prevents it from being inlined
// (https://github.com/golang/go/issues/38471).
//go:nosplit
func FinishReadWait(m *metric.Uint64Metric, start time.Time) {
if !RecordWaitTime {
return
}
m.IncrementBy(uint64(time.Since(start).Nanoseconds()))
}
|