Workaround for AFS bug
Francois Gouget
fgouget at codeweavers.com
Wed May 25 07:13:41 CDT 2005
We got reports that Wine would go into an infinite loop on systems that
use an AFS file system. Strace logs indicated that the problem happened
in read_directory_vfat() and implicated VFAT_IOCTL_READDIR_BOTH. So I
wrote a test app which confirmed that on the user's system:
* either AFS failed to set d_reclen to 0 to signal the end of the
directory
* or AFS did not support the VFAT_IOCTL_READDIR_BOTH ioctl at all but
returned 0 (success) anyway
So this patch sets d_reclen to 0 before the ioctl() and checks whether
it's still 0 afterwards.
For reference the user's kernel was an ia32 2.6.8 kernel as found in
SUSE 9.1 and 9.2. I have checked the 2.4.26, 2.6.8 and 2.6.11.9 kernel
sources but I have not found how this could happen so I could not
produce a patch fixing the kernel.
If anyone uses AFS I would be interested if you could run the vfat_ioctl
test and let me know if it gets into an infinite loop, and which kernel
you are using.
Changelog:
* dlls/ntdll/directory.c
Francois Gouget <fgouget at codeweavers.com>
On some systems (linux 2.6.8) AFS fails to set d_reclen to 0 or does
not support VFAT_IOCTL_READDIR_BOTH but returns 0 (success) anyway. So
set d_reclen to 0 before the ioctl() and check it afterwards to work
around this bug.
--
Francois Gouget
fgouget at codeweavers.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: vfat_ioctl.c
Type: text/x-csrc
Size: 2181 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20050525/441dfc86/vfat_ioctl.c
-------------- next part --------------
Index: dlls/ntdll/directory.c
===================================================================
RCS file: /var/cvs/wine/dlls/ntdll/directory.c,v
retrieving revision 1.28
diff -u -p -r1.28 directory.c
--- dlls/ntdll/directory.c 20 May 2005 19:24:07 -0000 1.28
+++ dlls/ntdll/directory.c 25 May 2005 11:58:03 -0000
@@ -831,8 +831,11 @@ static int read_directory_vfat( int fd,
{
off_t old_pos = lseek( fd, 0, SEEK_CUR );
+ /* Set d_reclen to 0 to work around an AFS kernel bug */
+ de[0].d_reclen=0;
res = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de );
- if (res == -1 && errno != ENOENT) return -1; /* VFAT ioctl probably not supported */
+ if ((res == -1 && errno != ENOENT) || de[0].d_reclen == 0)
+ return -1; /* VFAT ioctl probably not supported */
while (res != -1)
{
@@ -859,8 +862,11 @@ static int read_directory_vfat( int fd,
}
else /* we'll only return full entries, no need to worry about overflow */
{
+ /* Set d_reclen to 0 to work around an AFS kernel bug */
+ de[0].d_reclen=0;
res = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de );
- if (res == -1 && errno != ENOENT) return -1; /* VFAT ioctl probably not supported */
+ if ((res == -1 && errno != ENOENT) || de[0].d_reclen == 0)
+ return -1; /* VFAT ioctl probably not supported */
while (res != -1)
{
@@ -1161,7 +1167,10 @@ static NTSTATUS find_file_in_dir( char *
{
KERNEL_DIRENT de[2];
- if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1)
+ /* Set d_reclen to 0 to work around an AFS kernel bug */
+ de[0].d_reclen=0;
+ if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1 &&
+ de[0].d_reclen != 0)
{
unix_name[pos - 1] = '/';
for (;;)
More information about the wine-patches
mailing list