aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Y. Ts'o <tytso@mit.edu>2005-01-07 21:42:57 -0800
committerLinus Torvalds <torvalds@evo.osdl.org>2005-01-07 21:42:57 -0800
commit2f0f10bb16dcc550feee88cab0fb5a2257688e59 (patch)
tree45eb64dbbbb6d73433a5dec3b85855a931fb9505 /fs
parentfd604180c07f26beaaa7efc84ca74bf87a152b9e (diff)
downloadhistory-2f0f10bb16dcc550feee88cab0fb5a2257688e59.tar.gz
[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: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext3/namei.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index c5ba3ffc2aa10a..4df04e4bd88e61 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -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;
if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
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);
- 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;
- count += 2;
+ count++;
}
while (1) {