diff --git a/[refs] b/[refs] index 57e957b659b5..b231ed2b96cc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 378bac820be6a0ec95df8151524de73ad2b2d2ac +refs/heads/master: f3ef6f63e5c575c136b39bb423a6e9a002932da7 diff --git a/trunk/fs/fat/dir.c b/trunk/fs/fat/dir.c index e5ae1b720dde..895049b2ac9c 100644 --- a/trunk/fs/fat/dir.c +++ b/trunk/fs/fat/dir.c @@ -30,6 +30,29 @@ static inline loff_t fat_make_i_pos(struct super_block *sb, | (de - (struct msdos_dir_entry *)bh->b_data); } +static inline void fat_dir_readahead(struct inode *dir, sector_t iblock, + sector_t phys) +{ + struct super_block *sb = dir->i_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + struct buffer_head *bh; + int sec; + + /* This is not a first sector of cluster, or sec_per_clus == 1 */ + if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1) + return; + /* root dir of FAT12/FAT16 */ + if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO)) + return; + + bh = sb_getblk(sb, phys); + if (bh && !buffer_uptodate(bh)) { + for (sec = 0; sec < sbi->sec_per_clus; sec++) + sb_breadahead(sb, phys + sec); + } + brelse(bh); +} + /* Returns the inode number of the directory entry at offset pos. If bh is non-NULL, it is brelse'd before. Pos is incremented. The buffer header is returned in bh. @@ -58,6 +81,8 @@ static int fat__get_entry(struct inode *dir, loff_t *pos, if (err || !phys) return -1; /* beyond EOF or error */ + fat_dir_readahead(dir, iblock, phys); + *bh = sb_bread(sb, phys); if (*bh == NULL) { printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", @@ -635,8 +660,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent, EODir: filp->f_pos = cpos; FillFailed: - if (bh) - brelse(bh); + brelse(bh); if (unicode) free_page((unsigned long)unicode); out: