summaryrefslogtreecommitdiff
path: root/fs/fat
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-09-08 05:39:55 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-08 05:39:55 -0400
commitc324b44c34050cf2a9b58830e11c974806bd85d8 (patch)
tree3ac45a783221283925cd698334a8f5e7dd4c1df8 /fs/fat
parent2fcf522509cceea524b6e7ece8fd6759b682175a (diff)
parentcaf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/dir.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index e5ae1b720dde..895049b2ac9c 100644
--- a/fs/fat/dir.c
+++ b/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 @@ next:
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 @@ RecEnd:
EODir:
filp->f_pos = cpos;
FillFailed:
- if (bh)
- brelse(bh);
+ brelse(bh);
if (unicode)
free_page((unsigned long)unicode);
out: