Commit f93a1734 authored by Hirofumi Ogawa's avatar Hirofumi Ogawa Committed by Linus Torvalds

[PATCH] FAT: rewrite the cache for file allocation table lookup

This rewrites the cache stuff for file allocation table (FAT).

This cache stocks the more pieces of FAT-chain by counting the number
of contiguous data blocks. And if cache hit, since a block number can
calculate without looking FAT-chain up, fat_get_block() become more
fast.

But if data blocks was fragmenting, unfortunately this cache is unuseful.

read from block device

[1st]# time dd if=/dev/hda6 of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 229.524189 seconds (9356241 bytes/sec)
real    3m49.557s, user    0m0.026s, sys     1m20.414s
[2nd]# time dd if=/dev/hda6 of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 229.539358 seconds (9355623 bytes/sec)
real    3m49.647s, user    0m0.036s, sys     1m20.144s

read from full contiguous file with this patch

[1st]# time dd if=data of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 337.959477 seconds (6354264 bytes/sec)
real    5m37.970s, user    0m0.031s, sys     1m21.915s
[2nd]# time dd if=data of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 225.401699 seconds (9527362 bytes/sec)
real    3m45.476s, user    0m0.027s, sys     1m19.286s

read from full fragmented file with this patch

[1st]# time dd if=data of=/dev/null bs=1M count=2048
2147483647 bytes transferred in 1146.529081 seconds (1873030 bytes/sec)
real    19m6.538s, user    0m0.020s, sys     1m32.774s
[2nd]# time dd if=data of=/dev/null bs=1M count=2048
2147483647 bytes transferred in 1045.084822 seconds (2054841 bytes/sec)
real    17m25.152s, user    0m0.022s, sys     1m34.801s

read from full contiguous file without this patch

[1st]# time dd if=data of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 348.144707 seconds (6168365 bytes/sec)
real    5m48.169s, user    0m0.019s, sys     1m29.962s
[2nd]# time dd if=data of=/dev/null bs=1M count=2048
2147483648 bytes transferred in 324.017361 seconds (6627681 bytes/sec)
real    5m24.038s, user    0m0.023s, sys     1m20.602s

read from full fragmented file without this patch

