|
@@ -590,21 +590,49 @@ error:
|
|
|
|
|
|
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;
|