github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/usage/io.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package usage 16 17 import ( 18 "sync/atomic" 19 ) 20 21 // IO contains I/O-related statistics. 22 // 23 // +stateify savable 24 type IO struct { 25 // CharsRead is the number of bytes read by read syscalls. 26 CharsRead uint64 27 28 // CharsWritten is the number of bytes written by write syscalls. 29 CharsWritten uint64 30 31 // ReadSyscalls is the number of read syscalls. 32 ReadSyscalls uint64 33 34 // WriteSyscalls is the number of write syscalls. 35 WriteSyscalls uint64 36 37 // The following counter is only meaningful when Sentry has internal 38 // pagecache. 39 40 // BytesRead is the number of bytes actually read into pagecache. 41 BytesRead uint64 42 43 // BytesWritten is the number of bytes actually written from pagecache. 44 BytesWritten uint64 45 46 // BytesWriteCancelled is the number of bytes not written out due to 47 // truncation. 48 BytesWriteCancelled uint64 49 } 50 51 // AccountReadSyscall does the accounting for a read syscall. 52 func (i *IO) AccountReadSyscall(bytes int64) { 53 atomic.AddUint64(&i.ReadSyscalls, 1) 54 if bytes > 0 { 55 atomic.AddUint64(&i.CharsRead, uint64(bytes)) 56 } 57 } 58 59 // AccountWriteSyscall does the accounting for a write syscall. 60 func (i *IO) AccountWriteSyscall(bytes int64) { 61 atomic.AddUint64(&i.WriteSyscalls, 1) 62 if bytes > 0 { 63 atomic.AddUint64(&i.CharsWritten, uint64(bytes)) 64 } 65 } 66 67 // AccountReadIO does the accounting for a read IO into the file system. 68 func (i *IO) AccountReadIO(bytes int64) { 69 if bytes > 0 { 70 atomic.AddUint64(&i.BytesRead, uint64(bytes)) 71 } 72 } 73 74 // AccountWriteIO does the accounting for a write IO into the file system. 75 func (i *IO) AccountWriteIO(bytes int64) { 76 if bytes > 0 { 77 atomic.AddUint64(&i.BytesWritten, uint64(bytes)) 78 } 79 } 80 81 // Accumulate adds up io usages. 82 func (i *IO) Accumulate(io *IO) { 83 atomic.AddUint64(&i.CharsRead, atomic.LoadUint64(&io.CharsRead)) 84 atomic.AddUint64(&i.CharsWritten, atomic.LoadUint64(&io.CharsWritten)) 85 atomic.AddUint64(&i.ReadSyscalls, atomic.LoadUint64(&io.ReadSyscalls)) 86 atomic.AddUint64(&i.WriteSyscalls, atomic.LoadUint64(&io.WriteSyscalls)) 87 atomic.AddUint64(&i.BytesRead, atomic.LoadUint64(&io.BytesRead)) 88 atomic.AddUint64(&i.BytesWritten, atomic.LoadUint64(&io.BytesWritten)) 89 atomic.AddUint64(&i.BytesWriteCancelled, atomic.LoadUint64(&io.BytesWriteCancelled)) 90 }