Don't just loop indefinitely when an obfuscated name comes up as a duplicate. Count the number of times we've found a duplicate and if if it gets excessive despite choosing names at random, just give up and use the original name without obfuscation. Technically, a typical 5-character name has 255 other names that can have the same hash value. But the algorithm doesn't hit all possible names (far from it) so duplicates are still possible. Signed-off-by: Alex Elder <aelder@xxxxxxx> The only change worth mentioning from the last version posted is that the duplicate count is now updated inside the loop that searches the name table. --- db/metadump.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) Index: b/db/metadump.c =================================================================== --- a/db/metadump.c +++ b/db/metadump.c @@ -29,6 +29,14 @@ #define DEFAULT_MAX_EXT_SIZE 1000 +/* + * It's possible that multiple files in a directory (or attributes + * in a file) produce the same obfuscated name. If that happens, we + * try to create another one. After several rounds of this though, + * we just give up and leave the original name as-is. + */ +#define DUP_MAX 5 /* Max duplicates before we give up */ + /* copy all metadata structures to/from a file */ static int metadump_f(int argc, char **argv); @@ -437,8 +445,9 @@ generate_obfuscated_name( { xfs_dahash_t hash; name_ent_t *p; - int dup; + int dup = 0; uchar_t newname[NAME_MAX]; + uchar_t *newp; /* * Our obfuscation algorithm requires at least 5-character @@ -471,19 +480,17 @@ generate_obfuscated_name( do { int i; xfs_dahash_t newhash = 0; - uchar_t *newp = &newname[0]; uchar_t *first; uchar_t high_bit; int shift; - dup = 0; - /* * The beginning of the obfuscated name can be * pretty much anything, so fill it in with random * characters. Accumulate its new hash value as we * go. */ + newp = &newname[0]; for (i = 0; i < namelen - 5; i++) { *newp = random_filename_char(); newhash = *newp ^ rol32(newhash, 7); @@ -531,14 +538,22 @@ generate_obfuscated_name( ASSERT(libxfs_da_hashname(newname, namelen) == hash); + /* + * Search the name table to be sure we don't produce + * a name that's already been used. + */ for (p = nametable[hash % NAME_TABLE_SIZE]; p; p = p->next) { if (p->hash == hash && p->namelen == namelen && !memcmp(p->name, newname, namelen)) { - dup = 1; + dup++; break; } } - } while (dup); + } while (dup && dup < DUP_MAX); + + /* Use the original name if we got too many dups. */ + + newp = dup < DUP_MAX ? newname : name; /* Create an entry for the name in the name table */ @@ -547,7 +562,7 @@ generate_obfuscated_name( return; p->namelen = namelen; - memcpy(p->name, newname, namelen); + memcpy(p->name, newp, namelen); p->hash = hash; p->next = nametable[hash % NAME_TABLE_SIZE]; @@ -555,7 +570,8 @@ generate_obfuscated_name( /* Update the caller's copy with the obfuscated name */ - memcpy(name, newname, namelen); + if (newp != name) + memcpy(name, newp, namelen); } static void _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs