All of lore.kernel.org
 help / color / mirror / Atom feed
From: ykzhao <yakui.zhao@intel.com>
To: hirofumi@mail.parknet.co.jp
Cc: linux-fsdevel@vger.kernel.org
Subject: [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl
Date: Thu, 25 Nov 2010 16:46:37 +0800	[thread overview]
Message-ID: <1290674797.3948.71.camel@localhost.localdomain> (raw)

>From badc27e6b5f732191fb3b7e964f68da030144c76 Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Fri, 19 Nov 2010 10:29:33 +0800
Subject: [PATCH] FAT: Readahead FAT table to reduce the read request of FAT table

On FAT filesystem the FAT table will be accessed very frequently when
reading/writing the file. Now it reads only block sector from FAT table every
time and it will have to wait for the completion of read-access. In fact
as the FAT table is located sequentially on the disk, maybe we can readahead
the following sectors to reduce the read access of FAT table.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
The following is the test result on SD card/U-disk.
a. Read/Write a large file by using direct mode on SD card
   dd if=sda.bin of=sda.bin2 bs=64k iflag=direct
	The average copy time can be reduced from 470 second to 452 seconds(The file
of sda.bin is about 1.8G).

a. Read/Write a large file by using direct mode on U-disk
   dd if=sda.bin of=sda.bin2 bs=64k iflag=direct
	The average copy time can be reduced from about 880 to 855 seconds.(The file
of sda.bin is about 1.8G).

 fs/fat/fat.h    |    1 +
 fs/fat/fatent.c |   26 ++++++++++++++++++++++++++
 fs/fat/inode.c  |    4 ++++
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index d75a77f..caf5449 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -84,6 +84,7 @@ struct msdos_sb_info {
 	struct inode *fat_inode;
 
 	struct ratelimit_state ratelimit;
+	int fat_readahead_cnt; /* block number for readahead FAT table every time */
 
 	spinlock_t inode_hash_lock;
 	struct hlist_head inode_hashtable[FAT_HASH_SIZE];
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index b47d2c9..1dfd73f 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -67,6 +67,26 @@ static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset)
 	fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);
 }
 
+static void fat_table_readahead(struct super_block *sb, sector_t iphys)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct buffer_head *bh;
+	int sec, sec_count;
+
+	sec_count = sbi->fat_readahead_cnt;
+	/*
+	 * It will check whether the current block is already obtained from the
+	 * disk. If not, we will try to readahead more sectors when
+	 * reading the FAT table
+	 */
+	bh = sb_find_get_block(sb, iphys);
+	if (bh == NULL || !buffer_uptodate(bh)) {
+		for (sec = 0; sec < sec_count; sec++)
+			sb_breadahead(sb, iphys + sec);
+	}
+	brelse(bh);
+}
+
 static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 			   int offset, sector_t blocknr)
 {
@@ -75,6 +95,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
 	fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
 
+	fat_table_readahead(sb, blocknr);
 	bhs[0] = sb_bread(sb, blocknr);
 	if (!bhs[0])
 		goto err;
@@ -84,6 +105,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 	else {
 		/* This entry is block boundary, it needs the next block */
 		blocknr++;
+		fat_table_readahead(sb, blocknr);
 		bhs[1] = sb_bread(sb, blocknr);
 		if (!bhs[1])
 			goto err_brelse;
@@ -105,6 +127,10 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
 
 	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
+
+	/* readahead the content of FAT table */
+	fat_table_readahead(sb, blocknr);
+
 	fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
 	fatent->bhs[0] = sb_bread(sb, blocknr);
 	if (!fatent->bhs[0]) {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ad6998a..fa00b6f 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -34,6 +34,8 @@
 #define CONFIG_FAT_DEFAULT_IOCHARSET	""
 #endif
 
+
+#define FAT_MAX_READAHEAD	32768
 static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
 static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
 
@@ -1406,6 +1408,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
 	sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
+
+	sbi->fat_readahead_cnt = FAT_MAX_READAHEAD / sb->s_blocksize;
 	sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
 	sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
 	if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
-- 
1.5.4.5




             reply	other threads:[~2010-11-25  8:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-25  8:46 ykzhao [this message]
2010-12-03  5:44 ` [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl ykzhao
2010-12-30  1:34 ` ykzhao
2011-01-21  8:38 ` Andrew Morton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1290674797.3948.71.camel@localhost.localdomain \
    --to=yakui.zhao@intel.com \
    --cc=hirofumi@mail.parknet.co.jp \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.