aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2008-01-08 18:32:41 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-01-08 19:10:35 -0500
commit9f966be8996f2829406324c68e4c67c2d64d864b (patch)
tree40b2e1f12834498f1e7d8240fe7f6f3dbaf0dce2
parentd52df2e2ea2d881b1439bbdec7f67c27e0f47941 (diff)
fat: optimize fat_count_free_clusters()
On large partition, scanning the free clusters is very slow if users doesn't use "usefree" option. For optimizing it, this patch uses sb_breadahead() to read of FAT sectors. On some user's 15GB partition, this patch improved it very much (1min => 600ms). The following is the result of 2GB partition on my machine. without patch: root@devron (/)# time df -h > /dev/null real 0m1.202s user 0m0.000s sys 0m0.440s with patch: root@devron (/)# time df -h > /dev/null real 0m0.378s user 0m0.012s sys 0m0.168s Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/fat/fatent.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 2c1b73fb82ae..5fb366992b73 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -590,21 +590,49 @@ error:
590 590
591EXPORT_SYMBOL_GPL(fat_free_clusters); 591EXPORT_SYMBOL_GPL(fat_free_clusters);
592 592
593/* 128kb is the whole sectors for FAT12 and FAT16 */
594#define FAT_READA_SIZE (128 * 1024)
595
596static void fat_ent_reada(struct super_block *sb, struct fat_entry *fatent,
597 unsigned long reada_blocks)
598{
599 struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
600 sector_t blocknr;
601 int i, offset;
602
603 ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
604
605 for (i = 0; i < reada_blocks; i++)
606 sb_breadahead(sb, blocknr + i);
607}
608
593int fat_count_free_clusters(struct super_block *sb) 609int fat_count_free_clusters(struct super_block *sb)
594{ 610{
595 struct msdos_sb_info *sbi = MSDOS_SB(sb); 611 struct msdos_sb_info *sbi = MSDOS_SB(sb);
596 struct fatent_operations *ops = sbi->fatent_ops; 612 struct fatent_operations *ops = sbi->fatent_ops;
597 struct fat_entry fatent; 613 struct fat_entry fatent;
614 unsigned long reada_blocks, reada_mask, cur_block;
598 int err = 0, free; 615 int err = 0, free;
599 616
600 lock_fat(sbi); 617 lock_fat(sbi);
601 if (sbi->free_clusters != -1) 618 if (sbi->free_clusters != -1)
602 goto out; 619 goto out;
603 620
621 reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
622 reada_mask = reada_blocks - 1;
623 cur_block = 0;
624
604 free = 0; 625 free = 0;
605 fatent_init(&fatent); 626 fatent_init(&fatent);
606 fatent_set_entry(&fatent, FAT_START_ENT); 627 fatent_set_entry(&fatent, FAT_START_ENT);
607 while (fatent.entry < sbi->max_cluster) { 628 while (fatent.entry < sbi->max_cluster) {
629 /* readahead of fat blocks */
630 if ((cur_block & reada_mask) == 0) {
631 unsigned long rest = sbi->fat_length - cur_block;
632 fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
633 }
634 cur_block++;
635
608 err = fat_ent_read_block(sb, &fatent); 636 err = fat_ent_read_block(sb, &fatent);
609 if (err) 637 if (err)
610 goto out; 638 goto out;