diff --git a/e2fsck/dirinfo.c b/e2fsck/dirinfo.c index 901235c..9b29f23 100644 --- a/e2fsck/dirinfo.c +++ b/e2fsck/dirinfo.c @@ -62,7 +62,7 @@ static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs) uuid_unparse(ctx->fs->super->s_uuid, uuid); sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid); fd = mkstemp(db->tdb_fn); - db->tdb = tdb_open(db->tdb_fn, 0, TDB_CLEAR_IF_FIRST, + db->tdb = tdb_open(db->tdb_fn, 999931, TDB_NOLOCK | TDB_NOSYNC, O_RDWR | O_CREAT | O_TRUNC, 0600); close(fd); } diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c index bec0f5f..bdd5b26 100644 --- a/lib/ext2fs/icount.c +++ b/lib/ext2fs/icount.c @@ -173,6 +173,19 @@ static void uuid_unparse(void *uu, char *out) uuid.node[3], uuid.node[4], uuid.node[5]); } +static unsigned int my_tdb_hash(TDB_DATA *key) +{ + unsigned int value; /* Used to compute the hash value. */ + int i; /* Used to cycle through random values. */ + + /* initial value 0 is as good as any one. */ + for (value = 0, i=0; i < key->dsize; i++) + value = value * 256 + key->dptr[i] + (value >> 24) * 241; + + return value; +} + + errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, int flags, ext2_icount_t *ret) { @@ -180,6 +193,7 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, errcode_t retval; char *fn, uuid[40]; int fd; + int hash_size; retval = alloc_icount(fs, flags, &icount); if (retval) @@ -192,9 +206,20 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid); fd = mkstemp(fn); + /* + hash_size should be on the same order of the number of entries actually + used. The tdb default used to be 131 which gives us a big performance + penalty with normal inode numbers. We now trust the superblock. If it's + wrong, don't worry, tdb will manage, it will just cost a little bit more + CPUtime. + If the hash function is good and distributes the values uniformly across + the 32bit output space, it doesn't really matter that we didn't chose a + prime. The default tdb hash function is pretty worthless. Someone didn't + read Knuth. */ + hash_size = fs->super->s_inodes_count - fs->super->s_free_inodes_count; icount->tdb_fn = fn; - icount->tdb = tdb_open(fn, 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT | O_TRUNC, 0600); + icount->tdb = tdb_open_ex(fn, hash_size, TDB_NOLOCK | TDB_NOSYNC, + O_RDWR | O_CREAT | O_TRUNC, 0600, NULL, my_tdb_hash); if (icount->tdb) { close(fd); *ret = icount;