[1st]# time dd if=data of=/dev/null bs=1M count=2048
2147483647 bytes transferred in 1156.845693 seconds (1856327 bytes/sec)
real    19m16.855s, user    0m0.031s, sys     1m32.172s
[2nd]# time dd if=data of=/dev/null bs=1M count=2048
2147483647 bytes transferred in 1066.518713 seconds (2013545 bytes/sec)
real    17m46.526s, user    0m0.023s, sys     1m33.630s
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 13f17cb5
This diff is collapsed.
...@@ -24,16 +24,23 @@ EXPORT_SYMBOL(fat_scan); ...@@ -24,16 +24,23 @@ EXPORT_SYMBOL(fat_scan);
EXPORT_SYMBOL(fat_add_entries); EXPORT_SYMBOL(fat_add_entries);
EXPORT_SYMBOL(fat_dir_empty); EXPORT_SYMBOL(fat_dir_empty);
int __init fat_cache_init(void);
void __exit fat_cache_destroy(void);
int __init fat_init_inodecache(void); int __init fat_init_inodecache(void);
void __exit fat_destroy_inodecache(void); void __exit fat_destroy_inodecache(void);
static int __init init_fat_fs(void) static int __init init_fat_fs(void)
{ {
int ret;
fat_hash_init(); fat_hash_init();
ret = fat_cache_init();
if (ret < 0)
return ret;
return fat_init_inodecache(); return fat_init_inodecache();
} }
static void __exit exit_fat_fs(void) static void __exit exit_fat_fs(void)
{ {
fat_cache_destroy();
fat_destroy_inodecache(); fat_destroy_inodecache();
} }
......
...@@ -533,7 +533,6 @@ static int fat_read_root(struct inode *inode) ...@@ -533,7 +533,6 @@ static int fat_read_root(struct inode *inode)
struct msdos_sb_info *sbi = MSDOS_SB(sb); struct msdos_sb_info *sbi = MSDOS_SB(sb);
int error; int error;
MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
MSDOS_I(inode)->i_pos = 0; MSDOS_I(inode)->i_pos = 0;
inode->i_uid = sbi->options.fs_uid; inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid; inode->i_gid = sbi->options.fs_gid;
...@@ -736,6 +735,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -736,6 +735,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) { SLAB_CTOR_CONSTRUCTOR) {
ei->nr_caches = 0;
INIT_LIST_HEAD(&ei->cache_lru);
INIT_HLIST_NODE(&ei->i_fat_hash); INIT_HLIST_NODE(&ei->i_fat_hash);
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
} }
...@@ -819,7 +820,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -819,7 +820,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
if (error) if (error)
goto out_fail; goto out_fail;
fat_cache_init(sb); spin_lock_init(&MSDOS_SB(sb)->cache_lock);
/* set up enough so that it can read an inode */ /* set up enough so that it can read an inode */
init_MUTEX(&sbi->fat_lock); init_MUTEX(&sbi->fat_lock);
...@@ -1164,7 +1165,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) ...@@ -1164,7 +1165,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
struct msdos_sb_info *sbi = MSDOS_SB(sb); struct msdos_sb_info *sbi = MSDOS_SB(sb);
int error; int error;
MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
MSDOS_I(inode)->i_pos = 0; MSDOS_I(inode)->i_pos = 0;
inode->i_uid = sbi->options.fs_uid; inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid; inode->i_gid = sbi->options.fs_gid;
......
...@@ -155,7 +155,7 @@ int fat_add_cluster(struct inode *inode) ...@@ -155,7 +155,7 @@ int fat_add_cluster(struct inode *inode)
ret = fat_access(sb, last, new_dclus); ret = fat_access(sb, last, new_dclus);
if (ret < 0) if (ret < 0)
return ret; return ret;
fat_cache_add(inode, new_fclus, new_dclus); // fat_cache_add(inode, new_fclus, new_dclus);
} else { } else {
MSDOS_I(inode)->i_start = new_dclus; MSDOS_I(inode)->i_start = new_dclus;
MSDOS_I(inode)->i_logstart = new_dclus; MSDOS_I(inode)->i_logstart = new_dclus;
......
...@@ -232,8 +232,6 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) ...@@ -232,8 +232,6 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
extern int fat_access(struct super_block *sb, int nr, int new_value); extern int fat_access(struct super_block *sb, int nr, int new_value);
extern int __fat_access(struct super_block *sb, int nr, int new_value); extern int __fat_access(struct super_block *sb, int nr, int new_value);
extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys); extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
extern void fat_cache_init(struct super_block *sb);
extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
extern void fat_cache_inval_inode(struct inode *inode); extern void fat_cache_inval_inode(struct inode *inode);
extern int fat_get_cluster(struct inode *inode, int cluster, extern int fat_get_cluster(struct inode *inode, int cluster,
int *fclus, int *dclus); int *fclus, int *dclus);
......
...@@ -8,9 +8,8 @@ ...@@ -8,9 +8,8 @@
*/ */
struct msdos_inode_info { struct msdos_inode_info {
/* cache of lastest accessed cluster */ struct list_head cache_lru;
int file_cluster; /* cluster number in the file. */ int nr_caches;
int disk_cluster; /* cluster number on disk. */
loff_t mmu_private; loff_t mmu_private;
int i_start; /* first cluster or 0 */ int i_start; /* first cluster or 0 */
......
...@@ -26,15 +26,6 @@ struct fat_mount_options { ...@@ -26,15 +26,6 @@ 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_CACHE_NR 8 /* number of FAT cache */
struct fat_cache {
int start_cluster; /* first cluster of the chain. */
int file_cluster; /* cluster number in the file. */
int disk_cluster; /* cluster number on disk. */
struct fat_cache *next; /* next cache entry */
};
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) */
...@@ -59,7 +50,6 @@ struct msdos_sb_info { ...@@ -59,7 +50,6 @@ struct msdos_sb_info {
int dir_per_block_bits; /* log2(dir_per_block) */ int dir_per_block_bits; /* log2(dir_per_block) */
spinlock_t cache_lock; spinlock_t cache_lock;
struct fat_cache cache_array[FAT_CACHE_NR], *cache;
}; };
#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