xfs
[Top] [All Lists]

Re: files disappearing?

To: Kip Macy <kmacy@xxxxxxxxxxxxxxx>
Subject: Re: files disappearing?
From: Steve Lord <lord@xxxxxxx>
Date: Wed, 12 Apr 2000 09:11:15 -0500
Cc: linux-xfs@xxxxxxxxxxx
In-reply-to: Message from Kip Macy <kmacy@xxxxxxxxxxxxxxx> of "Wed, 12 Apr 2000 00:33:38 PDT." <Pine.SOL.4.10.10004120025170.17488-100000@xxxxxxxxxxxxxxxxxxxxxx>
Sender: owner-linux-xfs@xxxxxxxxxxx
> When I do a cvs checkout of the source tree in an ext2fs partition and cd to 
> linux-2.3-xfs/linux 
> > ls -lR | grep .c | wc
>    5510   44454  337781
> > ls -lR | grep .h | wc
>   4114   34458  256249
> 
> When I do a cvs checkout of the source tree in an xfs partition and cd to
> linux-2.3-xfs/linux
> > ls -lR | grep .h | wc
> not only do I get fewer files but I also get stuff like the following
> 
> ls: ./net/core/ Intel I810/I810 DC100/I810e sup: No such file or directory
> ls: ./net/core/_I810
>       bool '  VIA chipset support' CONFIG_AGP_VIA
>       bool '  AMD Ironga: No such file or directory
> ls: ./net/core/IG_AGP_AMD
>       bool '  Generic SiS support' CONFIG_AGP_SIS
>       boo: No such file or directory
> ls: ./net/core/port' CONFIG_AGP_ALI
>    fi
> fi
> endmenu
> : No such file or directory
> 
> 
> 

There is a problem in the directory code and the way it interacts with the
glibc getdents code - glibc uses a different size dirent structure from that
returned by the kernel, which results in occasions when there are entries
returned by the kernel which will not fit in the user's buffer. In this case
glibc does an lseek backwards to reobtain these entries. The handling of
this lseek call appears to result in an entry getting skipped.

This should show up in directories with a fairly large number of entries
and an average name length of 12 or more characters (I think). 

While this sounds simple to fix it does not appear to be, the lseek offsets
returned by xfs are not real offsets, they attempt to represent a location
into a b+ tree of directory blocks. I have a simple workaround which seems
to make getdents work - but it may confuse other parts of the system.

Try making this change to linux/fs/xfs/xfs_dir2_leaf.c and see what happens:

*** /usr/tmp/TmpDir.3736-0/linux/fs/xfs/xfs_dir2_leaf.c_1.11    Wed Apr 12 
07:43:52 2000
--- linux/fs/xfs/xfs_dir2_leaf.c        Wed Apr 12 08:44:46 2000
***************
*** 1164,1170 ****
                dep = (xfs_dir2_data_entry_t *)ptr;
                p.namelen = dep->namelen;
                length = XFS_DIR2_DATA_ENTSIZE(p.namelen);
!               p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
  #if XFS_BIG_FILESYSTEMS
                p.ino = INT_GET(dep->inumber, ARCH_UNKNOWN) + mp->m_inoadd;
  #else
--- 1164,1170 ----
                dep = (xfs_dir2_data_entry_t *)ptr;
                p.namelen = dep->namelen;
                length = XFS_DIR2_DATA_ENTSIZE(p.namelen);
!               p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
  #if XFS_BIG_FILESYSTEMS
                p.ino = INT_GET(dep->inumber, ARCH_UNKNOWN) + mp->m_inoadd;
  #else


-----------------------------------

I should stress that this is an incorrect fix in that, according to the code,
it is making the d_off field in the getdents structure point at this entry
in the directory, not the next one as it should.

Hopefully we can come up with a correct fix soon.

Steve



<Prev in Thread] Current Thread [Next in Thread>