fs: stops pre-fetching the inode of dot-dot ("..") (#1544)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2023-06-29 21:00:09 +08:00
committed by GitHub
parent 9762d5b28d
commit 221ed0373a
3 changed files with 35 additions and 16 deletions

View File

@@ -745,6 +745,33 @@ yet these are returned for `wasi_snapshot_preview1.fd_readdir`. This was a
change specifically made to pass wasi-testsuite, and has problems known since
late 2019.
### Why don't we pre-populate an inode for the dot-dot ("..") entry?
We only populate an inode for dot (".") because wasi-testsuite requires it, and
we likely already have it (because we cache it). We could attempt to populate
one for dot-dot (".."), but chose not to.
Firstly, wasi-testsuite does not require the inode of dot-dot, possibly because
the wasip2 adapter doesn't populate it (but we don't really know why).
The only other reason to populate it would be to avoid wasi-libc's stat fanout
when it is missing. However, the inode for dot-dot is not cached, and is also
likely not possible to get on a pseudo file. Even if we could get it, we would
have to use stat. In other words, pre-populating this would have the same cost
as waiting for something to call stat instead.
Fetching dot-dot's inode despite the above not only doesn't help wasi-libc, but
it also hurts languages that don't use it, such as Go. These languages would
pay a stat syscall penalty even if they don't need the inode. In fact, Go
discards both dot entries!
In summary, there are no significant upsides in attempting to pre-fetch
dot-dot's inode, and there are downsides to doing it anyway.
See https://github.com/WebAssembly/wasi-libc/pull/345
See https://github.com/WebAssembly/wasi-testsuite/blob/main/tests/rust/src/bin/fd_readdir.rs#L108
See https://github.com/bytecodealliance/preview2-prototyping/blob/e4c04bcfbd11c42c27c28984948d501a3e168121/crates/wasi-preview1-component-adapter/src/lib.rs#L1037
## Why does "wasi_snapshot_preview1" require dot entries when POSIX does not?
In October 2019, WASI project knew requiring dot entries ("." and "..") was not

View File

@@ -4919,8 +4919,8 @@ func requireOpenFile(t *testing.T, tmpDir string, pathName string, data []byte,
return mod, fd, log, r
}
// Test_fdReaddir_dotEntriesHaveRealInodes because wasi-testsuite requires it.
func Test_fdReaddir_dotEntriesHaveRealInodes(t *testing.T) {
// Test_fdReaddir_dotEntryHasARealInode because wasi-testsuite requires it.
func Test_fdReaddir_dotEntryHasARealInode(t *testing.T) {
if runtime.GOOS == "windows" && !platform.IsGo120 {
t.Skip("windows before go 1.20 has trouble reading the inode information on directories.")
}
@@ -4954,11 +4954,10 @@ func Test_fdReaddir_dotEntriesHaveRealInodes(t *testing.T) {
dirents = append(dirents, 3, 0, 0, 0) // d_type = directory
dirents = append(dirents, '.') // name
// get the real inode of the parent directory
st, errno = preopen.Stat(".")
require.EqualErrno(t, 0, errno)
dirents = append(dirents, 2, 0, 0, 0, 0, 0, 0, 0) // d_next = 2
dirents = append(dirents, u64.LeBytes(st.Ino)...) // d_ino
// See /RATIONALE.md for why we don't attempt to get an inode for ".."
dirents = append(dirents, 0, 0, 0, 0, 0, 0, 0, 0) // d_ino
dirents = append(dirents, 2, 0, 0, 0) // d_namlen = 2 characters
dirents = append(dirents, 3, 0, 0, 0) // d_type = directory
dirents = append(dirents, '.', '.') // name
@@ -5021,7 +5020,8 @@ func Test_fdReaddir_opened_file_written(t *testing.T) {
st, errno = preopen.Stat(".")
require.EqualErrno(t, 0, errno)
dirents = append(dirents, 2, 0, 0, 0, 0, 0, 0, 0) // d_next = 2
dirents = append(dirents, u64.LeBytes(st.Ino)...) // d_ino
// See /RATIONALE.md for why we don't attempt to get an inode for ".."
dirents = append(dirents, 0, 0, 0, 0, 0, 0, 0, 0) // d_ino
dirents = append(dirents, 2, 0, 0, 0) // d_namlen = 2 characters
dirents = append(dirents, 3, 0, 0, 0) // d_type = directory
dirents = append(dirents, '.', '.') // name

View File

@@ -4,7 +4,6 @@ import (
"io"
"io/fs"
"net"
"path"
"syscall"
"github.com/tetratelabs/wazero/internal/descriptor"
@@ -160,15 +159,8 @@ func synthesizeDotEntries(f *FileEntry) (result []fsapi.Dirent, errno syscall.Er
return nil, errno
}
result = append(result, fsapi.Dirent{Name: ".", Ino: dotIno, Type: fs.ModeDir})
dotDotIno := uint64(0)
if !f.IsPreopen && f.Name != "." {
if st, errno := f.FS.Stat(path.Dir(f.Name)); errno != 0 {
return nil, errno
} else {
dotDotIno = st.Ino
}
}
result = append(result, fsapi.Dirent{Name: "..", Ino: dotDotIno, Type: fs.ModeDir})
// See /RATIONALE.md for why we don't attempt to get an inode for ".."
result = append(result, fsapi.Dirent{Name: "..", Ino: 0, Type: fs.ModeDir})
return result, 0
}