From: OGAWA Hirofumi Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton --- 25-akpm/fs/fat/fatfs_syms.c | 2 - 25-akpm/fs/fat/inode.c | 57 +++++++++++++++++++----------------- 25-akpm/include/linux/msdos_fs.h | 1 25-akpm/include/linux/msdos_fs_sb.h | 7 ++++ 4 files changed, 39 insertions(+), 28 deletions(-) diff -puN fs/fat/fatfs_syms.c~fat-the-inode-hash-from-per-module-to-per-sb-4-6 fs/fat/fatfs_syms.c --- 25/fs/fat/fatfs_syms.c~fat-the-inode-hash-from-per-module-to-per-sb-4-6 Tue Sep 14 15:57:56 2004 +++ 25-akpm/fs/fat/fatfs_syms.c Tue Sep 14 15:57:56 2004 @@ -31,7 +31,7 @@ void __exit fat_destroy_inodecache(void) static int __init init_fat_fs(void) { int ret; - fat_hash_init(); + ret = fat_cache_init(); if (ret < 0) return ret; diff -puN fs/fat/inode.c~fat-the-inode-hash-from-per-module-to-per-sb-4-6 fs/fat/inode.c --- 25/fs/fat/inode.c~fat-the-inode-hash-from-per-module-to-per-sb-4-6 Tue Sep 14 15:57:56 2004 +++ 25-akpm/fs/fat/inode.c Tue Sep 14 15:58:50 2004 @@ -58,17 +58,14 @@ static void fat_write_inode(struct inode * and consider negative result as cache miss. */ -#define FAT_HASH_BITS 8 -#define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) -#define FAT_HASH_MASK (FAT_HASH_SIZE-1) -static struct hlist_head fat_inode_hashtable[FAT_HASH_SIZE]; -static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED; - -void fat_hash_init(void) +static void fat_hash_init(struct super_block *sb) { + struct msdos_sb_info *sbi = MSDOS_SB(sb); int i; + + spin_lock_init(&sbi->inode_hash_lock); for (i = 0; i < FAT_HASH_SIZE; i++) - INIT_HLIST_HEAD(&fat_inode_hashtable[i]); + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); } static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) @@ -80,39 +77,43 @@ static inline unsigned long fat_hash(str void fat_attach(struct inode *inode, loff_t i_pos) { - spin_lock(&fat_inode_lock); + struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + + spin_lock(&sbi->inode_hash_lock); MSDOS_I(inode)->i_pos = i_pos; hlist_add_head(&MSDOS_I(inode)->i_fat_hash, - fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); - spin_unlock(&fat_inode_lock); + sbi->inode_hashtable + fat_hash(sb, i_pos)); + spin_unlock(&sbi->inode_hash_lock); } void fat_detach(struct inode *inode) { - spin_lock(&fat_inode_lock); + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + spin_lock(&sbi->inode_hash_lock); MSDOS_I(inode)->i_pos = 0; hlist_del_init(&MSDOS_I(inode)->i_fat_hash); - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); } struct inode *fat_iget(struct super_block *sb, loff_t i_pos) { - struct hlist_head *head = fat_inode_hashtable + fat_hash(sb, i_pos); + struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); struct hlist_node *_p; struct msdos_inode_info *i; struct inode *inode = NULL; - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); hlist_for_each_entry(i, _p, head, i_fat_hash) { - if (i->vfs_inode.i_sb != sb) - continue; + BUG_ON(i->vfs_inode.i_sb != sb); if (i->i_pos != i_pos) continue; inode = igrab(&i->vfs_inode); if (inode) break; } - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); return inode; } @@ -155,13 +156,15 @@ static void fat_delete_inode(struct inod static void fat_clear_inode(struct inode *inode) { + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); + if (is_bad_inode(inode)) return; lock_kernel(); - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); fat_cache_inval_inode(inode); hlist_del_init(&MSDOS_I(inode)->i_fat_hash); - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); unlock_kernel(); } @@ -822,6 +825,7 @@ int fat_fill_super(struct super_block *s goto out_fail; /* set up enough so that it can read an inode */ + fat_hash_init(sb); init_MUTEX(&sbi->fat_lock); error = -EIO; @@ -1231,6 +1235,7 @@ static int fat_fill_inode(struct inode * int fat_write_inode(struct inode *inode, int wait) { struct super_block *sb = inode->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; struct msdos_dir_entry *raw_entry; loff_t i_pos; @@ -1241,22 +1246,22 @@ retry: return 0; } lock_kernel(); - if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) { + if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) { printk(KERN_ERR "FAT: unable to read inode block " "for updating (i_pos %lld)\n", i_pos); unlock_kernel(); return -EIO; } - spin_lock(&fat_inode_lock); + spin_lock(&sbi->inode_hash_lock); if (i_pos != MSDOS_I(inode)->i_pos) { - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); brelse(bh); unlock_kernel(); goto retry; } raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) - [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)]; + [i_pos & (sbi->dir_per_block - 1)]; if (S_ISDIR(inode->i_mode)) { raw_entry->attr = ATTR_DIR; raw_entry->size = 0; @@ -1270,11 +1275,11 @@ retry: raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart); raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16); fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); - if (MSDOS_SB(sb)->options.isvfat) { + if (sbi->options.isvfat) { fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */ } - spin_unlock(&fat_inode_lock); + spin_unlock(&sbi->inode_hash_lock); mark_buffer_dirty(bh); brelse(bh); unlock_kernel(); diff -puN include/linux/msdos_fs.h~fat-the-inode-hash-from-per-module-to-per-sb-4-6 include/linux/msdos_fs.h --- 25/include/linux/msdos_fs.h~fat-the-inode-hash-from-per-module-to-per-sb-4-6 Tue Sep 14 15:57:56 2004 +++ 25-akpm/include/linux/msdos_fs.h Tue Sep 14 15:57:56 2004 @@ -259,7 +259,6 @@ extern int fat_get_block(struct inode *i extern void fat_truncate(struct inode *inode); /* fat/inode.c */ -extern void fat_hash_init(void); extern void fat_attach(struct inode *inode, loff_t i_pos); extern void fat_detach(struct inode *inode); extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); diff -puN include/linux/msdos_fs_sb.h~fat-the-inode-hash-from-per-module-to-per-sb-4-6 include/linux/msdos_fs_sb.h --- 25/include/linux/msdos_fs_sb.h~fat-the-inode-hash-from-per-module-to-per-sb-4-6 Tue Sep 14 15:57:56 2004 +++ 25-akpm/include/linux/msdos_fs_sb.h Tue Sep 14 15:57:56 2004 @@ -26,6 +26,10 @@ struct fat_mount_options { nocase:1; /* Does this need case conversion? 0=need case conversion*/ }; +#define FAT_HASH_BITS 8 +#define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) +#define FAT_HASH_MASK (FAT_HASH_SIZE-1) + struct msdos_sb_info { unsigned short sec_per_clus; /* sectors/cluster */ unsigned short cluster_bits; /* log2(cluster_size) */ @@ -48,6 +52,9 @@ struct msdos_sb_info { void *dir_ops; /* Opaque; default directory operations */ int dir_per_block; /* dir entries per block */ int dir_per_block_bits; /* log2(dir_per_block) */ + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[FAT_HASH_SIZE]; }; #endif _