* [PATCH] Fix for reiserfsck mishandling hash=0
@ 2004-09-15 13:52 Jeff Mahoney
2004-09-16 12:35 ` Vitaly Fertman
0 siblings, 1 reply; 2+ messages in thread
From: Jeff Mahoney @ 2004-09-15 13:52 UTC (permalink / raw)
To: ReiserFS List
[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hey all -
When reiserfsck traverses the tree looking for errors, one of the checks
it performs is to see if the hash on disk matches the expected hash,
computed from the filename.
However, the handling of hash = 0 is broken in reiserfsck. In the
kernel, hash = 0 is considered special and is adjusted to 0x80.
reiserfsck doesn't perform this adjustment, and yields fatal errors with
~ instructions to use --rebuild-tree, even though no such error exists.
reiserfs_add_entry() in the semantic rebuild uses the correct
adjustment, from hash_value()
This filename has hash = 0:
G60V0AAT6HJ0000000000000001IC8TRGDUN604xDOCCM2IFN304Q~GM~M2
Attached is a patch to good_name(), allowing reiserfsprogs to properly
handle filenames with hash = 0.
Please apply.
- -Jeff
- --
Jeff Mahoney
SuSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFBSEkULPWxlyuTD7IRAouvAKCaPDwiKW47iUD9zkBOtdCsLpofywCfXZNX
5v0/2Z1LB+EYRFNrByTRJDI=
=K18H
-----END PGP SIGNATURE-----
[-- Attachment #2: reiserfsprogs-hash0.diff --]
[-- Type: text/plain, Size: 974 bytes --]
diff -rup reiserfsprogs-3.6.18/reiserfscore/node_formats.c reiserfsprogs-3.6.18.devel/reiserfscore/node_formats.c
--- reiserfsprogs-3.6.18/reiserfscore/node_formats.c 2004-05-28 07:42:43.000000000 -0400
+++ reiserfsprogs-3.6.18.devel/reiserfscore/node_formats.c 2004-09-15 09:05:16.681478544 -0400
@@ -527,9 +527,13 @@ int known_hashes (void)
}
-#define good_name(hashfn,name,namelen,deh_offset) \
-(GET_HASH_VALUE ((hashfn) (name, namelen)) == GET_HASH_VALUE (deh_offset))
-
+#define good_name(hashfn,name,namelen,deh_offset) \
+({ \
+ __u32 __x = (GET_HASH_VALUE ((hashfn) (name, namelen))); \
+ if (__x == 0) \
+ __x = 128; \
+ __x == GET_HASH_VALUE (deh_offset); \
+})
/* this also sets hash function */
int is_properly_hashed (reiserfs_filsys_t * fs,
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] Fix for reiserfsck mishandling hash=0
2004-09-15 13:52 [PATCH] Fix for reiserfsck mishandling hash=0 Jeff Mahoney
@ 2004-09-16 12:35 ` Vitaly Fertman
0 siblings, 0 replies; 2+ messages in thread
From: Vitaly Fertman @ 2004-09-16 12:35 UTC (permalink / raw)
To: Jeff Mahoney, ReiserFS List
[-- Attachment #1: Type: text/plain, Size: 998 bytes --]
On Wednesday 15 September 2004 17:52, Jeff Mahoney wrote:
> Hey all -
>
> When reiserfsck traverses the tree looking for errors, one of the checks
> it performs is to see if the hash on disk matches the expected hash,
> computed from the filename.
>
> However, the handling of hash = 0 is broken in reiserfsck. In the
> kernel, hash = 0 is considered special and is adjusted to 0x80.
> reiserfsck doesn't perform this adjustment, and yields fatal errors with
> ~ instructions to use --rebuild-tree, even though no such error exists.
>
> reiserfs_add_entry() in the semantic rebuild uses the correct
> adjustment, from hash_value()
>
> This filename has hash = 0:
> G60V0AAT6HJ0000000000000001IC8TRGDUN604xDOCCM2IFN304Q~GM~M2
>
> Attached is a patch to good_name(), allowing reiserfsprogs to properly
> handle filenames with hash = 0.
>
> Please apply.
Thank you for hitting the bug. The problem seems a bit larger,
the attached patch fixes rebuild-tree behaviour also.
--
Thanks,
Vitaly Fertman
[-- Attachment #2: reiserfsprogs_hash.patch --]
[-- Type: text/x-diff, Size: 7181 bytes --]
diff -Nru a/reiserfsprogs/debugreiserfs/unpack.c b/reiserfsprogs/debugreiserfs/unpack.c
--- a/reiserfsprogs/debugreiserfs/unpack.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/debugreiserfs/unpack.c Thu Sep 16 16:14:40 2004
@@ -128,8 +128,7 @@
/* old or new ".." */
set_deh_offset (deh, DOT_DOT_OFFSET);
else if (hash_func)
- set_deh_offset (deh, GET_HASH_VALUE (hash_func (item + location,
- namelen)));
+ set_deh_offset (deh, hash_value(hash_func, item + location, namelen));
if (mask & HAS_GEN_COUNTER) {
fread_le16 (&gen_counter);
set_deh_offset (deh, get_deh_offset (deh) | gen_counter);
diff -Nru a/reiserfsprogs/fsck/pass0.c b/reiserfsprogs/fsck/pass0.c
--- a/reiserfsprogs/fsck/pass0.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/fsck/pass0.c Thu Sep 16 16:14:40 2004
@@ -365,8 +365,7 @@
hash_code = 0;
for (j = min_length; j <= max_length; j ++) {
- hash_code = find_hash_in_use (name, j,
- GET_HASH_VALUE (get_deh_offset (deh + i)),
+ hash_code = find_hash_in_use (name, j, get_deh_offset (deh + i),
get_sb_hash_code (fs->fs_ondisk_sb));
/* add_hash_hit (fs, hash_code);*/
if (code2func (hash_code) != 0) {
diff -Nru a/reiserfsprogs/fsck/pass1.c b/reiserfsprogs/fsck/pass1.c
--- a/reiserfsprogs/fsck/pass1.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/fsck/pass1.c Thu Sep 16 16:14:40 2004
@@ -363,8 +363,7 @@
continue;
}
- hash_code = find_hash_in_use (name, name_len,
- GET_HASH_VALUE (get_deh_offset (deh + j)),
+ hash_code = find_hash_in_use (name, name_len, get_deh_offset (deh + j),
get_sb_hash_code (fs->fs_ondisk_sb));
if (hash_code != get_sb_hash_code (fs->fs_ondisk_sb)) {
fsck_log ("pass1: block %lu, item %d, entry %d: The entry \"%.*s\" of the %k is hashed with %s "
diff -Nru a/reiserfsprogs/include/reiserfs_lib.h b/reiserfsprogs/include/reiserfs_lib.h
--- a/reiserfsprogs/include/reiserfs_lib.h Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/include/reiserfs_lib.h Thu Sep 16 16:14:40 2004
@@ -135,6 +135,8 @@
int comp_short_keys (const void * p_s_key1, const void * p_s_key2);
int comp_items (struct item_head * p_s_ih, struct path * p_s_path);
+__u32 hash_value (hashf_t func, char * name, int namelen);
+
int create_dir_sd (reiserfs_filsys_t * fs,
struct path * path, struct key * key,
void (*modify_item)(struct item_head *, void *));
@@ -279,7 +281,7 @@
int func2code (hashf_t func);
hashf_t code2func (unsigned int code);
hashf_t name2func (char * hash);
-int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, unsigned int code_to_try_first);
+int find_hash_in_use (char * name, int namelen, __u32 deh_offset, unsigned int code_to_try_first);
int entry_length (struct item_head * ih, struct reiserfs_de_head * deh,
int pos_in_item);
diff -Nru a/reiserfsprogs/reiserfscore/node_formats.c b/reiserfsprogs/reiserfscore/node_formats.c
--- a/reiserfsprogs/reiserfscore/node_formats.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/reiserfscore/node_formats.c Thu Sep 16 16:14:40 2004
@@ -528,7 +528,7 @@
#define good_name(hashfn,name,namelen,deh_offset) \
-(GET_HASH_VALUE ((hashfn) (name, namelen)) == GET_HASH_VALUE (deh_offset))
+(hash_value (hashfn, name, namelen) == GET_HASH_VALUE (deh_offset))
/* this also sets hash function */
@@ -579,7 +579,7 @@
}
-int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, unsigned int code_to_try_first)
+int find_hash_in_use (char * name, int namelen, __u32 offset, unsigned int code_to_try_first)
{
unsigned int i;
@@ -587,14 +587,14 @@
return UNSET_HASH;
if (code_to_try_first) {
- if (hash_value_masked == GET_HASH_VALUE (hashes [code_to_try_first].func (name, namelen)))
+ if (good_name (hashes [code_to_try_first].func, name, namelen, offset))
return code_to_try_first;
}
for (i = 1; i < HASH_AMOUNT; i ++) {
if (i == code_to_try_first)
continue;
- if (hash_value_masked == GET_HASH_VALUE (hashes [i].func (name, namelen)))
+ if (good_name (hashes [i].func, name, namelen, offset))
return i;
}
diff -Nru a/reiserfsprogs/reiserfscore/prints.c b/reiserfsprogs/reiserfscore/prints.c
--- a/reiserfsprogs/reiserfscore/prints.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/reiserfscore/prints.c Thu Sep 16 16:14:40 2004
@@ -332,8 +332,7 @@
GET_HASH_VALUE (get_deh_offset (deh)),
GET_GENERATION_NUMBER (get_deh_offset (deh)),
get_deh_location (deh), get_deh_state (deh),
- code2name (find_hash_in_use (name, namelen,
- GET_HASH_VALUE (get_deh_offset (deh)),
+ code2name (find_hash_in_use (name, namelen, get_deh_offset (deh),
fs ? get_sb_hash_code (fs->fs_ondisk_sb) : UNSET_HASH)));
/*fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??");*/
}
diff -Nru a/reiserfsprogs/reiserfscore/reiserfslib.c b/reiserfsprogs/reiserfscore/reiserfslib.c
--- a/reiserfsprogs/reiserfscore/reiserfslib.c Thu Sep 16 16:14:40 2004
+++ b/reiserfsprogs/reiserfscore/reiserfslib.c Thu Sep 16 16:14:40 2004
@@ -839,16 +839,11 @@
/*===========================================================================*/
-static __u32 hash_value (reiserfs_filsys_t * fs, char * name)
+__u32 hash_value (hashf_t func, char * name, int namelen)
{
__u32 res;
- if (!strcmp (name, "."))
- return DOT_OFFSET;
- if (!strcmp (name, ".."))
- return DOT_DOT_OFFSET;
-
- res = reiserfs_hash (fs) (name, strlen (name));
+ res = func (name, namelen);
res = GET_HASH_VALUE(res);
if (res == 0)
res = 128;
@@ -871,7 +866,12 @@
set_key_dirid (&entry_key, get_key_dirid (dir));
set_key_objectid (&entry_key, get_key_objectid (dir));
- hash = hash_value (fs, name);
+ if (!strcmp (name, "."))
+ hash = DOT_OFFSET;
+ else if (!strcmp (name, ".."))
+ hash = DOT_DOT_OFFSET;
+ else
+ hash = hash_value (reiserfs_hash (fs), name, strlen (name));
set_key_offset_v1 (&entry_key, hash);
set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS);
@@ -948,7 +948,12 @@
set_key_dirid (&entry_key, get_key_dirid (dir));
set_key_objectid (&entry_key, get_key_objectid (dir));
- hash = hash_value (fs, name);
+ if (!strcmp (name, "."))
+ hash = DOT_OFFSET;
+ else if (!strcmp (name, ".."))
+ hash = DOT_DOT_OFFSET;
+ else
+ hash = hash_value (reiserfs_hash (fs), name, strlen (name));
set_key_offset_v1 (&entry_key, hash);
set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS);
@@ -1060,11 +1065,12 @@
/* compose entry key to look for its place in the tree */
set_key_dirid (&(entry_ih.ih_key), get_key_dirid (dir));
set_key_objectid (&(entry_ih.ih_key), get_key_objectid (dir));
- hash = hash_value (fs, name) + gen_counter;
if (!strcmp (name, "."))
hash = DOT_OFFSET;
- if (!strcmp (name, ".."))
+ else if (!strcmp (name, ".."))
hash = DOT_DOT_OFFSET;
+ else
+ hash = hash_value (reiserfs_hash (fs), name, strlen (name)) + gen_counter;
set_key_offset_v1 (&(entry_ih.ih_key), hash);
set_key_uniqueness (&(entry_ih.ih_key), DIRENTRY_UNIQUENESS);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-09-16 12:35 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-15 13:52 [PATCH] Fix for reiserfsck mishandling hash=0 Jeff Mahoney
2004-09-16 12:35 ` Vitaly Fertman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.