mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
UPSTREAM: exfat: reduce block requests when zeroing a cluster
If 'dirsync' is enabled, when zeroing a cluster, submitting
sector by sector will generate many block requests, will
cause the block device to not fully perform its performance.
This commit makes the sectors in a cluster to be submitted in
once, it will reduce the number of block requests. This will
make the block device to give full play to its performance.
Test create 1000 directories on SD card with:
$ time (for ((i=0;i<1000;i++)); do mkdir dir${i}; done)
Performance has been improved by more than 73% on imx6q-sabrelite.
Cluster size Before After Improvement
64 KBytes 3m34.036s 0m56.052s 73.8%
128 KBytes 6m2.644s 1m13.354s 79.8%
256 KBytes 11m22.202s 1m39.451s 85.4%
imx6q-sabrelite:
- CPU: 792 MHz x4
- Memory: 1GB DDR3
- SD Card: SanDisk 8GB Class 4
Bug: 239500767
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Sungjong Seo <sj1557.seo@samsung.com>
(cherry picked from commit 1b61383854)
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: liujinbao1 <liujinbao1@xiaomi.com>
Change-Id: Ie9ed20fb90caed2fce2692f7fb81272cf647faa7
This commit is contained in:
committed by
Treehugger Robot
parent
885349f53d
commit
1f44e4411f
@@ -6,6 +6,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/blk_types.h>
|
||||
|
||||
#include "exfat_raw.h"
|
||||
#include "exfat_fs.h"
|
||||
@@ -233,10 +234,10 @@ int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct buffer_head *bhs[MAX_BUF_PER_PAGE];
|
||||
int nr_bhs = MAX_BUF_PER_PAGE;
|
||||
struct buffer_head *bh;
|
||||
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
|
||||
sector_t blknr, last_blknr;
|
||||
int err, i, n;
|
||||
int i;
|
||||
|
||||
blknr = exfat_cluster_to_sector(sbi, clu);
|
||||
last_blknr = blknr + sbi->sect_per_clus;
|
||||
@@ -250,30 +251,22 @@ int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
|
||||
}
|
||||
|
||||
/* Zeroing the unused blocks on this cluster */
|
||||
while (blknr < last_blknr) {
|
||||
for (n = 0; n < nr_bhs && blknr < last_blknr; n++, blknr++) {
|
||||
bhs[n] = sb_getblk(sb, blknr);
|
||||
if (!bhs[n]) {
|
||||
err = -ENOMEM;
|
||||
goto release_bhs;
|
||||
}
|
||||
memset(bhs[n]->b_data, 0, sb->s_blocksize);
|
||||
}
|
||||
for (i = blknr; i < last_blknr; i++) {
|
||||
bh = sb_getblk(sb, i);
|
||||
if (!bh)
|
||||
return -ENOMEM;
|
||||
|
||||
err = exfat_update_bhs(bhs, n, IS_DIRSYNC(dir));
|
||||
if (err)
|
||||
goto release_bhs;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
brelse(bhs[i]);
|
||||
memset(bh->b_data, 0, sb->s_blocksize);
|
||||
set_buffer_uptodate(bh);
|
||||
mark_buffer_dirty(bh);
|
||||
brelse(bh);
|
||||
}
|
||||
return 0;
|
||||
if (IS_DIRSYNC(dir))
|
||||
return filemap_write_and_wait_range(mapping,
|
||||
EXFAT_BLK_TO_B(blknr, sb),
|
||||
EXFAT_BLK_TO_B(last_blknr, sb) - 1);
|
||||
|
||||
release_bhs:
|
||||
exfat_err(sb, "failed zeroed sect %llu\n", (unsigned long long)blknr);
|
||||
for (i = 0; i < n; i++)
|
||||
bforget(bhs[i]);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
||||
|
||||
Reference in New Issue
Block a user