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 <[email protected]>
---
fs/fat/fatent.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff -puN fs/fat/fatent.c~fat_optimize-count-freeclus fs/fat/fatent.c
--- linux-2.6/fs/fat/fatent.c~fat_optimize-count-freeclus 2007-11-05 06:01:10.000000000 +0900
+++ linux-2.6-hirofumi/fs/fat/fatent.c 2007-11-05 06:01:10.000000000 +0900
@@ -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;
_
--
OGAWA Hirofumi <[email protected]>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]