diff options
Diffstat (limited to 'fs/fat')
-rw-r--r-- | fs/fat/fatent.c | 28 |
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 | ||
591 | EXPORT_SYMBOL_GPL(fat_free_clusters); | 591 | EXPORT_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 | |||
596 | static 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 | |||
593 | int fat_count_free_clusters(struct super_block *sb) | 609 | int 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; |