info for discussion of syscall getdents() kern/117010

Gary Stanley gary at velocity-servers.net
Fri Feb 29 13:31:59 UTC 2008


At 03:36 AM 2/25/2008, sam wrote:
>hi all
>
>links to similar problems:
>http://mail-index.netbsd.org/current-users/2005/11/13/0011.html
>
> >  bug (+fix) in getdents + readdir
> >  o We're not sure what the Linux kernel intended to place in this field,
> >    but our experience shows that on "real" file systems (that actually
> >    reside on some disk) the offset seems to be a simple (not necessarily
> >    continuous) counter: e.g. first entry may have d_off=1, second: d_off=2,
> >    third: d_off=4096, fourth=d_off=4097 etc. We conjecture this is the
> >    serial of the dirent record within the directory (and so, this is indeed
> >    the "offset", but counted in records out of which some were already
> >    removed).
>
>
> > - In such an "overflow" situation, getdents() tries to lseek (the
> >  directory-fd) to the end of the last-legal-dirent that getdents()
> >  has successfully read.
> >  This offset is supposedly held by the local variable `last_offset'.
> >  But, since `last_offset' is assigned with `d_off' on each iteration,
> >  and since as mentioned above `d_off' usually holds an incorrect value,
> >  the lseek is not performed to the correct place.
> >  getdents() then returns the number of bytes successfully read.
I
I believe I have fixed this problem. I used a newer glibc version, 
extracted it via cpio/rpm2cpio and it fixes it. It seems the version 
of glibc that is installed with the fc6 port might have some 
regression issues, I don't have a free machine to test my theory out. 
I don't track the glibc changes, so it's rather difficult to say. 
However, I think this change might have something to do with 
(fixing?) the issue: 
http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/linux/getdents.c.diff?r1=1.22&r2=1.23&cvsroot=glibc

[root at swamp /usr/servers]# pkg_info|grep linux
linux_base-fc6-6_5  Base set of packages needed in Linux mode (for i386/amd64)

bash-3.1# uname -a
Linux swamp 2.6.16 FreeBSD 7.0-STABLE #2: Fri Feb 29 02:42:04 CST 
2008 i686 i686 i386 GNU/Linux

bash-3.1# ./hlds_run -game cstrike +ip localhost -port 29999 +exec 
server.cfg +map de_dust2
Auto detecting CPU
Using Pentium II Optimised binary.
Auto-restarting the server on crash

Console initialized.
scandir failed:/usr/servers/1.6/./valve/SAVE
scandir failed:/usr/servers/1.6/./platform/SAVE
Protocol version 47
Exe version 1.1.2.5/Stdio (cstrike)
Exe build: 20:02:49 Oct 24 2006 (3651)
STEAM Auth Server
couldn't exec language.cfg
couldn't exec listip.cfg
couldn't exec banned.cfg
Server IP address 127.0.0.1:29999
scandir failed:/usr/servers/1.6/./valve/SAVE
scandir failed:/usr/servers/1.6/./platform/SAVE
net.cpp (926) : Assertion Failed: 0 == iRet
net.cpp (928) : Assertion Failed: 0 == iRet

couldn't exec listip.cfg
couldn't exec banned.cfg
Adding master server 68.142.72.250:27010
Adding master server 72.165.61.190:27010
Connection to Steam servers successful.
VAC secure mode is activated.
status
hostname:  Counter-Strike 1.6 Server
version :  47/1.1.2.5/Stdio 3651 secure
tcp/ip  :  127.0.0.1:29999
map     :  de_dust2 at: 0 x, 0 y, 0 z
players :  0 active (6 max)


Anyway, here are some very brief instructions on how i fixed it:

"cd /compat/linux && fetch 
ftp://rpmfind.net/linux/fedora/development/x86_64/os/Packages/glibc-2.7.90-7.i386.rpm"
Then you do a simple "rpm2cpio glibc-2.7.90-7.i386.rpm | cpio -idvu"

-Gary



More information about the freebsd-emulation mailing list