Commit 47c872b3 authored by Hirofumi Ogawa's avatar Hirofumi Ogawa Committed by Arnaldo Carvalho de Melo

[PATCH] FAT cluster chain cache per inode (5/5)

This adds a cache of lastest accessed cluster to inode for sequential
access.

The following is 500M file of FAT-to-FAT copy test, this may be a most
different case in usual operations, because maximum readahead window
flush the all caches.

512 bytes blocksize, 4096 bytes cluster size.

linux-2.5.69-bk12
	root@devron (a)[1232]# time cp file file1

	real    7m58.900s
	user    0m0.267s
	sys     6m44.258s

linux-2.5.69-bk12+patch
	root@devron (a)[1576]# time cp file file1

	real    2m44.309s
	user    0m0.270s
	sys     0m28.631s
parent b438aca4
...@@ -152,11 +152,20 @@ void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu) ...@@ -152,11 +152,20 @@ void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
struct fat_cache *walk; struct fat_cache *walk;
int first; int first;
BUG_ON(cluster == 0);
first = MSDOS_I(inode)->i_start; first = MSDOS_I(inode)->i_start;
if (!first) if (!first)
return; return;
spin_lock(&sbi->cache_lock); spin_lock(&sbi->cache_lock);
if (MSDOS_I(inode)->disk_cluster &&
MSDOS_I(inode)->file_cluster <= cluster) {
*d_clu = MSDOS_I(inode)->disk_cluster;
*f_clu = MSDOS_I(inode)->file_cluster;
}
for (walk = sbi->cache; walk; walk = walk->next) { for (walk = sbi->cache; walk; walk = walk->next) {
if (walk->start_cluster == first if (walk->start_cluster == first
&& walk->file_cluster <= cluster && walk->file_cluster <= cluster
...@@ -203,6 +212,7 @@ static void __fat_cache_inval_inode(struct inode *inode) ...@@ -203,6 +212,7 @@ static void __fat_cache_inval_inode(struct inode *inode)
{ {
struct fat_cache *walk; struct fat_cache *walk;
int first = MSDOS_I(inode)->i_start; int first = MSDOS_I(inode)->i_start;
MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next) for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next)
if (walk->start_cluster == first) if (walk->start_cluster == first)
walk->start_cluster = 0; walk->start_cluster = 0;
...@@ -220,7 +230,7 @@ void fat_cache_add(struct inode *inode, int f_clu, int d_clu) ...@@ -220,7 +230,7 @@ void fat_cache_add(struct inode *inode, int f_clu, int d_clu)
{ {
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
struct fat_cache *walk, *last; struct fat_cache *walk, *last;
int first; int first, prev_f_clu, prev_d_clu;
first = MSDOS_I(inode)->i_start; first = MSDOS_I(inode)->i_start;
if (!first) if (!first)
...@@ -228,6 +238,20 @@ void fat_cache_add(struct inode *inode, int f_clu, int d_clu) ...@@ -228,6 +238,20 @@ void fat_cache_add(struct inode *inode, int f_clu, int d_clu)
last = NULL; last = NULL;
spin_lock(&sbi->cache_lock); spin_lock(&sbi->cache_lock);
if (MSDOS_I(inode)->file_cluster == f_clu)
goto out;
else {
prev_f_clu = MSDOS_I(inode)->file_cluster;
prev_d_clu = MSDOS_I(inode)->disk_cluster;
MSDOS_I(inode)->file_cluster = f_clu;
MSDOS_I(inode)->disk_cluster = d_clu;
if (prev_f_clu == 0)
goto out;
f_clu = prev_f_clu;
d_clu = prev_d_clu;
}
for (walk = sbi->cache; walk->next; walk = (last = walk)->next) { for (walk = sbi->cache; walk->next; walk = (last = walk)->next) {
if (walk->start_cluster == first && if (walk->start_cluster == first &&
walk->file_cluster == f_clu) { walk->file_cluster == f_clu) {
......
...@@ -1101,6 +1101,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) ...@@ -1101,6 +1101,7 @@ 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;
......
...@@ -8,6 +8,10 @@ ...@@ -8,6 +8,10 @@
*/ */
struct msdos_inode_info { struct msdos_inode_info {
/* cache of lastest accessed cluster */
int file_cluster; /* cluster number in the file. */
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 */
int i_logstart; /* logical first cluster */ int i_logstart; /* logical first cluster */
......
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