diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2008-11-06 15:53:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-06 18:41:20 -0500 |
commit | d3dfa8228f87ab9960ab8b4718013d68e3c25a43 (patch) | |
tree | 236784875a5c735688e644fe8412649e5fdbfcd7 | |
parent | 52e9d9f4b32a3bec91feb76c84e37b7dcffe5040 (diff) |
fat: improve fat_hash()
fat_hash() is using the algorithm known as bad. Instead of it, this
uses hash_32(). The following is the summary of test.
old hash:
hash func (1000 times): 33489 cycles
total inodes in hash table: 70926
largest bucket contains: 696
smallest bucket contains: 54
new hash:
hash func (1000 times): 33129 cycles
total inodes in hash table: 70926
largest bucket contains: 315
smallest bucket contains: 236
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/fat/fat.h | 1 | ||||
-rw-r--r-- | fs/fat/inode.c | 18 |
2 files changed, 7 insertions, 12 deletions
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index a2a570f81719..2b8e94c3eef4 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -43,7 +43,6 @@ struct fat_mount_options { | |||
43 | 43 | ||
44 | #define FAT_HASH_BITS 8 | 44 | #define FAT_HASH_BITS 8 |
45 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) | 45 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) |
46 | #define FAT_HASH_MASK (FAT_HASH_SIZE-1) | ||
47 | 46 | ||
48 | /* | 47 | /* |
49 | * MS-DOS file system in-core superblock data | 48 | * MS-DOS file system in-core superblock data |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 079d9d5e0d36..f58cd48d98b8 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
27 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
28 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
29 | #include <linux/hash.h> | ||
29 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
30 | #include "fat.h" | 31 | #include "fat.h" |
31 | 32 | ||
@@ -247,25 +248,21 @@ static void fat_hash_init(struct super_block *sb) | |||
247 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); | 248 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); |
248 | } | 249 | } |
249 | 250 | ||
250 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) | 251 | static inline unsigned long fat_hash(loff_t i_pos) |
251 | { | 252 | { |
252 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; | 253 | return hash_32(i_pos, FAT_HASH_BITS); |
253 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); | ||
254 | return tmp & FAT_HASH_MASK; | ||
255 | } | 254 | } |
256 | 255 | ||
257 | void fat_attach(struct inode *inode, loff_t i_pos) | 256 | void fat_attach(struct inode *inode, loff_t i_pos) |
258 | { | 257 | { |
259 | struct super_block *sb = inode->i_sb; | 258 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
260 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 259 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
261 | 260 | ||
262 | spin_lock(&sbi->inode_hash_lock); | 261 | spin_lock(&sbi->inode_hash_lock); |
263 | MSDOS_I(inode)->i_pos = i_pos; | 262 | MSDOS_I(inode)->i_pos = i_pos; |
264 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, | 263 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head); |
265 | sbi->inode_hashtable + fat_hash(sb, i_pos)); | ||
266 | spin_unlock(&sbi->inode_hash_lock); | 264 | spin_unlock(&sbi->inode_hash_lock); |
267 | } | 265 | } |
268 | |||
269 | EXPORT_SYMBOL_GPL(fat_attach); | 266 | EXPORT_SYMBOL_GPL(fat_attach); |
270 | 267 | ||
271 | void fat_detach(struct inode *inode) | 268 | void fat_detach(struct inode *inode) |
@@ -276,13 +273,12 @@ void fat_detach(struct inode *inode) | |||
276 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 273 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
277 | spin_unlock(&sbi->inode_hash_lock); | 274 | spin_unlock(&sbi->inode_hash_lock); |
278 | } | 275 | } |
279 | |||
280 | EXPORT_SYMBOL_GPL(fat_detach); | 276 | EXPORT_SYMBOL_GPL(fat_detach); |
281 | 277 | ||
282 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | 278 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) |
283 | { | 279 | { |
284 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 280 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
285 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); | 281 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
286 | struct hlist_node *_p; | 282 | struct hlist_node *_p; |
287 | struct msdos_inode_info *i; | 283 | struct msdos_inode_info *i; |
288 | struct inode *inode = NULL; | 284 | struct inode *inode = NULL; |