Re: DCACHE Pinning Problems with rm -r on 2.2.15/2.3.99Pre3 withNWFS2.2.2

From: Jamie Lokier (lk@tantalophile.demon.co.uk)
Date: Wed Apr 05 2000 - 01:51:10 EST


Stephen C. Tweedie wrote:
> > Which is unfortunate because the computed LSEEK_CUR appears in Glibc's
> > readdir(). It's a corner case. To remove the LSEEK_CUR, unfortunately
> > you have to use another syscall in the normal case.
>
> What is the problem? You just cannot assume that the pointer
> progresses in a nice, arithmetic patter in directories. If you are
> at lseek() point P and read Q bytes, you are not going to end up
> at P+Q: the actual file location you end up at depends on how much
> padding there was in the directory and how much extra filesystem
> metadata was there that didn't get returned to user space.

Glibc assumes you end up at P+Q, so it is broken. It's a corner
case that won't have shown up in tests. Here's the code from
glibc-2.1-990920/sysdeps/unix/sysv/linux/getdents.c:

  retval = INLINE_SYSCALL (getdents, 3, fd, (char *) kdp, red_nbytes);

  if (retval == -1)
    return -1;

  while ((char *) kdp < (char *) skdp + retval)
    {
      const size_t alignment = __alignof__ (struct dirent);
      /* Since kdp->d_reclen is already aligned for the kernel structure
         this may compute a value that is bigger than necessary. */
      size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
                           & ~(alignment - 1));
      if ((char *) dp + new_reclen > buf + nbytes)
        {
          /* Our heuristic failed. We read too many entries. Reset
             the stream. `last_offset' contains the last known
             position. If it is zero this is the first record we are
             reading. In this case do a relative search. */
          if (last_offset == 0)
            __lseek (fd, -retval, SEEK_CUR);
          else
            __lseek (fd, last_offset, SEEK_SET);
          break;
        }

      last_offset = kdp->d_off;

Ironically, an older Glibc did this right and it was changed as an
optimisation.

-- Jamie

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Apr 07 2000 - 21:00:14 EST