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>
This commit is contained in:
parent
d52df2e2ea
commit
9f966be899
1 changed files with 28 additions and 0 deletions
|
@ -590,21 +590,49 @@ int fat_free_clusters(struct inode *inode, int cluster)
|
|||
|
||||
EXPORT_SYMBOL_GPL(fat_free_clusters);
|
||||
|
||||
/* 128kb is the whole sectors for FAT12 and FAT16 */
|
||||
#define FAT_READA_SIZE (128 * 1024)
|
||||
|
||||
static void fat_ent_reada(struct super_block *sb, struct fat_entry *fatent,
|
||||
unsigned long reada_blocks)
|
||||
{
|
||||
struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
|
||||
sector_t blocknr;
|
||||
int i, offset;
|
||||
|
||||
ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
|
||||
|
||||
for (i = 0; i < reada_blocks; i++)
|
||||
sb_breadahead(sb, blocknr + i);
|
||||
}
|
||||
|
||||
int fat_count_free_clusters(struct super_block *sb)
|
||||
{
|
||||
struct msdos_sb_info *sbi = MSDOS_SB(sb);
|
||||
struct fatent_operations *ops = sbi->fatent_ops;
|
||||
struct fat_entry fatent;
|
||||
unsigned long reada_blocks, reada_mask, cur_block;
|
||||
int err = 0, free;
|
||||
|
||||
lock_fat(sbi);
|
||||
if (sbi->free_clusters != -1)
|
||||
goto out;
|
||||
|
||||
reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
|
||||
reada_mask = reada_blocks - 1;
|
||||
cur_block = 0;
|
||||
|
||||
free = 0;
|
||||
fatent_init(&fatent);
|
||||
fatent_set_entry(&fatent, FAT_START_ENT);
|
||||
while (fatent.entry < sbi->max_cluster) {
|
||||
/* readahead of fat blocks */
|
||||
if ((cur_block & reada_mask) == 0) {
|
||||
unsigned long rest = sbi->fat_length - cur_block;
|
||||
fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
|
||||
}
|
||||
cur_block++;
|
||||
|
||||
err = fat_ent_read_block(sb, &fatent);
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
Loading…
Reference in a new issue