Re: Fw: [POSSIBLE-BUG] telldir() broken on ext3 dir_index'd directories just after the first entry.

From: Theodore Ts'o
Date: Wed Nov 17 2004 - 17:50:08 EST


> [1.] One line summary of the problem:
> telldir() 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....

- Ted

Here is a patch which causes d_off of '.' to be 1, and for seekdir(1)
to cause readdir to return the directory entry of '..'.

Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx>

===== fs/ext3/namei.c 1.59 vs edited =====
--- 1.59/fs/ext3/namei.c 2004-10-19 05:40:30 -04:00
+++ edited/fs/ext3/namei.c 2004-11-17 17:14:06 -05:00
@@ -610,10 +610,15 @@ int ext3_htree_fill_tree(struct file *di
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++;
+ start_hash=2;
+ }
+ if (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) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/