mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Consistent precondition formatting
Our "Preconditions:" blocks are very useful to determine the input invariants, but they are bit inconsistent throughout the codebase, which makes them harder to read (particularly cases with 5+ conditions in a single paragraph). I've reformatted all of the cases to fit in simple rules: 1. Cases with a single condition are placed on a single line. 2. Cases with multiple conditions are placed in a bulleted list. This format has been added to the style guide. I've also mentioned "Postconditions:", though those are much less frequently used, and all uses already match this style. PiperOrigin-RevId: 327687465
This commit is contained in:
committed by
gVisor bot
parent
f12b545d8f
commit
129018ab3d
@@ -46,6 +46,15 @@ protected.
|
||||
Each field or variable protected by a mutex should state as such in a comment on
|
||||
the field or variable declaration.
|
||||
|
||||
### Function comments
|
||||
|
||||
Functions with special entry conditions (e.g., a lock must be held) should state
|
||||
these conditions in a `Preconditions:` comment block. One condition per line;
|
||||
multiple conditions are specified with a bullet (`*`).
|
||||
|
||||
Functions with notable exit conditions (e.g., a `Done` function must eventually
|
||||
be called by the caller) can similarly have a `Postconditions:` block.
|
||||
|
||||
### Unused returns
|
||||
|
||||
Unused returns should be explicitly ignored with underscores. If there is a
|
||||
|
||||
@@ -65,8 +65,7 @@ func NonBlockingPoll(fd int32, mask waiter.EventMask) waiter.EventMask {
|
||||
|
||||
// epollWait performs a blocking wait on epfd.
|
||||
//
|
||||
// Preconditions:
|
||||
// * len(events) > 0
|
||||
// Preconditions: len(events) > 0
|
||||
func epollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
|
||||
if len(events) == 0 {
|
||||
panic("Empty events passed to EpollWait")
|
||||
|
||||
+19
-12
@@ -179,8 +179,10 @@ const (
|
||||
|
||||
// Connect blocks until the peer Endpoint has called Endpoint.RecvFirst().
|
||||
//
|
||||
// Preconditions: ep is a client Endpoint. ep.Connect(), ep.RecvFirst(),
|
||||
// ep.SendRecv(), and ep.SendLast() have never been called.
|
||||
// Preconditions:
|
||||
// * ep is a client Endpoint.
|
||||
// * ep.Connect(), ep.RecvFirst(), ep.SendRecv(), and ep.SendLast() have never
|
||||
// been called.
|
||||
func (ep *Endpoint) Connect() error {
|
||||
err := ep.ctrlConnect()
|
||||
if err == nil {
|
||||
@@ -192,8 +194,9 @@ func (ep *Endpoint) Connect() error {
|
||||
// RecvFirst blocks until the peer Endpoint calls Endpoint.SendRecv(), then
|
||||
// returns the datagram length specified by that call.
|
||||
//
|
||||
// Preconditions: ep is a server Endpoint. ep.SendRecv(), ep.RecvFirst(), and
|
||||
// ep.SendLast() have never been called.
|
||||
// Preconditions:
|
||||
// * ep is a server Endpoint.
|
||||
// * ep.SendRecv(), ep.RecvFirst(), and ep.SendLast() have never been called.
|
||||
func (ep *Endpoint) RecvFirst() (uint32, error) {
|
||||
if err := ep.ctrlWaitFirst(); err != nil {
|
||||
return 0, err
|
||||
@@ -211,10 +214,12 @@ func (ep *Endpoint) RecvFirst() (uint32, error) {
|
||||
// datagram length, then blocks until the peer Endpoint calls
|
||||
// Endpoint.SendRecv() or Endpoint.SendLast().
|
||||
//
|
||||
// Preconditions: dataLen <= ep.DataCap(). No previous call to ep.SendRecv() or
|
||||
// ep.RecvFirst() has returned an error. ep.SendLast() has never been called.
|
||||
// If ep is a client Endpoint, ep.Connect() has previously been called and
|
||||
// returned nil.
|
||||
// Preconditions:
|
||||
// * dataLen <= ep.DataCap().
|
||||
// * No previous call to ep.SendRecv() or ep.RecvFirst() has returned an error.
|
||||
// * ep.SendLast() has never been called.
|
||||
// * If ep is a client Endpoint, ep.Connect() has previously been called and
|
||||
// returned nil.
|
||||
func (ep *Endpoint) SendRecv(dataLen uint32) (uint32, error) {
|
||||
if dataLen > ep.dataCap {
|
||||
panic(fmt.Sprintf("attempting to send packet with datagram length %d (maximum %d)", dataLen, ep.dataCap))
|
||||
@@ -240,10 +245,12 @@ func (ep *Endpoint) SendRecv(dataLen uint32) (uint32, error) {
|
||||
// SendLast causes the peer Endpoint's call to Endpoint.SendRecv() or
|
||||
// Endpoint.RecvFirst() to return with the given datagram length.
|
||||
//
|
||||
// Preconditions: dataLen <= ep.DataCap(). No previous call to ep.SendRecv() or
|
||||
// ep.RecvFirst() has returned an error. ep.SendLast() has never been called.
|
||||
// If ep is a client Endpoint, ep.Connect() has previously been called and
|
||||
// returned nil.
|
||||
// Preconditions:
|
||||
// * dataLen <= ep.DataCap().
|
||||
// * No previous call to ep.SendRecv() or ep.RecvFirst() has returned an error.
|
||||
// * ep.SendLast() has never been called.
|
||||
// * If ep is a client Endpoint, ep.Connect() has previously been called and
|
||||
// returned nil.
|
||||
func (ep *Endpoint) SendLast(dataLen uint32) error {
|
||||
if dataLen > ep.dataCap {
|
||||
panic(fmt.Sprintf("attempting to send packet with datagram length %d (maximum %d)", dataLen, ep.dataCap))
|
||||
|
||||
@@ -106,8 +106,8 @@ type customUint64Metric struct {
|
||||
// after Initialized.
|
||||
//
|
||||
// Preconditions:
|
||||
// * name must be globally unique.
|
||||
// * Initialize/Disable have not been called.
|
||||
// * name must be globally unique.
|
||||
// * Initialize/Disable have not been called.
|
||||
func RegisterCustomUint64Metric(name string, cumulative, sync bool, units pb.MetricMetadata_Units, description string, value func() uint64) error {
|
||||
if initialized {
|
||||
return ErrInitializationDone
|
||||
@@ -221,7 +221,7 @@ var (
|
||||
// EmitMetricUpdate is thread-safe.
|
||||
//
|
||||
// Preconditions:
|
||||
// * Initialize has been called.
|
||||
// * Initialize has been called.
|
||||
func EmitMetricUpdate() {
|
||||
emitMu.Lock()
|
||||
defer emitMu.Unlock()
|
||||
|
||||
@@ -91,9 +91,10 @@ func BlockSeqFromSlice(slice []Block) BlockSeq {
|
||||
return blockSeqFromSliceLimited(slice, limit)
|
||||
}
|
||||
|
||||
// Preconditions: The combined length of all Blocks in slice <= limit. If
|
||||
// len(slice) != 0, the first Block in slice has non-zero length, and limit >
|
||||
// 0.
|
||||
// Preconditions:
|
||||
// * The combined length of all Blocks in slice <= limit.
|
||||
// * If len(slice) != 0, the first Block in slice has non-zero length and
|
||||
// limit > 0.
|
||||
func blockSeqFromSliceLimited(slice []Block, limit uint64) BlockSeq {
|
||||
switch len(slice) {
|
||||
case 0:
|
||||
|
||||
+18
-14
@@ -407,7 +407,9 @@ func (s *Set) InsertWithoutMerging(gap GapIterator, r Range, val Value) Iterator
|
||||
// and returns an iterator to the inserted segment. All existing iterators
|
||||
// (including gap, but not including the returned iterator) are invalidated.
|
||||
//
|
||||
// Preconditions: r.Start >= gap.Start(); r.End <= gap.End().
|
||||
// Preconditions:
|
||||
// * r.Start >= gap.Start().
|
||||
// * r.End <= gap.End().
|
||||
func (s *Set) InsertWithoutMergingUnchecked(gap GapIterator, r Range, val Value) Iterator {
|
||||
gap = gap.node.rebalanceBeforeInsert(gap)
|
||||
splitMaxGap := trackGaps != 0 && (gap.node.nrSegments == 0 || gap.Range().Length() == gap.node.maxGap.Get())
|
||||
@@ -1211,12 +1213,10 @@ func (seg Iterator) End() Key {
|
||||
// does not invalidate any iterators.
|
||||
//
|
||||
// Preconditions:
|
||||
//
|
||||
// - r.Length() > 0.
|
||||
//
|
||||
// - The new range must not overlap an existing one: If seg.NextSegment().Ok(),
|
||||
// then r.end <= seg.NextSegment().Start(); if seg.PrevSegment().Ok(), then
|
||||
// r.start >= seg.PrevSegment().End().
|
||||
// * r.Length() > 0.
|
||||
// * The new range must not overlap an existing one:
|
||||
// * If seg.NextSegment().Ok(), then r.end <= seg.NextSegment().Start().
|
||||
// * If seg.PrevSegment().Ok(), then r.start >= seg.PrevSegment().End().
|
||||
func (seg Iterator) SetRangeUnchecked(r Range) {
|
||||
seg.node.keys[seg.index] = r
|
||||
}
|
||||
@@ -1241,8 +1241,9 @@ func (seg Iterator) SetRange(r Range) {
|
||||
// SetStartUnchecked mutates the iterated segment's start. This operation does
|
||||
// not invalidate any iterators.
|
||||
//
|
||||
// Preconditions: The new start must be valid: start < seg.End(); if
|
||||
// seg.PrevSegment().Ok(), then start >= seg.PrevSegment().End().
|
||||
// Preconditions: The new start must be valid:
|
||||
// * start < seg.End()
|
||||
// * If seg.PrevSegment().Ok(), then start >= seg.PrevSegment().End().
|
||||
func (seg Iterator) SetStartUnchecked(start Key) {
|
||||
seg.node.keys[seg.index].Start = start
|
||||
}
|
||||
@@ -1264,8 +1265,9 @@ func (seg Iterator) SetStart(start Key) {
|
||||
// SetEndUnchecked mutates the iterated segment's end. This operation does not
|
||||
// invalidate any iterators.
|
||||
//
|
||||
// Preconditions: The new end must be valid: end > seg.Start(); if
|
||||
// seg.NextSegment().Ok(), then end <= seg.NextSegment().Start().
|
||||
// Preconditions: The new end must be valid:
|
||||
// * end > seg.Start().
|
||||
// * If seg.NextSegment().Ok(), then end <= seg.NextSegment().Start().
|
||||
func (seg Iterator) SetEndUnchecked(end Key) {
|
||||
seg.node.keys[seg.index].End = end
|
||||
}
|
||||
@@ -1695,9 +1697,11 @@ func (s *Set) ExportSortedSlices() *SegmentDataSlices {
|
||||
|
||||
// ImportSortedSlice initializes the given set from the given slice.
|
||||
//
|
||||
// Preconditions: s must be empty. sds must represent a valid set (the segments
|
||||
// in sds must have valid lengths that do not overlap). The segments in sds
|
||||
// must be sorted in ascending key order.
|
||||
// Preconditions:
|
||||
// * s must be empty.
|
||||
// * sds must represent a valid set (the segments in sds must have valid
|
||||
// lengths that do not overlap).
|
||||
// * The segments in sds must be sorted in ascending key order.
|
||||
func (s *Set) ImportSortedSlices(sds *SegmentDataSlices) error {
|
||||
if !s.IsEmpty() {
|
||||
return fmt.Errorf("cannot import into non-empty set %v", s)
|
||||
|
||||
@@ -107,8 +107,7 @@ func copyUp(ctx context.Context, d *Dirent) error {
|
||||
// leave the upper filesystem filled with any number of parent directories
|
||||
// but the upper filesystem will never be in an inconsistent state.
|
||||
//
|
||||
// Preconditions:
|
||||
// - d.Inode.overlay is non-nil.
|
||||
// Preconditions: d.Inode.overlay is non-nil.
|
||||
func copyUpLockedForRename(ctx context.Context, d *Dirent) error {
|
||||
for {
|
||||
// Did we race with another copy up or does there
|
||||
@@ -183,12 +182,12 @@ func doCopyUp(ctx context.Context, d *Dirent) error {
|
||||
// Returns a generic error on failure.
|
||||
//
|
||||
// Preconditions:
|
||||
// - parent.Inode.overlay.upper must be non-nil.
|
||||
// - next.Inode.overlay.copyMu must be locked writable.
|
||||
// - next.Inode.overlay.lower must be non-nil.
|
||||
// - next.Inode.overlay.lower.StableAttr.Type must be RegularFile, Directory,
|
||||
// * parent.Inode.overlay.upper must be non-nil.
|
||||
// * next.Inode.overlay.copyMu must be locked writable.
|
||||
// * next.Inode.overlay.lower must be non-nil.
|
||||
// * next.Inode.overlay.lower.StableAttr.Type must be RegularFile, Directory,
|
||||
// or Symlink.
|
||||
// - upper filesystem must support setting file ownership and timestamps.
|
||||
// * upper filesystem must support setting file ownership and timestamps.
|
||||
func copyUpLocked(ctx context.Context, parent *Dirent, next *Dirent) error {
|
||||
// Extract the attributes of the file we wish to copy.
|
||||
attrs, err := next.Inode.overlay.lower.UnstableAttr(ctx)
|
||||
|
||||
@@ -413,9 +413,9 @@ func (d *Dirent) descendantOf(p *Dirent) bool {
|
||||
// Inode.Lookup, otherwise walk will keep d.mu locked.
|
||||
//
|
||||
// Preconditions:
|
||||
// - renameMu must be held for reading.
|
||||
// - d.mu must be held.
|
||||
// - name must must not contain "/"s.
|
||||
// * renameMu must be held for reading.
|
||||
// * d.mu must be held.
|
||||
// * name must must not contain "/"s.
|
||||
func (d *Dirent) walk(ctx context.Context, root *Dirent, name string, walkMayUnlock bool) (*Dirent, error) {
|
||||
if !IsDir(d.Inode.StableAttr) {
|
||||
return nil, syscall.ENOTDIR
|
||||
@@ -577,9 +577,9 @@ func (d *Dirent) Walk(ctx context.Context, root *Dirent, name string) (*Dirent,
|
||||
// exists returns true if name exists in relation to d.
|
||||
//
|
||||
// Preconditions:
|
||||
// - renameMu must be held for reading.
|
||||
// - d.mu must be held.
|
||||
// - name must must not contain "/"s.
|
||||
// * renameMu must be held for reading.
|
||||
// * d.mu must be held.
|
||||
// * name must must not contain "/"s.
|
||||
func (d *Dirent) exists(ctx context.Context, root *Dirent, name string) bool {
|
||||
child, err := d.walk(ctx, root, name, false /* may unlock */)
|
||||
if err != nil {
|
||||
|
||||
@@ -159,8 +159,9 @@ type FileOperations interface {
|
||||
// io provides access to the virtual memory space to which pointers in args
|
||||
// refer.
|
||||
//
|
||||
// Preconditions: The AddressSpace (if any) that io refers to is activated.
|
||||
// Must only be called from a task goroutine.
|
||||
// Preconditions:
|
||||
// * The AddressSpace (if any) that io refers to is activated.
|
||||
// * Must only be called from a task goroutine.
|
||||
Ioctl(ctx context.Context, file *File, io usermem.IO, args arch.SyscallArguments) (uintptr, error)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,9 @@ func (seg FileRangeIterator) FileRange() memmap.FileRange {
|
||||
|
||||
// FileRangeOf returns the FileRange mapped by mr.
|
||||
//
|
||||
// Preconditions: seg.Range().IsSupersetOf(mr). mr.Length() != 0.
|
||||
// Preconditions:
|
||||
// * seg.Range().IsSupersetOf(mr).
|
||||
// * mr.Length() != 0.
|
||||
func (seg FileRangeIterator) FileRangeOf(mr memmap.MappableRange) memmap.FileRange {
|
||||
frstart := seg.Value() + (mr.Start - seg.Start())
|
||||
return memmap.FileRange{frstart, frstart + mr.Length()}
|
||||
@@ -88,8 +90,10 @@ func (seg FileRangeIterator) FileRangeOf(mr memmap.MappableRange) memmap.FileRan
|
||||
// outside of optional. It returns a non-nil error if any error occurs, even
|
||||
// if the error only affects offsets in optional, but not in required.
|
||||
//
|
||||
// Preconditions: required.Length() > 0. optional.IsSupersetOf(required).
|
||||
// required and optional must be page-aligned.
|
||||
// Preconditions:
|
||||
// * required.Length() > 0.
|
||||
// * optional.IsSupersetOf(required).
|
||||
// * required and optional must be page-aligned.
|
||||
func (frs *FileRangeSet) Fill(ctx context.Context, required, optional memmap.MappableRange, mf *pgalloc.MemoryFile, kind usage.MemoryKind, readAt func(ctx context.Context, dsts safemem.BlockSeq, offset uint64) (uint64, error)) error {
|
||||
gap := frs.LowerBoundGap(required.Start)
|
||||
for gap.Ok() && gap.Start() < required.End {
|
||||
|
||||
@@ -80,7 +80,9 @@ func NewHostFileMapper() *HostFileMapper {
|
||||
|
||||
// IncRefOn increments the reference count on all offsets in mr.
|
||||
//
|
||||
// Preconditions: mr.Length() != 0. mr.Start and mr.End must be page-aligned.
|
||||
// Preconditions:
|
||||
// * mr.Length() != 0.
|
||||
// * mr.Start and mr.End must be page-aligned.
|
||||
func (f *HostFileMapper) IncRefOn(mr memmap.MappableRange) {
|
||||
f.refsMu.Lock()
|
||||
defer f.refsMu.Unlock()
|
||||
@@ -97,7 +99,9 @@ func (f *HostFileMapper) IncRefOn(mr memmap.MappableRange) {
|
||||
|
||||
// DecRefOn decrements the reference count on all offsets in mr.
|
||||
//
|
||||
// Preconditions: mr.Length() != 0. mr.Start and mr.End must be page-aligned.
|
||||
// Preconditions:
|
||||
// * mr.Length() != 0.
|
||||
// * mr.Start and mr.End must be page-aligned.
|
||||
func (f *HostFileMapper) DecRefOn(mr memmap.MappableRange) {
|
||||
f.refsMu.Lock()
|
||||
defer f.refsMu.Unlock()
|
||||
@@ -204,7 +208,9 @@ func (f *HostFileMapper) UnmapAll() {
|
||||
}
|
||||
}
|
||||
|
||||
// Preconditions: f.mapsMu must be locked. f.mappings[chunkStart] == m.
|
||||
// Preconditions:
|
||||
// * f.mapsMu must be locked.
|
||||
// * f.mappings[chunkStart] == m.
|
||||
func (f *HostFileMapper) unmapAndRemoveLocked(chunkStart uint64, m mapping) {
|
||||
if _, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, m.addr, chunkSize, 0); errno != 0 {
|
||||
// This leaks address space and is unexpected, but is otherwise
|
||||
|
||||
@@ -684,7 +684,9 @@ func (rw *inodeReadWriter) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) {
|
||||
// maybeGrowFile grows the file's size if data has been written past the old
|
||||
// size.
|
||||
//
|
||||
// Preconditions: rw.c.attrMu and rw.c.dataMu bust be locked.
|
||||
// Preconditions:
|
||||
// * rw.c.attrMu must be locked.
|
||||
// * rw.c.dataMu must be locked.
|
||||
func (rw *inodeReadWriter) maybeGrowFile() {
|
||||
// If the write ends beyond the file's previous size, it causes the
|
||||
// file to grow.
|
||||
|
||||
@@ -86,13 +86,12 @@ func isXattrOverlay(name string) bool {
|
||||
// NewOverlayRoot produces the root of an overlay.
|
||||
//
|
||||
// Preconditions:
|
||||
//
|
||||
// - upper and lower must be non-nil.
|
||||
// - upper must not be an overlay.
|
||||
// - lower should not expose character devices, pipes, or sockets, because
|
||||
// * upper and lower must be non-nil.
|
||||
// * upper must not be an overlay.
|
||||
// * lower should not expose character devices, pipes, or sockets, because
|
||||
// copying up these types of files is not supported.
|
||||
// - lower must not require that file objects be revalidated.
|
||||
// - lower must not have dynamic file/directory content.
|
||||
// * lower must not require that file objects be revalidated.
|
||||
// * lower must not have dynamic file/directory content.
|
||||
func NewOverlayRoot(ctx context.Context, upper *Inode, lower *Inode, flags MountSourceFlags) (*Inode, error) {
|
||||
if !IsDir(upper.StableAttr) {
|
||||
return nil, fmt.Errorf("upper Inode is a %v, not a directory", upper.StableAttr.Type)
|
||||
@@ -117,12 +116,11 @@ func NewOverlayRoot(ctx context.Context, upper *Inode, lower *Inode, flags Mount
|
||||
// NewOverlayRootFile produces the root of an overlay that points to a file.
|
||||
//
|
||||
// Preconditions:
|
||||
//
|
||||
// - lower must be non-nil.
|
||||
// - lower should not expose character devices, pipes, or sockets, because
|
||||
// * lower must be non-nil.
|
||||
// * lower should not expose character devices, pipes, or sockets, because
|
||||
// copying up these types of files is not supported. Neither it can be a dir.
|
||||
// - lower must not require that file objects be revalidated.
|
||||
// - lower must not have dynamic file/directory content.
|
||||
// * lower must not require that file objects be revalidated.
|
||||
// * lower must not have dynamic file/directory content.
|
||||
func NewOverlayRootFile(ctx context.Context, upperMS *MountSource, lower *Inode, flags MountSourceFlags) (*Inode, error) {
|
||||
if !IsRegular(lower.StableAttr) {
|
||||
return nil, fmt.Errorf("lower Inode is not a regular file")
|
||||
|
||||
@@ -104,8 +104,7 @@ func (q *queue) readableSize(ctx context.Context, io usermem.IO, args arch.Sysca
|
||||
// as whether the read caused more readable data to become available (whether
|
||||
// data was pushed from the wait buffer to the read buffer).
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) read(ctx context.Context, dst usermem.IOSequence, l *lineDiscipline) (int64, bool, error) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
@@ -145,8 +144,7 @@ func (q *queue) read(ctx context.Context, dst usermem.IOSequence, l *lineDiscipl
|
||||
|
||||
// write writes to q from userspace.
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) write(ctx context.Context, src usermem.IOSequence, l *lineDiscipline) (int64, error) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
@@ -188,8 +186,7 @@ func (q *queue) write(ctx context.Context, src usermem.IOSequence, l *lineDiscip
|
||||
|
||||
// writeBytes writes to q from b.
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) writeBytes(b []byte, l *lineDiscipline) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
|
||||
@@ -102,8 +102,7 @@ func (q *queue) readableSize(ctx context.Context, io usermem.IO, args arch.Sysca
|
||||
// as whether the read caused more readable data to become available (whether
|
||||
// data was pushed from the wait buffer to the read buffer).
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) read(ctx context.Context, dst usermem.IOSequence, l *lineDiscipline) (int64, bool, error) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
@@ -143,8 +142,7 @@ func (q *queue) read(ctx context.Context, dst usermem.IOSequence, l *lineDiscipl
|
||||
|
||||
// write writes to q from userspace.
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) write(ctx context.Context, src usermem.IOSequence, l *lineDiscipline) (int64, error) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
@@ -186,8 +184,7 @@ func (q *queue) write(ctx context.Context, src usermem.IOSequence, l *lineDiscip
|
||||
|
||||
// writeBytes writes to q from b.
|
||||
//
|
||||
// Preconditions:
|
||||
// * l.termiosMu must be held for reading.
|
||||
// Preconditions: l.termiosMu must be held for reading.
|
||||
func (q *queue) writeBytes(b []byte, l *lineDiscipline) {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
|
||||
@@ -81,9 +81,9 @@ var _ vfs.FilesystemImpl = (*filesystem)(nil)
|
||||
// stepLocked is loosely analogous to fs/namei.c:walk_component().
|
||||
//
|
||||
// Preconditions:
|
||||
// - filesystem.mu must be locked (for writing if write param is true).
|
||||
// - !rp.Done().
|
||||
// - inode == vfsd.Impl().(*Dentry).inode.
|
||||
// * filesystem.mu must be locked (for writing if write param is true).
|
||||
// * !rp.Done().
|
||||
// * inode == vfsd.Impl().(*Dentry).inode.
|
||||
func stepLocked(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentry, inode *inode, write bool) (*vfs.Dentry, *inode, error) {
|
||||
if !inode.isDir() {
|
||||
return nil, nil, syserror.ENOTDIR
|
||||
@@ -166,7 +166,7 @@ func stepLocked(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentry, in
|
||||
// walkLocked is loosely analogous to Linux's fs/namei.c:path_lookupat().
|
||||
//
|
||||
// Preconditions:
|
||||
// - filesystem.mu must be locked (for writing if write param is true).
|
||||
// * filesystem.mu must be locked (for writing if write param is true).
|
||||
func walkLocked(ctx context.Context, rp *vfs.ResolvingPath, write bool) (*vfs.Dentry, *inode, error) {
|
||||
vfsd := rp.Start()
|
||||
inode := vfsd.Impl().(*dentry).inode
|
||||
@@ -194,8 +194,8 @@ func walkLocked(ctx context.Context, rp *vfs.ResolvingPath, write bool) (*vfs.De
|
||||
// walkParentLocked is loosely analogous to Linux's fs/namei.c:path_parentat().
|
||||
//
|
||||
// Preconditions:
|
||||
// - filesystem.mu must be locked (for writing if write param is true).
|
||||
// - !rp.Done().
|
||||
// * filesystem.mu must be locked (for writing if write param is true).
|
||||
// * !rp.Done().
|
||||
func walkParentLocked(ctx context.Context, rp *vfs.ResolvingPath, write bool) (*vfs.Dentry, *inode, error) {
|
||||
vfsd := rp.Start()
|
||||
inode := vfsd.Impl().(*dentry).inode
|
||||
|
||||
@@ -34,8 +34,11 @@ func (d *dentry) isDir() bool {
|
||||
return d.fileType() == linux.S_IFDIR
|
||||
}
|
||||
|
||||
// Preconditions: filesystem.renameMu must be locked. d.dirMu must be locked.
|
||||
// d.isDir(). child must be a newly-created dentry that has never had a parent.
|
||||
// Preconditions:
|
||||
// * filesystem.renameMu must be locked.
|
||||
// * d.dirMu must be locked.
|
||||
// * d.isDir().
|
||||
// * child must be a newly-created dentry that has never had a parent.
|
||||
func (d *dentry) cacheNewChildLocked(child *dentry, name string) {
|
||||
d.IncRef() // reference held by child on its parent
|
||||
child.parent = d
|
||||
@@ -46,7 +49,9 @@ func (d *dentry) cacheNewChildLocked(child *dentry, name string) {
|
||||
d.children[name] = child
|
||||
}
|
||||
|
||||
// Preconditions: d.dirMu must be locked. d.isDir().
|
||||
// Preconditions:
|
||||
// * d.dirMu must be locked.
|
||||
// * d.isDir().
|
||||
func (d *dentry) cacheNegativeLookupLocked(name string) {
|
||||
// Don't cache negative lookups if InteropModeShared is in effect (since
|
||||
// this makes remote lookup unavoidable), or if d.isSynthetic() (in which
|
||||
@@ -79,8 +84,10 @@ type createSyntheticOpts struct {
|
||||
// createSyntheticChildLocked creates a synthetic file with the given name
|
||||
// in d.
|
||||
//
|
||||
// Preconditions: d.dirMu must be locked. d.isDir(). d does not already contain
|
||||
// a child with the given name.
|
||||
// Preconditions:
|
||||
// * d.dirMu must be locked.
|
||||
// * d.isDir().
|
||||
// * d does not already contain a child with the given name.
|
||||
func (d *dentry) createSyntheticChildLocked(opts *createSyntheticOpts) {
|
||||
child := &dentry{
|
||||
refs: 1, // held by d
|
||||
@@ -151,7 +158,9 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
|
||||
return nil
|
||||
}
|
||||
|
||||
// Preconditions: d.isDir(). There exists at least one directoryFD representing d.
|
||||
// Preconditions:
|
||||
// * d.isDir().
|
||||
// * There exists at least one directoryFD representing d.
|
||||
func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
|
||||
// NOTE(b/135560623): 9P2000.L's readdir does not specify behavior in the
|
||||
// presence of concurrent mutation of an iterated directory, so
|
||||
|
||||
@@ -115,9 +115,12 @@ func putDentrySlice(ds *[]*dentry) {
|
||||
// Dentries which may become cached as a result of the traversal are appended
|
||||
// to *ds.
|
||||
//
|
||||
// Preconditions: fs.renameMu must be locked. d.dirMu must be locked.
|
||||
// !rp.Done(). If !d.cachedMetadataAuthoritative(), then d's cached metadata
|
||||
// must be up to date.
|
||||
// Preconditions:
|
||||
// * fs.renameMu must be locked.
|
||||
// * d.dirMu must be locked.
|
||||
// * !rp.Done().
|
||||
// * If !d.cachedMetadataAuthoritative(), then d's cached metadata must be up
|
||||
// to date.
|
||||
//
|
||||
// Postconditions: The returned dentry's cached metadata is up to date.
|
||||
func (fs *filesystem) stepLocked(ctx context.Context, rp *vfs.ResolvingPath, d *dentry, mayFollowSymlinks bool, ds **[]*dentry) (*dentry, error) {
|
||||
@@ -185,8 +188,11 @@ afterSymlink:
|
||||
// getChildLocked returns a dentry representing the child of parent with the
|
||||
// given name. If no such child exists, getChildLocked returns (nil, nil).
|
||||
//
|
||||
// Preconditions: fs.renameMu must be locked. parent.dirMu must be locked.
|
||||
// parent.isDir(). name is not "." or "..".
|
||||
// Preconditions:
|
||||
// * fs.renameMu must be locked.
|
||||
// * parent.dirMu must be locked.
|
||||
// * parent.isDir().
|
||||
// * name is not "." or "..".
|
||||
//
|
||||
// Postconditions: If getChildLocked returns a non-nil dentry, its cached
|
||||
// metadata is up to date.
|
||||
@@ -206,7 +212,8 @@ func (fs *filesystem) getChildLocked(ctx context.Context, vfsObj *vfs.VirtualFil
|
||||
return fs.revalidateChildLocked(ctx, vfsObj, parent, name, child, ds)
|
||||
}
|
||||
|
||||
// Preconditions: As for getChildLocked. !parent.isSynthetic().
|
||||
// Preconditions: Same as getChildLocked, plus:
|
||||
// * !parent.isSynthetic().
|
||||
func (fs *filesystem) revalidateChildLocked(ctx context.Context, vfsObj *vfs.VirtualFilesystem, parent *dentry, name string, child *dentry, ds **[]*dentry) (*dentry, error) {
|
||||
if child != nil {
|
||||
// Need to lock child.metadataMu because we might be updating child
|
||||
@@ -279,9 +286,11 @@ func (fs *filesystem) revalidateChildLocked(ctx context.Context, vfsObj *vfs.Vir
|
||||
// rp.Start().Impl().(*dentry)). It does not check that the returned directory
|
||||
// is searchable by the provider of rp.
|
||||
//
|
||||
// Preconditions: fs.renameMu must be locked. !rp.Done(). If
|
||||
// !d.cachedMetadataAuthoritative(), then d's cached metadata must be up to
|
||||
// date.
|
||||
// Preconditions:
|
||||
// * fs.renameMu must be locked.
|
||||
// * !rp.Done().
|
||||
// * If !d.cachedMetadataAuthoritative(), then d's cached metadata must be up
|
||||
// to date.
|
||||
func (fs *filesystem) walkParentDirLocked(ctx context.Context, rp *vfs.ResolvingPath, d *dentry, ds **[]*dentry) (*dentry, error) {
|
||||
for !rp.Final() {
|
||||
d.dirMu.Lock()
|
||||
@@ -328,8 +337,9 @@ func (fs *filesystem) resolveLocked(ctx context.Context, rp *vfs.ResolvingPath,
|
||||
// createInRemoteDir (if the parent directory is a real remote directory) or
|
||||
// createInSyntheticDir (if the parent directory is synthetic) to do so.
|
||||
//
|
||||
// Preconditions: !rp.Done(). For the final path component in rp,
|
||||
// !rp.ShouldFollowSymlink().
|
||||
// Preconditions:
|
||||
// * !rp.Done().
|
||||
// * For the final path component in rp, !rp.ShouldFollowSymlink().
|
||||
func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir bool, createInRemoteDir func(parent *dentry, name string, ds **[]*dentry) error, createInSyntheticDir func(parent *dentry, name string) error) error {
|
||||
var ds *[]*dentry
|
||||
fs.renameMu.RLock()
|
||||
@@ -1087,8 +1097,10 @@ retry:
|
||||
return &fd.vfsfd, nil
|
||||
}
|
||||
|
||||
// Preconditions: d.fs.renameMu must be locked. d.dirMu must be locked.
|
||||
// !d.isSynthetic().
|
||||
// Preconditions:
|
||||
// * d.fs.renameMu must be locked.
|
||||
// * d.dirMu must be locked.
|
||||
// * !d.isSynthetic().
|
||||
func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.OpenOptions, ds **[]*dentry) (*vfs.FileDescription, error) {
|
||||
if err := d.checkPermissions(rp.Credentials(), vfs.MayWrite); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1418,7 +1418,9 @@ func (d *dentry) userXattrSupported() bool {
|
||||
return filetype == linux.ModeRegular || filetype == linux.ModeDirectory
|
||||
}
|
||||
|
||||
// Preconditions: !d.isSynthetic(). d.isRegularFile() || d.isDir().
|
||||
// Preconditions:
|
||||
// * !d.isSynthetic().
|
||||
// * d.isRegularFile() || d.isDir().
|
||||
func (d *dentry) ensureSharedHandle(ctx context.Context, read, write, trunc bool) error {
|
||||
// O_TRUNC unconditionally requires us to obtain a new handle (opened with
|
||||
// O_TRUNC).
|
||||
|
||||
@@ -52,8 +52,9 @@ func (d *dentry) touchAtime(mnt *vfs.Mount) {
|
||||
mnt.EndWrite()
|
||||
}
|
||||
|
||||
// Preconditions: d.cachedMetadataAuthoritative() == true. The caller has
|
||||
// successfully called vfs.Mount.CheckBeginWrite().
|
||||
// Preconditions:
|
||||
// * d.cachedMetadataAuthoritative() == true.
|
||||
// * The caller has successfully called vfs.Mount.CheckBeginWrite().
|
||||
func (d *dentry) touchCtime() {
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
d.metadataMu.Lock()
|
||||
@@ -61,8 +62,9 @@ func (d *dentry) touchCtime() {
|
||||
d.metadataMu.Unlock()
|
||||
}
|
||||
|
||||
// Preconditions: d.cachedMetadataAuthoritative() == true. The caller has
|
||||
// successfully called vfs.Mount.CheckBeginWrite().
|
||||
// Preconditions:
|
||||
// * d.cachedMetadataAuthoritative() == true.
|
||||
// * The caller has successfully called vfs.Mount.CheckBeginWrite().
|
||||
func (d *dentry) touchCMtime() {
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
d.metadataMu.Lock()
|
||||
@@ -72,8 +74,9 @@ func (d *dentry) touchCMtime() {
|
||||
d.metadataMu.Unlock()
|
||||
}
|
||||
|
||||
// Preconditions: d.cachedMetadataAuthoritative() == true. The caller has
|
||||
// locked d.metadataMu.
|
||||
// Preconditions:
|
||||
// * d.cachedMetadataAuthoritative() == true.
|
||||
// * The caller has locked d.metadataMu.
|
||||
func (d *dentry) touchCMtimeLocked() {
|
||||
now := d.fs.clock.Now().Nanoseconds()
|
||||
atomic.StoreInt64(&d.mtime, now)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user