This is an optimization that will prevent needless lookups on lower layers for
directories. This is analogous to the Linux commit 97c684cc9110 ("ovl: create
directories inside merged parent opaque").
If mkdir(2) does succeed, then none of the lower layers have a file at that
position, otherwise mkdir(2) would have failed with EEXIST.
Changes on the lower layer underneath a new upper layer directory are not
visible. See the following for example:
```
$ sudo mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=workdir none overlay
$ mkdir -p overlay/dir/dir1
$ mkdir -p lower/dir/dir2
$ ls overlay/dir/
dir1
```
Benchmarking shows that this change cuts ABSL build time by 9.5%!
```
goos: linux
goarch: amd64
cpu: Intel(R) Xeon(R) CPU @ 2.20GHz
│ /tmp/benchout.runsc │ /tmp/benchout.runsc-opt │
│ sec/op │ sec/op vs base │
BuildABSL/page_cache.clean/filesystem.bindfs-8 71.16 ± 12% 64.40 ± 3% -9.50% (p=0.003 n=8)
BuildGRPC/page_cache.clean/filesystem.bindfs-8 418.2 ± 1% 419.9 ± 1% ~ (p=0.721 n=8)
RubySpecTest/page_cache.clean/filesystem.bindfs-8 76.67 ± 5% 75.17 ± 1% ~ (p=0.382 n=8)
geomean 131.6 126.7 -3.78%
│ /tmp/benchout.runsc │ /tmp/benchout.runsc-opt │
│ load.sec │ load.sec vs base │
RubySpecTest/page_cache.clean/filesystem.bindfs-8 12.95 ± 6% 12.80 ± 5% ~ (p=0.625 n=8)
```
PiperOrigin-RevId: 538823897
This catches up the interface to the `EmitUnimplementedEvent` method signature
on `kernel.Kernel`.
Also add build-time test to verify that `kernel.Kernel` implements this
interface, in order to catch such breakages at build time in the future.
PiperOrigin-RevId: 519000411
All filesystems except tmpfs had the same bug regarding handling symlinks
in the terminal path component. When they tried to open(2) such a symlink
file, these implementations called into stepLocked() with
Then these implementations also called vfs.HandleSymlink() which would
also advance rp (when rp.Done() was already true).
This was tripping the invariants checks in sentry/vfs/debug.go.
PiperOrigin-RevId: 504098263
Linux overlayfs uses the max of all layers' filename length limit. Do the same
in gVisor.
This is needed to get PHP runtime test ext/standard/tests/strings/007.phpt to
pass with overlayfs.
PiperOrigin-RevId: 493942515
This CL does the following:
- Add the ability for nested locks to have names.
- Give names to all current uses of nested locks in the codebase.
- Truncate `lockdep` debug stack traces to avoid the clutter from the
`lockdep` code itself
- Simplify `lockdep` to not longer require `classMap`.
PiperOrigin-RevId: 491486620
Earlier, we were only copying up regular files. We were missing
out device files. ensureOpenableLocked() should ensure that
files are copied up if mode is writable. Without this, we
violate the preconditions for openCopiedUp().
Also, without this, open(file, O_WRONLY) on a lower layer pipe
returns EROFS, which is confusing because the upper layer is
still writable. Now it will return EPERM which indicates that
the pipe can not be copied up.
PiperOrigin-RevId: 465838606
Make access(W_OK) return EACCES in overlayfs if file exists only
on lower layer and can not be copied up. Earlier, access(W_OK)
was succeeding but operations that cause copy-up (like
open(WR_ONLY)) were failing. This is likely to confuse
applications.
PiperOrigin-RevId: 465818314
In Linux, the callers of fs/namei.c:do_renameat2() do this check
by calling fs/namei.c:getname().
This is important of consistency with Linux. Also, without this
we can see panics in overlayfs rename if new file's name is too
long. Because upperlayer RenameAt operation would succeed but
SetXattr operation will fail leading to an inconsistent state.
PiperOrigin-RevId: 464173793
`vfs.FileDescription` in general handles all inotify work. Only
SetStat, SetXattr, RemoveXattr and Iterdirents require FDImpls to
handle the Inotify work. This leads to repeated code. And for
kernfs users, there are too many FD implementors. So it becomes
difficult plumbing Inotify consistenly through all FDImpls.
So make it consistent that all Inotify work is handled by
`vfs.FileDescription`, not FDImpls.
PiperOrigin-RevId: 461751122
This change does 3 things:
- Adds `IsEvictable() bool` and `MarkEvictable()` methods to
vfs.Dentry. A dentry's "evictability" is just a hint to filesystem
implementations that this dentry will not be accessed again
(from the caller of Dentry.MarkEvictable()). So filesystem
implementation can choose to release resources for such evictable
dentries. For example, caching such dentries is no longer useful.
- In VFS2, only 2 filesystem implementations have a LRU dentry
cache: kernfs and gofer. Dentries with 0 refs are cached here.
Updated both these filesystem implementations to evict dentries
that have 0 refs and are evictable.
- Updated overlayfs to mark lower layer dentries for
non-directory files as evictable when either a dentry is copied up
or a dentry is deleted. In both cases if there is a dentry in
the lower layer, it is no longer visible from the overlayfs.
Note that the file "replaced" by rename(2) is also considered
deleted.
Motivation:
We were observing elevated memory usage in VFS2 when using
overlayfs because VFS2 gofer client has a dentry cache and was
holding on to lower layer dentries which were anyways not
accessible from the overlayfs. The file mappings for these stale
dentries were responsible for holding up so much sentry memory.
PiperOrigin-RevId: 460325860
Earlier we were using the topmost inode and device number to
compute the directory inode number. But the topmost layer changes
after a copy up which causes a new inode number to be generated
after a copy up.
This confuses some applications like GNU's FTS library. See
fts_safe_changedir() for example which errors out with ENOENT if
it observes that the dirctory inode or device number has changed.
Now we use the bottommost layer's inode and device numbers. Linux
and VFS1 also preserve the directory's inode number after copy up.
PiperOrigin-RevId: 456147019
All atomic 64 bit ints are changed to atomicbitops.(Ui|I)nt64. A nogo checker
enforces that sync/atomic 64 bit functions are not called.
For reviewers: the interesting changes are in the atomicbitops and checkaligned
packages.
Why do this?
- It is very easy to accidentally use atomic values without sync/atomic funcs.
- We have checkatomics, but this is optional and is forgotten in several places.
- Using a type+checker to enforce this seems less error prone and simpler.
- We get NoCopy protection.
- Use of 64 bit atomics can break 32 bit builds. We have types to handle this
without any runtime cost, so we might as well use them.
PiperOrigin-RevId: 440473398
Linux exempts special files (sockets, named pipes, and character/block device
special files) from mount writability checks in both open
(fs/open.c:do_dentry_open()) and access (fs/open.c:do_faccessat()) paths. We
don't currently do so in open (in VFS1 or VFS2) or access (in VFS1), so we
don't do so in VFS2 access either.
PiperOrigin-RevId: 439398002
Linux behaves differently for regular files and dirs for poll(2)/select(2)
compared to epoll_ctl(2). The latter returns EPERM for file and dirs.
I've also changed host FDs to behave like the underlying FD in regards
to epoll to keep it compatible with docker.
Fixes#7134
PiperOrigin-RevId: 429412692
Doing so can deadlock, and regular files and symlinks usually shouldn't be
event-registerable anyway (especially after cl/426516504).
PiperOrigin-RevId: 429117155
Docker maps stdin to `/dev/null` which doesn't support epoll. Host FD
was ignoring the error and suceeding the epoll_ctl call from the
container, giving false impressing that epoll would be notified.
This required plumbing failure to all waiter.Waitable.EventRegister
callers and implementers.
Closes#6795
PiperOrigin-RevId: 414797621
Instead of passing the event mask at registratrion time, pass the mask as part
of the waiter. This makes the mask immutable and simplifies the architecture of
waiters. This is also necessary for a future fix that will allow the fdnotifier
to keep persistent entries, as opposed to requiring constant updates.
This change is intended to be a no-op in terms of function. The only exception
is signalfd, where this mask was abused. To handle this case, the operation of
signalfd changed to allow one layer of indirection.
PiperOrigin-RevId: 409702998
vfs.NewDisconnectedMount has no error paths. Its much prettier without the
error return value.
Also simplify MountDisconnected which would immediately drop the refs taken by
NewDisconnectedMount. Instead make it directly call newMount.
PiperOrigin-RevId: 405767966
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 change makes the checklocks analyzer considerable more powerful, adding:
* The ability to traverse complex structures, e.g. to have multiple nested
fields as part of the annotation.
* The ability to resolve simple anonymous functions and closures, and perform
lock analysis across these invocations. This does not apply to closures that
are passed elsewhere, since it is not possible to know the context in which
they might be invoked.
* The ability to annotate return values in addition to receivers and other
parameters, with the same complex structures noted above.
* Ignoring locking semantics for "fresh" objects, i.e. objects that are
allocated in the local frame (typically a new-style function).
* Sanity checking of locking state across block transitions and returns, to
ensure that no unexpected locks are held.
Note that initially, most of these findings are excluded by a comprehensive
nogo.yaml. The findings that are included are fundamental lock violations.
The changes here should be relatively low risk, minor refactorings to either
include necessary annotations to simplify the code structure (in general
removing closures in favor of methods) so that the analyzer can be easily
track the lock state.
This change additional includes two changes to nogo itself:
* Sanity checking of all types to ensure that the binary and ast-derived
types have a consistent objectpath, to prevent the bug above from occurring
silently (and causing much confusion). This also requires a trick in
order to ensure that serialized facts are consumable downstream. This can
be removed with https://go-review.googlesource.com/c/tools/+/331789 merged.
* A minor refactoring to isolation the objdump settings in its own package.
This was originally used to implement the sanity check above, but this
information is now being passed another way. The minor refactor is preserved
however, since it cleans up the code slightly and is minimal risk.
PiperOrigin-RevId: 382613300
Update all instances of the above errors to the faster linuxerr implementation.
With the temporary linuxerr.Equals(), no logical changes are made.
PiperOrigin-RevId: 382306655
Remove three syserror entries duplicated in linuxerr. Because of the
linuxerr.Equals method, this is a mere change of return values from
syserror to linuxerr definitions.
Done with only these three errnos as CLs removing all grow to a significantly
large size.
PiperOrigin-RevId: 382173835
Add Equals method to compare syserror and unix.Errno errors to linuxerr errors.
This will facilitate removal of syserror definitions in a followup, and
finding needed conversions from unix.Errno to linuxerr.
PiperOrigin-RevId: 380909667
Split usermem package to help remove syserror dependency in go_marshal.
New hostarch package contains code not dependent on syserror.
PiperOrigin-RevId: 365651233
This validates that struct fields if annotated with "// checklocks:mu" where
"mu" is a mutex field in the same struct then access to the field is only
done with "mu" locked.
All types that are guarded by a mutex must be annotated with
// +checklocks:<mutex field name>
For more details please refer to README.md.
PiperOrigin-RevId: 360729328
Before this CL, VFS2's overlayfs uses a single private device number and an
autoincrementing generated inode number for directories; this is consistent
with Linux's overlayfs in the non-samefs non-xino case. However, this breaks
some applications more consistently than on Linux due to more aggressive
caching of Linux overlayfs dentries.
Switch from using mapped device numbers + the topmost layer's inode number for
just non-copied-up non-directory files, to doing so for all files. This still
allows directory dev/ino numbers to change across copy-up, but otherwise keeps
them consistent.
Fixes#5545:
```
$ docker run --runtime=runsc-vfs2-overlay --rm ubuntu:focal bash -c "mkdir -p 1/2/3/4/5/6/7/8 && rm -rf 1 && echo done"
done
```
PiperOrigin-RevId: 359350716
Our implementation of vfs.CheckDeleteSticky was not consistent with Linux,
specifically not consistent with fs/linux.h:check_sticky().
One of the biggest differences was that the vfs implementation did not
allow the owner of the sticky directory to delete files inside it that belonged
to other users.
This change makes our implementation consistent with Linux.
Also adds an integration test to check for this. This bug is also present in
VFS1.
Updates #3027
PiperOrigin-RevId: 355557425