From: Bjorn Stenberg OGAWA Hirofumi This simple patch makes the linux fat filesystem driver use the next_cluster field in the fat_boot_fsinfo structure. This field is a hint where to start looking for free clusters. Using this field makes a big difference for disks connected over slow links such as USB 1.1. Finding the first free cluster on a 40gig fat-formatted usb disk can today take several minutes. This patch cuts it down to a fraction of a second. Also, commit the next_cluster search hint toand from the superblock in write_super/fill_super. fs/fat/inode.c | 1 + fs/fat/misc.c | 17 +++++++++++------ include/linux/msdos_fs.h | 3 +-- 3 files changed, 13 insertions(+), 8 deletions(-) diff -puN fs/fat/inode.c~fat-speedup fs/fat/inode.c --- 25/fs/fat/inode.c~fat-speedup 2003-05-12 21:23:11.000000000 -0700 +++ 25-akpm/fs/fat/inode.c 2003-05-12 21:23:11.000000000 -0700 @@ -897,6 +897,7 @@ int fat_fill_super(struct super_block *s sbi->fsinfo_sector); } else { sbi->free_clusters = CF_LE_L(fsinfo->free_clusters); + sbi->prev_free = CF_LE_L(fsinfo->next_cluster); } brelse(fsinfo_bh); diff -puN fs/fat/misc.c~fat-speedup fs/fat/misc.c --- 25/fs/fat/misc.c~fat-speedup 2003-05-12 21:23:11.000000000 -0700 +++ 25-akpm/fs/fat/misc.c 2003-05-12 21:23:11.000000000 -0700 @@ -74,6 +74,7 @@ void fat_clusters_flush(struct super_blo MSDOS_SB(sb)->fsinfo_sector); } else { fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters); + fsinfo->next_cluster = CF_LE_L(MSDOS_SB(sb)->prev_free); mark_buffer_dirty(bh); } brelse(bh); @@ -130,19 +131,23 @@ int fat_add_cluster(struct inode *inode) unlock_fat(sb); return -ENOSPC; } - limit = MSDOS_SB(sb)->clusters; - for (count = 0; count < limit; count++) { - nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2; + + limit = MSDOS_SB(sb)->clusters + 2; + nr = MSDOS_SB(sb)->prev_free + 1; + for (count = 0; count < MSDOS_SB(sb)->clusters; count++, nr++) { + nr = nr % limit; + if (nr < 2) + nr = 2; if (fat_access(sb, nr, -1) == FAT_ENT_FREE) break; } - if (count >= limit) { + if (count >= MSDOS_SB(sb)->clusters) { MSDOS_SB(sb)->free_clusters = 0; unlock_fat(sb); return -ENOSPC; } - - MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit; + MSDOS_SB(sb)->prev_free = nr; + fat_access(sb, nr, FAT_ENT_EOF); if (MSDOS_SB(sb)->free_clusters != -1) MSDOS_SB(sb)->free_clusters--; diff -puN include/linux/msdos_fs.h~fat-speedup include/linux/msdos_fs.h --- 25/include/linux/msdos_fs.h~fat-speedup 2003-05-12 21:23:11.000000000 -0700 +++ 25-akpm/include/linux/msdos_fs.h 2003-05-12 21:23:11.000000000 -0700 @@ -146,8 +146,7 @@ struct fat_boot_fsinfo { __u32 reserved1[120]; /* Nothing as far as I can tell */ __u32 signature2; /* 0x61417272L */ __u32 free_clusters; /* Free cluster count. -1 if unknown */ - __u32 next_cluster; /* Most recently allocated cluster. - * Unused under Linux. */ + __u32 next_cluster; /* Most recently allocated cluster */ __u32 reserved2[4]; }; _