linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl
@ 2010-11-25  8:46 ykzhao
  2010-12-03  5:44 ` ykzhao
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: ykzhao @ 2010-11-25  8:46 UTC (permalink / raw)
  To: hirofumi; +Cc: linux-fsdevel

>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




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl
  2010-11-25  8:46 [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl ykzhao
@ 2010-12-03  5:44 ` ykzhao
  2010-12-30  1:34 ` ykzhao
  2011-01-21  8:38 ` Andrew Morton
  2 siblings, 0 replies; 4+ messages in thread
From: ykzhao @ 2010-12-03  5:44 UTC (permalink / raw)
  To: hirofumi@mail.parknet.co.jp; +Cc: linux-fsdevel@vger.kernel.org

On Thu, 2010-11-25 at 16:46 +0800, ykzhao wrote:
> >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.

Hi, Hirofumi
    Does this patch make sense to you?

thanks.
    Yakui 
   
> 
> 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)) {


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl
  2010-11-25  8:46 [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl ykzhao
  2010-12-03  5:44 ` ykzhao
@ 2010-12-30  1:34 ` ykzhao
  2011-01-21  8:38 ` Andrew Morton
  2 siblings, 0 replies; 4+ messages in thread
From: ykzhao @ 2010-12-30  1:34 UTC (permalink / raw)
  To: hirofumi@mail.parknet.co.jp; +Cc: linux-fsdevel@vger.kernel.org

On Thu, 2010-11-25 at 16:46 +0800, ykzhao wrote:
> >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>

Hi, Hirofumi
    Does this patch make sense to you?

thanks
> ---
> 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)) {


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl
  2010-11-25  8:46 [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl ykzhao
  2010-12-03  5:44 ` ykzhao
  2010-12-30  1:34 ` ykzhao
@ 2011-01-21  8:38 ` Andrew Morton
  2 siblings, 0 replies; 4+ messages in thread
From: Andrew Morton @ 2011-01-21  8:38 UTC (permalink / raw)
  To: ykzhao; +Cc: hirofumi, linux-fsdevel, Wu Fengguang

On Thu, 25 Nov 2010 16:46:37 +0800 ykzhao <yakui.zhao@intel.com> wrote:

> >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).

Seems reasonable.

> 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);
> +}

A few things.

a) I'd like to be really really convinced that there's no way in which
   this function can wander off the end of the device.  Or that the called
   functions handle this situation gracefully.

b) Lots of (old) filesystems probably do block-level readahead like this. 
   We really should have a generic vfs-layer library function, rather than
   open-coding it all the time.

c) sb_breadahead() is a truly ancient function.  It would be nice to use
   the more modern (and probably more efficient)
   force_page_cache_readahead().  It should be OK to pass filp==0.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-01-21  8:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-25  8:46 [PATCH] FAT: Readahead FAT table to reduce the read request of FAT tabl ykzhao
2010-12-03  5:44 ` ykzhao
2010-12-30  1:34 ` ykzhao
2011-01-21  8:38 ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).