Commit 699155e3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] htree nfs fix

Patch from "Theodore Ts'o" <tytso@mit.edu>

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.
parent 7c6d1fb9
...@@ -439,7 +439,7 @@ static int ext3_dx_readdir(struct file * filp, ...@@ -439,7 +439,7 @@ static int ext3_dx_readdir(struct file * filp,
filp->private_data = info; filp->private_data = info;
} }
if (filp->f_pos == -1) if (filp->f_pos == EXT3_HTREE_EOF)
return 0; /* EOF */ return 0; /* EOF */
/* Some one has messed with f_pos; reset the world */ /* Some one has messed with f_pos; reset the world */
...@@ -479,7 +479,7 @@ static int ext3_dx_readdir(struct file * filp, ...@@ -479,7 +479,7 @@ static int ext3_dx_readdir(struct file * filp,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret == 0) { if (ret == 0) {
filp->f_pos = -1; filp->f_pos = EXT3_HTREE_EOF;
break; break;
} }
info->curr_node = rb_first(&info->root); info->curr_node = rb_first(&info->root);
...@@ -494,7 +494,7 @@ static int ext3_dx_readdir(struct file * filp, ...@@ -494,7 +494,7 @@ static int ext3_dx_readdir(struct file * filp,
info->curr_node = rb_next(info->curr_node); info->curr_node = rb_next(info->curr_node);
if (!info->curr_node) { if (!info->curr_node) {
if (info->next_hash == ~0) { if (info->next_hash == ~0) {
filp->f_pos = -1; filp->f_pos = EXT3_HTREE_EOF;
break; break;
} }
info->curr_hash = info->next_hash; info->curr_hash = info->next_hash;
......
...@@ -209,7 +209,10 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) ...@@ -209,7 +209,10 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
hinfo->hash = 0; hinfo->hash = 0;
return -1; 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; hinfo->minor_hash = minor_hash;
return 0; return 0;
} }
...@@ -625,6 +625,8 @@ struct dx_hash_info ...@@ -625,6 +625,8 @@ struct dx_hash_info
u32 *seed; u32 *seed;
}; };
#define EXT3_HTREE_EOF 0x7fffffff
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*
* Control parameters used by ext3_htree_next_block * Control parameters used by ext3_htree_next_block
......
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