mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Read all dirents in directfs.
Earlier we were only reading upto 64*1024 bytes and assuming that was all. Lisafs uses that count to make *multiple* Getdents RPCs until it encounters EOF. But directfs was only attempting the 64*1024 read one time. The count limit is not relevant for directfs. Make that lisafs specific. Make directfs read dirents until EOF is encountered. This this change, the nodejs test parallel/test-repl-tab-complete-import passes on ubuntu-1804-lts machine now. PiperOrigin-RevId: 532522376
This commit is contained in:
@@ -379,12 +379,12 @@ func (d *dentry) openCreate(ctx context.Context, name string, accessFlags uint32
|
||||
// - d.isDir().
|
||||
// - d.handleMu must be locked.
|
||||
// - !d.isSynthetic().
|
||||
func (d *dentry) getDirentsLocked(ctx context.Context, count int, recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
func (d *dentry) getDirentsLocked(ctx context.Context, recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
switch dt := d.impl.(type) {
|
||||
case *lisafsDentry:
|
||||
return dt.getDirentsLocked(ctx, count, recordDirent)
|
||||
return dt.getDirentsLocked(ctx, recordDirent)
|
||||
case *directfsDentry:
|
||||
return dt.getDirentsLocked(count, recordDirent)
|
||||
return dt.getDirentsLocked(recordDirent)
|
||||
default:
|
||||
panic("unknown dentry implementation")
|
||||
}
|
||||
|
||||
@@ -558,27 +558,16 @@ func (d *directfsDentry) openCreate(name string, accessFlags uint32, mode linux.
|
||||
return child, handle{fd: int32(childHandleFD)}, nil
|
||||
}
|
||||
|
||||
func (d *directfsDentry) getDirentsLocked(count int, recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
func (d *directfsDentry) getDirentsLocked(recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
readFD := int(d.readFD.RacyLoad())
|
||||
if _, err := unix.Seek(readFD, 0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var direntsBuf [8192]byte
|
||||
for bytesRead := 0; bytesRead < count; {
|
||||
bufEnd := len(direntsBuf)
|
||||
if remaining := int(count) - bytesRead; remaining < bufEnd {
|
||||
bufEnd = remaining
|
||||
}
|
||||
n, err := unix.Getdents(readFD, direntsBuf[:bufEnd])
|
||||
for {
|
||||
n, err := unix.Getdents(readFD, direntsBuf[:])
|
||||
if err != nil {
|
||||
if err == unix.EINVAL && bufEnd < fsutil.UnixDirentMaxSize {
|
||||
// getdents64(2) returns EINVAL is returned when the result
|
||||
// buffer is too small. If bufEnd is smaller than the max
|
||||
// size of unix.Dirent, then just break here to return all
|
||||
// dirents collected till now.
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if n <= 0 {
|
||||
@@ -594,12 +583,10 @@ func (d *directfsDentry) getDirentsLocked(count int, recordDirent func(name stri
|
||||
log.Warningf("Getdent64: skipping file %q with failed stat, err: %v", path.Join(genericDebugPathname(&d.dentry), name), err)
|
||||
return true
|
||||
}
|
||||
bytesRead += int(reclen)
|
||||
recordDirent(name, inoKeyFromStat(&stat), ftype)
|
||||
return true
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Precondition: fs.renameMu is locked.
|
||||
|
||||
@@ -272,8 +272,7 @@ func (d *dentry) getDirents(ctx context.Context) ([]vfs.Dirent, error) {
|
||||
// have been opened when the calling directoryFD was opened.
|
||||
panic("gofer.dentry.getDirents called without a readable handle")
|
||||
}
|
||||
const count = 64 * 1024 // for consistency with the vfs1 client
|
||||
err := d.getDirentsLocked(ctx, count, func(name string, key inoKey, dType uint8) {
|
||||
err := d.getDirentsLocked(ctx, func(name string, key inoKey, dType uint8) {
|
||||
dirent := vfs.Dirent{
|
||||
Name: name,
|
||||
Ino: d.fs.inoFromKey(key),
|
||||
|
||||
@@ -462,20 +462,24 @@ func (d *lisafsDentry) openCreate(ctx context.Context, name string, flags uint32
|
||||
return child, h, nil
|
||||
}
|
||||
|
||||
// lisafsGetdentsCount is the number of bytes of dirents to read from the
|
||||
// server in each Getdents RPC. This value is consistent with vfs1 client.
|
||||
const lisafsGetdentsCount = int32(64 * 1024)
|
||||
|
||||
// Preconditions:
|
||||
// - getDirents may not be called concurrently with another getDirents call.
|
||||
func (d *lisafsDentry) getDirentsLocked(ctx context.Context, count int, recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
func (d *lisafsDentry) getDirentsLocked(ctx context.Context, recordDirent func(name string, key inoKey, dType uint8)) error {
|
||||
// shouldSeek0 indicates whether the server should SEEK to 0 before reading
|
||||
// directory entries.
|
||||
shouldSeek0 := true
|
||||
for {
|
||||
countLisa := int32(count)
|
||||
count := lisafsGetdentsCount
|
||||
if shouldSeek0 {
|
||||
// See lisafs.Getdents64Req.Count.
|
||||
countLisa = -countLisa
|
||||
count = -count
|
||||
shouldSeek0 = false
|
||||
}
|
||||
dirents, err := d.readFDLisa.Getdents64(ctx, countLisa)
|
||||
dirents, err := d.readFDLisa.Getdents64(ctx, count)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user