Patch from "Theodore Ts'o" We now use 0x7ffffff as the EOF cookie, because Linux NFS stupidly interprets the cookie (which is supposed to be a bag of bits without necessarily any semantic value) as a signed 64 bit integer, and then converts it to a unsigned integer, and then blows up if it cannot be expressed be expressed as a 32-bit value!! In order to do this, we have to fold the hash value 0x7ffffff into the hash value 0x7ffffffe. This is relatively safe; the only time we will lose if the directory contains filenames that hash to both 0x7ffffffe and 0x7fffffff (under the original hash), and the last directory entry which hashes to 0x7ffffffe is at the end of a leaf block, and the first directory entry which hashes to 0x7fffffff is at the beginning of a leaf block. fs/ext3/dir.c | 6 +++--- fs/ext3/hash.c | 5 ++++- include/linux/ext3_fs.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff -puN fs/ext3/dir.c~htree-nfs-fix-2 fs/ext3/dir.c --- 25/fs/ext3/dir.c~htree-nfs-fix-2 2003-03-13 04:43:11.000000000 -0800 +++ 25-akpm/fs/ext3/dir.c 2003-03-13 04:43:11.000000000 -0800 @@ -439,7 +439,7 @@ static int ext3_dx_readdir(struct file * filp->private_data = info; } - if (filp->f_pos == -1) + if (filp->f_pos == EXT3_HTREE_EOF) return 0; /* EOF */ /* Some one has messed with f_pos; reset the world */ @@ -479,7 +479,7 @@ static int ext3_dx_readdir(struct file * if (ret < 0) return ret; if (ret == 0) { - filp->f_pos = -1; + filp->f_pos = EXT3_HTREE_EOF; break; } info->curr_node = rb_first(&info->root); @@ -494,7 +494,7 @@ static int ext3_dx_readdir(struct file * info->curr_node = rb_next(info->curr_node); if (!info->curr_node) { if (info->next_hash == ~0) { - filp->f_pos = -1; + filp->f_pos = EXT3_HTREE_EOF; break; } info->curr_hash = info->next_hash; diff -puN fs/ext3/hash.c~htree-nfs-fix-2 fs/ext3/hash.c --- 25/fs/ext3/hash.c~htree-nfs-fix-2 2003-03-13 04:43:11.000000000 -0800 +++ 25-akpm/fs/ext3/hash.c 2003-03-13 04:43:11.000000000 -0800 @@ -209,7 +209,10 @@ int ext3fs_dirhash(const char *name, int hinfo->hash = 0; return -1; } - hinfo->hash = hash & ~1; + hash = hash & ~1; + if (hash == (EXT3_HTREE_EOF << 1)) + hash = (EXT3_HTREE_EOF-1) << 1; + hinfo->hash = hash; hinfo->minor_hash = minor_hash; return 0; } diff -puN include/linux/ext3_fs.h~htree-nfs-fix-2 include/linux/ext3_fs.h --- 25/include/linux/ext3_fs.h~htree-nfs-fix-2 2003-03-13 04:43:11.000000000 -0800 +++ 25-akpm/include/linux/ext3_fs.h 2003-03-13 04:43:11.000000000 -0800 @@ -625,6 +625,8 @@ struct dx_hash_info u32 *seed; }; +#define EXT3_HTREE_EOF 0x7fffffff + #ifdef __KERNEL__ /* * Control parameters used by ext3_htree_next_block _