Fix for reiserfsck mishandling hash=0
PATCH 1/1 Fix for reiserfsck mishandling hash=0
-----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-----
reiserfscore/node_formats.c +7 -3
@@ -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,
Quoted 14 lines · Jeff Mahoney
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, fromhash_value()
Quoted 7 lines
This filename has hash = 0:
G60V0AAT6HJ0000000000000001IC8TRGDUN604xDOCCM2IFN304Q~GM~M2Attached 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.
Signature · 2 lines
Thanks, Vitaly Fertman
reiserfsprogs/debugreiserfs/unpack.c +1 -2
@@ -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);
reiserfsprogs/fsck/pass0.c +1 -2
@@ -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 ) {
reiserfsprogs/fsck/pass1.c +1 -2
@@ -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 "
reiserfsprogs/include/reiserfs_lib.h +3 -1
@@ -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);
reiserfsprogs/reiserfscore/node_formats.c +4 -4
@@ -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; }
reiserfsprogs/reiserfscore/prints.c +1 -2
@@ -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)") : "??");*/ }
reiserfsprogs/reiserfscore/reiserfslib.c +17 -11
@@ -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 );