Commit 2f0f10bb authored by Theodore Y. Ts'o's avatar Theodore Y. Ts'o Committed by Linus Torvalds

[PATCH] ext3 htree telldir() fix

telldir() is broken on large ext3 dir_index'd directories because
getdents() gives d_off==0 for the first entry

Here's a patch which fixes the problem, but note the following warning
from the readdir man page:

       According to POSIX, the dirent structure contains a field char d_name[]
       of  unspecified  size,  with  at most NAME_MAX characters preceding the
       terminating null character.  Use of other fields will harm  the  porta-
       bility  of  your  programs.

Also, as always, telldir() and seekdir() are truly awful interfaces
because they implicitly assume that (a) a directory is a linear data
structure, and (b) that the position in a directory can be expressed
in a cookie which hsa only 31 bits on 32-bit systems. 

So there will be hash colliions that will cause programs that assume
that seekdir(dirent->d_off) will always return the next directory
entry to sometimes lose directory entries in the
not-as-unlikely-as-we-would wish case of a 31-bit hash collision.
Really, any program which is using telldir/seekdir really should be
rewritten to not use these interfaces if at all possible.  So with
these caveats....


What we need to do is wire '.' and '..' to have hash values of (0,0) and
(2,0), respectively, without ignoring other existing dirents with colliding
hashes.  (In those cases the programs will break, but they are statistically
rare, and there's not much we can do in those cases anyway.)
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fd604180
...@@ -610,10 +610,14 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, ...@@ -610,10 +610,14 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
goto errout; goto errout;
count++;
}
if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
de = ext3_next_entry(de); de = ext3_next_entry(de);
if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) if ((err = ext3_htree_store_dirent(dir_file, 2, 0, de)) != 0)
goto errout; goto errout;
count += 2; count++;
} }
while (1) { while (1) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment