Commit 7ff228f0 authored by Hirofumi Ogawa's avatar Hirofumi Ogawa Committed by Linus Torvalds

[PATCH] FAT: the inode hash from per module to per sb

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ec1528b0
...@@ -31,7 +31,7 @@ void __exit fat_destroy_inodecache(void); ...@@ -31,7 +31,7 @@ void __exit fat_destroy_inodecache(void);
static int __init init_fat_fs(void) static int __init init_fat_fs(void)
{ {
int ret; int ret;
fat_hash_init();
ret = fat_cache_init(); ret = fat_cache_init();
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -58,17 +58,14 @@ static void fat_write_inode(struct inode *inode, int wait); ...@@ -58,17 +58,14 @@ static void fat_write_inode(struct inode *inode, int wait);
* and consider negative result as cache miss. * and consider negative result as cache miss.
*/ */
#define FAT_HASH_BITS 8 static void fat_hash_init(struct super_block *sb)
#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)
{ {
struct msdos_sb_info *sbi = MSDOS_SB(sb);
int i; int i;
spin_lock_init(&sbi->inode_hash_lock);
for (i = 0; i < FAT_HASH_SIZE; i++) 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) static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos)
...@@ -80,39 +77,43 @@ static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) ...@@ -80,39 +77,43 @@ static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos)
void fat_attach(struct inode *inode, loff_t i_pos) 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; MSDOS_I(inode)->i_pos = i_pos;
hlist_add_head(&MSDOS_I(inode)->i_fat_hash, hlist_add_head(&MSDOS_I(inode)->i_fat_hash,
fat_inode_hashtable + fat_hash(inode->i_sb, i_pos)); sbi->inode_hashtable + fat_hash(sb, i_pos));
spin_unlock(&fat_inode_lock); spin_unlock(&sbi->inode_hash_lock);
} }
void fat_detach(struct inode *inode) 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; MSDOS_I(inode)->i_pos = 0;
hlist_del_init(&MSDOS_I(inode)->i_fat_hash); 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 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 hlist_node *_p;
struct msdos_inode_info *i; struct msdos_inode_info *i;
struct inode *inode = NULL; 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) { hlist_for_each_entry(i, _p, head, i_fat_hash) {
if (i->vfs_inode.i_sb != sb) BUG_ON(i->vfs_inode.i_sb != sb);
continue;
if (i->i_pos != i_pos) if (i->i_pos != i_pos)
continue; continue;
inode = igrab(&i->vfs_inode); inode = igrab(&i->vfs_inode);
if (inode) if (inode)
break; break;
} }
spin_unlock(&fat_inode_lock); spin_unlock(&sbi->inode_hash_lock);
return inode; return inode;
} }
...@@ -155,13 +156,15 @@ static void fat_delete_inode(struct inode *inode) ...@@ -155,13 +156,15 @@ static void fat_delete_inode(struct inode *inode)
static void fat_clear_inode(struct inode *inode) static void fat_clear_inode(struct inode *inode)
{ {
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
if (is_bad_inode(inode)) if (is_bad_inode(inode))
return; return;
lock_kernel(); lock_kernel();
spin_lock(&fat_inode_lock); spin_lock(&sbi->inode_hash_lock);
fat_cache_inval_inode(inode); fat_cache_inval_inode(inode);
hlist_del_init(&MSDOS_I(inode)->i_fat_hash); hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
spin_unlock(&fat_inode_lock); spin_unlock(&sbi->inode_hash_lock);
unlock_kernel(); unlock_kernel();
} }
...@@ -822,6 +825,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -822,6 +825,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
goto out_fail; goto out_fail;
/* set up enough so that it can read an inode */ /* set up enough so that it can read an inode */
fat_hash_init(sb);
init_MUTEX(&sbi->fat_lock); init_MUTEX(&sbi->fat_lock);
error = -EIO; error = -EIO;
...@@ -1231,6 +1235,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) ...@@ -1231,6 +1235,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
int fat_write_inode(struct inode *inode, int wait) int fat_write_inode(struct inode *inode, int wait)
{ {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh; struct buffer_head *bh;
struct msdos_dir_entry *raw_entry; struct msdos_dir_entry *raw_entry;
loff_t i_pos; loff_t i_pos;
...@@ -1241,22 +1246,22 @@ int fat_write_inode(struct inode *inode, int wait) ...@@ -1241,22 +1246,22 @@ int fat_write_inode(struct inode *inode, int wait)
return 0; return 0;
} }
lock_kernel(); 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 " printk(KERN_ERR "FAT: unable to read inode block "
"for updating (i_pos %lld)\n", i_pos); "for updating (i_pos %lld)\n", i_pos);
unlock_kernel(); unlock_kernel();
return -EIO; return -EIO;
} }
spin_lock(&fat_inode_lock); spin_lock(&sbi->inode_hash_lock);
if (i_pos != MSDOS_I(inode)->i_pos) { if (i_pos != MSDOS_I(inode)->i_pos) {
spin_unlock(&fat_inode_lock); spin_unlock(&sbi->inode_hash_lock);
brelse(bh); brelse(bh);
unlock_kernel(); unlock_kernel();
goto retry; goto retry;
} }
raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) 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)) { if (S_ISDIR(inode->i_mode)) {
raw_entry->attr = ATTR_DIR; raw_entry->attr = ATTR_DIR;
raw_entry->size = 0; raw_entry->size = 0;
...@@ -1270,11 +1275,11 @@ int fat_write_inode(struct inode *inode, int wait) ...@@ -1270,11 +1275,11 @@ int fat_write_inode(struct inode *inode, int wait)
raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart); raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16); 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); 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); 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? */ 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); mark_buffer_dirty(bh);
brelse(bh); brelse(bh);
unlock_kernel(); unlock_kernel();
......
...@@ -259,7 +259,6 @@ extern int fat_get_block(struct inode *inode, sector_t iblock, ...@@ -259,7 +259,6 @@ extern int fat_get_block(struct inode *inode, sector_t iblock,
extern void fat_truncate(struct inode *inode); extern void fat_truncate(struct inode *inode);
/* fat/inode.c */ /* fat/inode.c */
extern void fat_hash_init(void);
extern void fat_attach(struct inode *inode, loff_t i_pos); extern void fat_attach(struct inode *inode, loff_t i_pos);
extern void fat_detach(struct inode *inode); extern void fat_detach(struct inode *inode);
extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
......
...@@ -26,6 +26,10 @@ struct fat_mount_options { ...@@ -26,6 +26,10 @@ struct fat_mount_options {
nocase:1; /* Does this need case conversion? 0=need case conversion*/ 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 { struct msdos_sb_info {
unsigned short sec_per_clus; /* sectors/cluster */ unsigned short sec_per_clus; /* sectors/cluster */
unsigned short cluster_bits; /* log2(cluster_size) */ unsigned short cluster_bits; /* log2(cluster_size) */
...@@ -48,6 +52,9 @@ struct msdos_sb_info { ...@@ -48,6 +52,9 @@ struct msdos_sb_info {
void *dir_ops; /* Opaque; default directory operations */ void *dir_ops; /* Opaque; default directory operations */
int dir_per_block; /* dir entries per block */ int dir_per_block; /* dir entries per block */
int dir_per_block_bits; /* log2(dir_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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment