* [PATCH] Speedup FAT filesystem directory reads
@ 2005-08-04 1:33 Karsten Wiese
2005-08-04 14:21 ` OGAWA Hirofumi
0 siblings, 1 reply; 6+ messages in thread
From: Karsten Wiese @ 2005-08-04 1:33 UTC (permalink / raw)
To: linux-kernel, hirofumi, akpm
[-- Attachment #1: Type: text/plain, Size: 1374 bytes --]
Hi,
Please give this a try and commit to -mm or mainline, if approved.
Thanks,
Karsten
Summary:
This speeds up directory reads for large FAT partitions,
if the buffercache has to be filled from the drive.
Following values were taken from:
$ time find path_to_freshly_mounted_fat > /dev/null
on an otherwise idle system.
FAT with 16KB Clusters on IDE attached drive: Factor 2
FAT with 32KB Clusters on USB2 attached drive: Factor 10 (!)
Its less than 1/10 slower, if the buffercache is uptodate.
The patch touches 3 areas:
- fat_bmap() returns the sector's offset in the cluster or a
negativ error code instead of 0 or the negativ error code.
It's callers are changed accordingly.
- fat__get_entry() calls sb_breadahead() to readahead a whole cluster,
if the requested sector is the first one in a cluster.
It is usefull to do this, because on FAT directories occupy whole
clusters.
Readahead is only done, if the cluster's first sector is not uptodate
to avoid overhead, when the buffer cache is already uptodate.
Note that on memory pressure, the maximal byte count wasted
(read: has to be red from disk twice) is 1 cluster's size. Thats 64KB.
- Unrelated cleanup at one spot:
if (bh)
brelse(bh);
is replaced with:
brelse(bh);
brelse() can handle NULL pointer arguments by itself.
Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
[-- Attachment #2: fat+sb_breadahead.diff --]
[-- Type: text/x-diff, Size: 2074 bytes --]
diff -ur linux-2.6.13_orig/fs/fat/cache.c linux-2.6.13/fs/fat/cache.c
--- linux-2.6.13_orig/fs/fat/cache.c 2005-07-31 21:15:16.000000000 +0200
+++ linux-2.6.13/fs/fat/cache.c 2005-08-02 13:55:50.000000000 +0200
@@ -320,5 +320,5 @@
return cluster;
else if (cluster)
*phys = fat_clus_to_blknr(sbi, cluster) + offset;
- return 0;
+ return offset;
}
diff -ur linux-2.6.13_orig/fs/fat/dir.c linux-2.6.13/fs/fat/dir.c
--- linux-2.6.13_orig/fs/fat/dir.c 2005-07-31 21:14:20.000000000 +0200
+++ linux-2.6.13/fs/fat/dir.c 2005-07-31 21:53:28.000000000 +0200
@@ -46,7 +46,7 @@
struct super_block *sb = dir->i_sb;
sector_t phys, iblock;
int offset;
- int err;
+ int clu_sector;
next:
if (*bh)
@@ -54,10 +54,21 @@
*bh = NULL;
iblock = *pos >> sb->s_blocksize_bits;
- err = fat_bmap(dir, iblock, &phys);
- if (err || !phys)
+ clu_sector = fat_bmap(dir, iblock, &phys);
+ if (clu_sector < 0 || !phys)
return -1; /* beyond EOF or error */
+ if (0 == clu_sector) {
+ struct buffer_head *bh = __getblk(sb->s_bdev, phys, sb->s_blocksize);
+ if (!buffer_uptodate(bh)) {
+ int sec;
+ int sec_per_clus = MSDOS_SB(sb)->sec_per_clus;
+ for (sec = 0; sec < sec_per_clus; sec++)
+ sb_breadahead(sb, phys + sec);
+ }
+ brelse(bh);
+ }
+
*bh = sb_bread(sb, phys);
if (*bh == NULL) {
printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
@@ -635,8 +646,7 @@
EODir:
filp->f_pos = cpos;
FillFailed:
- if (bh)
- brelse(bh);
+ brelse(bh);
if (unicode)
free_page((unsigned long)unicode);
out:
diff -ur linux-2.6.13_orig/fs/fat/inode.c linux-2.6.13/fs/fat/inode.c
--- linux-2.6.13_orig/fs/fat/inode.c 2005-07-31 21:15:16.000000000 +0200
+++ linux-2.6.13/fs/fat/inode.c 2005-08-02 13:55:50.000000000 +0200
@@ -56,7 +56,7 @@
int err;
err = fat_bmap(inode, iblock, &phys);
- if (err)
+ if (err < 0)
return err;
if (phys) {
map_bh(bh_result, sb, phys);
@@ -76,7 +76,7 @@
}
MSDOS_I(inode)->mmu_private += sb->s_blocksize;
err = fat_bmap(inode, iblock, &phys);
- if (err)
+ if (err < 0)
return err;
if (!phys)
BUG();
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Speedup FAT filesystem directory reads
2005-08-04 1:33 [PATCH] Speedup FAT filesystem directory reads Karsten Wiese
@ 2005-08-04 14:21 ` OGAWA Hirofumi
2005-08-05 0:54 ` Karsten Wiese
0 siblings, 1 reply; 6+ messages in thread
From: OGAWA Hirofumi @ 2005-08-04 14:21 UTC (permalink / raw)
To: Karsten Wiese; +Cc: linux-kernel, akpm
Karsten Wiese <annabellesgarden@yahoo.de> writes:
> Please give this a try and commit to -mm or mainline, if approved.
Looks good. Thanks. However, I tweaked the patch.
- replace __getblk() to sb_getblk()
- exclude root-dir of FAT12/FAT16 from readahead
- exclude (sec_per_clus == 1) from readahead
- move the all readahead stuff to one inline function
What do you think of the following patch?
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
---
fs/fat/dir.c | 28 ++++++++++++++++++++++++++--
1 files changed, 26 insertions(+), 2 deletions(-)
diff -puN fs/fat/dir.c~fat-sb_breadahead fs/fat/dir.c
--- linux-2.6.13-rc4/fs/fat/dir.c~fat-sb_breadahead 2005-08-04 21:21:59.000000000 +0900
+++ linux-2.6.13-rc4-hirofumi/fs/fat/dir.c 2005-08-04 23:05:58.000000000 +0900
@@ -30,6 +30,29 @@ static inline loff_t fat_make_i_pos(stru
| (de - (struct msdos_dir_entry *)bh->b_data);
}
+static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
+ sector_t phys)
+{
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ int sec;
+
+ /* This is not a first sector of cluster, or sec_per_clus == 1 */
+ if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1)
+ return;
+ /* root dir of FAT12/FAT16 */
+ if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
+ return;
+
+ bh = sb_getblk(sb, phys);
+ if (bh && !buffer_uptodate(bh)) {
+ for (sec = 0; sec < sbi->sec_per_clus; sec++)
+ sb_breadahead(sb, phys + sec);
+ }
+ brelse(bh);
+}
+
/* Returns the inode number of the directory entry at offset pos. If bh is
non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
returned in bh.
@@ -58,6 +81,8 @@ next:
if (err || !phys)
return -1; /* beyond EOF or error */
+ fat_dir_readahead(dir, iblock, phys);
+
*bh = sb_bread(sb, phys);
if (*bh == NULL) {
printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
@@ -635,8 +660,7 @@ RecEnd:
EODir:
filp->f_pos = cpos;
FillFailed:
- if (bh)
- brelse(bh);
+ brelse(bh);
if (unicode)
free_page((unsigned long)unicode);
out:
_
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Speedup FAT filesystem directory reads
2005-08-04 14:21 ` OGAWA Hirofumi
@ 2005-08-05 0:54 ` Karsten Wiese
2005-08-05 1:34 ` OGAWA Hirofumi
0 siblings, 1 reply; 6+ messages in thread
From: Karsten Wiese @ 2005-08-05 0:54 UTC (permalink / raw)
To: OGAWA Hirofumi, akpm; +Cc: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2254 bytes --]
Am Donnerstag, 4. August 2005 16:21 schrieb OGAWA Hirofumi:
> Karsten Wiese <annabellesgarden@yahoo.de> writes:
>
> > Please give this a try and commit to -mm or mainline, if approved.
>
> Looks good. Thanks. However, I tweaked the patch.
>
> - replace __getblk() to sb_getblk()
> - exclude root-dir of FAT12/FAT16 from readahead
> - exclude (sec_per_clus == 1) from readahead
> - move the all readahead stuff to one inline function
>
> What do you think of the following patch?
Looks better, is smaller and works equally well here, thanks.
I had to hand apply it though as it was slightly scrambled
(by my mail client?) so patch couldn't handle it.
Please send patches as attachment.
Andrew,
please replace the initial version in -mm with this one.
Thanks,
Karsten
From: Karsten Wiese <annabellesgarden@yahoo.de>
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
This speeds up directory reads for large FAT partitions, if the buffercache
has to be filled from the drive. Following values were taken from:
$ time find path_to_freshly_mounted_fat > /dev/null
on an otherwise idle system.
FAT with 16KB Clusters on IDE attached drive: Factor 2
FAT with 32KB Clusters on USB2 attached drive: Factor 10 (!)
Its less than 1/10 slower, if the buffercache is uptodate.
The patch introduces the new function fat_dir_readahead().
fat_dir_readahead() calls sb_breadahead() to readahead a whole cluster,
if the requested sector is the first one in a cluster.
It is usefull to do this, because on FAT directories occupy whole
clusters, with the exception of FAT12/FAT16 root dirs.
Readahead is only done, if the cluster's first sector is not uptodate
to avoid overhead, when the buffer cache is already uptodate.
Note that under memory pressure, the maximal byte count wasted
(read: has to be red from disk twice) is 1 cluster's size. Thats 64KB.
fat_dir_readahead() is called from fat__get_entry().
There is also an unrelated cleanup at one spot:
if (bh)
brelse(bh);
is replaced with:
brelse(bh);
brelse() can handle NULL pointer arguments by itself.
Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
[-- Attachment #2: speedup-fat-filesystem-directory-reads_2.patch --]
[-- Type: text/x-diff, Size: 1496 bytes --]
diff -ur linux-2.6.13_orig/fs/fat/dir.c linux-2.6.13/fs/fat/dir.c
--- linux-2.6.13_orig/fs/fat/dir.c 2005-07-31 21:14:20.000000000 +0200
+++ linux-2.6.13/fs/fat/dir.c 2005-08-04 19:11:21.000000000 +0200
@@ -30,6 +30,29 @@
| (de - (struct msdos_dir_entry *)bh->b_data);
}
+static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
+ sector_t phys)
+{
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ int sec;
+
+ /* This is not a first sector of cluster, or sec_per_clus == 1 */
+ if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1)
+ return;
+ /* root dir of FAT12/FAT16 */
+ if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
+ return;
+
+ bh = sb_getblk(sb, phys);
+ if (bh && !buffer_uptodate(bh)) {
+ for (sec = 0; sec < sbi->sec_per_clus; sec++)
+ sb_breadahead(sb, phys + sec);
+ }
+ brelse(bh);
+}
+
/* Returns the inode number of the directory entry at offset pos. If bh is
non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
returned in bh.
@@ -58,6 +81,8 @@
if (err || !phys)
return -1; /* beyond EOF or error */
+ fat_dir_readahead(dir, iblock, phys);
+
*bh = sb_bread(sb, phys);
if (*bh == NULL) {
printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
@@ -635,8 +660,7 @@
EODir:
filp->f_pos = cpos;
FillFailed:
- if (bh)
- brelse(bh);
+ brelse(bh);
if (unicode)
free_page((unsigned long)unicode);
out:
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Speedup FAT filesystem directory reads
2005-08-05 0:54 ` Karsten Wiese
@ 2005-08-05 1:34 ` OGAWA Hirofumi
2005-08-05 6:10 ` Jan Engelhardt
0 siblings, 1 reply; 6+ messages in thread
From: OGAWA Hirofumi @ 2005-08-05 1:34 UTC (permalink / raw)
To: Karsten Wiese; +Cc: akpm, linux-kernel
Karsten Wiese <annabellesgarden@yahoo.de> writes:
> Looks better, is smaller and works equally well here, thanks.
> I had to hand apply it though as it was slightly scrambled
> (by my mail client?) so patch couldn't handle it.
> Please send patches as attachment.
We like a plain text, not attachment, see Documentation/SubmittingPatches.
Anyway, thanks for nice work.
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Speedup FAT filesystem directory reads
2005-08-05 1:34 ` OGAWA Hirofumi
@ 2005-08-05 6:10 ` Jan Engelhardt
2005-08-05 8:23 ` OGAWA Hirofumi
0 siblings, 1 reply; 6+ messages in thread
From: Jan Engelhardt @ 2005-08-05 6:10 UTC (permalink / raw)
To: OGAWA Hirofumi; +Cc: Karsten Wiese, akpm, linux-kernel
>We like a plain text, not attachment, see Documentation/SubmittingPatches.
>Anyway, thanks for nice work.
|Exception: If your mailer is mangling patches then someone may ask
|you to re-send them using MIME.
from the doc ;)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Speedup FAT filesystem directory reads
2005-08-05 6:10 ` Jan Engelhardt
@ 2005-08-05 8:23 ` OGAWA Hirofumi
0 siblings, 0 replies; 6+ messages in thread
From: OGAWA Hirofumi @ 2005-08-05 8:23 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Karsten Wiese, akpm, linux-kernel
Jan Engelhardt <jengelh@linux01.gwdg.de> writes:
> |Exception: If your mailer is mangling patches then someone may ask
> |you to re-send them using MIME.
>
> from the doc ;)
Oh, sure, I missed to read it :) But my mailer is actually sane.
Please double check your mailer.
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2005-08-05 8:24 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-08-04 1:33 [PATCH] Speedup FAT filesystem directory reads Karsten Wiese
2005-08-04 14:21 ` OGAWA Hirofumi
2005-08-05 0:54 ` Karsten Wiese
2005-08-05 1:34 ` OGAWA Hirofumi
2005-08-05 6:10 ` Jan Engelhardt
2005-08-05 8:23 ` OGAWA Hirofumi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome