Subject: Re: problem with tmpfs and linux emulation?
To: Thor Lancelot Simon <tls@rek.tjls.com>
From: Michael van Elst <mlelstv@serpens.de>
List: current-users
Date: 11/13/2005 21:45:14
On Sun, Nov 13, 2005 at 12:30:15PM -0500, Thor Lancelot Simon wrote:
> On Sun, Nov 13, 2005 at 11:26:20AM +0000, Michael van Elst wrote:
> > 
> > Linux readdir() does neither of llseek or lstat64. If it did, then
> > you should see the effects also in trivial programs like 'ls'.
> > Does /emul/linux/bin/ls fail on tmpfs?
> 
> I don't think that's true.  I have trouble keeping track of which version
> of glibc does what, but see
> http://sources.redhat.com/ml/libc-alpha/2004-02/msg00013.html for one
> discussion of glibc readdir using lseek.

You are right. I checked glibc-2.3.2 and 2.3.3 (as found in Fedora3).

readdir() itself doesn't call llseek, but it calls a wrapper around
the syscall getdents/getdents64.

That wrapper tries to translate between kernel dirent structure and
glibc dirent structure. There is no translation when the structures
"look" compatible. Normally the wrapper calls getdents64() unless
there is no such syscall or getdents64() returned ENOSYS.


When calling getdents64() it checks for overflowing d_ino and d_off
fields. This can happen when the calling program is compiled for
32bit file offsets and d_ino larger than 32bit or d_off larger than
31bit.

When there is an overflow and there is at least one good entry
it llseeks() back to the previous d_off value, the next iteration
will reread the untranslatable entry and abort with EOVERFLOW.

When d_off is not a valid offset, the llseek fails and the next
iteration may or may not read more directory entries.


When calling getdents() it needs a larger buffer for the syscall
that is sized by a heuristic. The heuristic may fail, depending
on file name sizes.

When the heurstic fails it llseeks()s back to a previous d_off value,
the next iteration will reread starting from the entry that didn't
fit into the buffer.

When d_off is not a valid offset, the llseek() fails and the next
iteration continues missing some directory entries.


'ls' is compiled for 64bit fileoffsets, calls readdir64 and getdents64
without translation.

'soffice' is partially compiled for 32bit fileoffsets (libsal is
probably the culprit, other libraries are compiled for 64bit fileoffsets),
calls readdir and getdents64.


-- 
                                Michael van Elst
Internet: mlelstv@serpens.de
                                "A potential Snark may lurk in every tree."