Bug 1577640

Summary: getdents on cifs with 4k buffer loses files
Product: Red Hat Enterprise Linux 7 Reporter: Achilles Gaikwad <agaikwad>
Component: kernelAssignee: Ronnie Sahlberg <lsahlber>
kernel sub component: CIFS QA Contact: xiaoli feng <xifeng>
Status: CLOSED ERRATA Docs Contact:
Severity: medium    
Priority: medium CC: agaikwad, chlunde, dwysocha, fsorenso, ikent, jshivers, lsahlber, swhiteho, xzhou
Version: 7.5Keywords: Patch, Reproducer
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: kernel-3.10.0-1025.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-08-06 12:12:17 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1577173    
Attachments:
Description Flags
C program which calls the syscall getdents64 with the given buffer size none

Description Achilles Gaikwad 2018-05-13 17:00:18 UTC
Created attachment 1435776 [details]
C program which calls the syscall getdents64 with the given buffer size

Description of problem:
When a program written in Go is listing directory contents in a CIFS mount with many files, the Linux kernel misses some files. When we increase the buffer size for getdents we get a proper listing and no files are lost. 


Version-Release number of selected component (if applicable):
3.10.0-862.el7.x86_64

golang-src-1.9.4-1.el7.noarch
cifs-utils-6.2-10.el7.x86_64
golang-1.9.4-1.el7.x86_64
golang-bin-1.9.4-1.el7.x86_64

How reproducible:
Always 


Steps to Reproduce:
1. mount -t cifs //cifs-server/cifs /mnt 
2. touch /mnt/{1..1000}
3. ls -la /mnt | wc -l 
4. go run man.go /mnt
5. ./man.o 4096 /mnt 


Actual results:

# ls -la /mnt | wc -l 
1003


# go run man.go /mnt
996

# ./getdents_ls 4096 /cifs | tail -n 1 
Found 996 entries

Expected results:

# ls -la /mnt | wc -l 
1003


# go run man.go /mnt
1002

# ./getdents_ls 4096 /cifs | tail -n 1 
Found 1002 entries

Additional info:

I've attached the c program, 


C program. 
----------
 # gcc -Wall getdents_ls.c -o getdents_ls
 # getdents_ls [<buf_size> [<path>]]


GO program. 
----------

 # cat man.go 

package main

import (
        "fmt"
        "os"
)

func main() {
        f, err := os.Open(os.Args[1])
        if err != nil {
                panic(err)
        }
        names, err := f.Readdirnames(-1)
        if err != nil {
                panic(err)
        }
        fmt.Printf("%d\n", len(names)+2 /* ., .. */)
}

 # go run man.go [<path>]]


github issue for more information:  https://github.com/golang/go/issues/24015#issuecomment-369719030

Comment 2 Frank Sorenson 2018-05-14 01:28:02 UTC
issue does not reproduce on rhel6 or upstream kernel

Comment 11 Bruno Meneguele 2019-03-15 19:18:12 UTC
Patch(es) committed on kernel-3.10.0-1025.el7

Comment 16 errata-xmlrpc 2019-08-06 12:12:17 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHSA-2019:2029