This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: getdents64 problem


On Fri, Jan 19, 2001 at 11:25:30AM +0100, Andreas Jaeger wrote:
> 
> There was yesterday a thread on linux kernel with subject "nfs client
> problem in kernel 2.4.0" which noticed some problems with our getdents
> implementation.
> 
> Is the following patch ok?  Mogens, does it fix the problems you
> noticed?

At least my understanding was that the problem is the opposite of what
you're doing here:
last kernel_dirent64 entry given from kernel is
{ ?, 0xffffffffULL, ?, ?, ? }
and thus
(sizeof (dp->d_off) != sizeof (kdp->d_off) && dp->d_off != d_off) 
check fails (it would succeed if kernel gave { ?, -1LL, ?, ?, ? } instead),
which means (as last_offset != -1 at that point) that we just seek before
this entry and return. On next getdents call, we read
{ ?, 0xffffffffULL, ?, ?, ? }
once again and as last_offset is now -1 (no matter what your patch does), we
return EOVERFLOW since we were not able to convert the last entry into
struct dirent (4GB-1 does not fit into <-2GB,2GB-1> range).
So, I think this is a kernel bug which glibc cannot do anything about
(silently accepting d_off which would not fit would be IMHO a bad thing).

> 
> 2001-01-19  Andreas Jaeger  <aj@suse.de>
> 
> 	* sysdeps/unix/sysv/linux/getdents.c (__GETDENTS): Make 64 bit
> 	clean.
> 
> ============================================================
> Index: sysdeps/unix/sysv/linux/getdents.c
> --- sysdeps/unix/sysv/linux/getdents.c	2000/11/30 17:41:56	1.15
> +++ sysdeps/unix/sysv/linux/getdents.c	2001/01/19 10:24:24
> @@ -1,4 +1,4 @@
> -/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
> +/* Copyright (C) 1993,95,96,97,98,99,2000,2001 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>  
>     The GNU C Library is free software; you can redistribute it and/or
> @@ -98,7 +98,7 @@
>  __GETDENTS (int fd, char *buf, size_t nbytes)
>  {
>    DIRENT_TYPE *dp;
> -  off_t last_offset = -1;
> +  off64_t last_offset = -1;
>    ssize_t retval;
>  
>  #ifdef __NR_getdents64
> @@ -164,7 +164,7 @@
>  		     otherwise signal overflow.  */
>  		  if (last_offset != -1)
>  		    {
> -		      __lseek (fd, last_offset, SEEK_SET);
> +		      __lseek64 (fd, last_offset, SEEK_SET);
>  		      return (char *) dp - buf;
>  		    }
>  		  __set_errno (EOVERFLOW);

	Jakub

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]