UPSTREAM: exfat: improve performance of exfat_free_cluster when using dirsync mount
There are stressful update of cluster allocation bitmap when using dirsync mount option which is doing sync buffer on every cluster bit clearing. This could result in performance degradation when deleting big size file. Fix to update only when the bitmap buffer index is changed would make less disk access, improving performance especially for truncate operation. Testing with Samsung 256GB sdcard, mounted with dirsync option (mount -t exfat /dev/block/mmcblk0p1 /temp/mount -o dirsync) Remove 4GB file, blktrace result. [Before] : 39 secs. Total (blktrace): Reads Queued: 0, 0KiB Writes Queued: 32775, 16387KiB Read Dispatches: 0, 0KiB Write Dispatches: 32775, 16387KiB Reads Requeued: 0 Writes Requeued: 0 Reads Completed: 0, 0KiB Writes Completed: 32775, 16387KiB Read Merges: 0, 0KiB Write Merges: 0, 0KiB IO unplugs: 2 Timer unplugs: 0 [After] : 1 sec. Total (blktrace): Reads Queued: 0, 0KiB Writes Queued: 13, 6KiB Read Dispatches: 0, 0KiB Write Dispatches: 13, 6KiB Reads Requeued: 0 Writes Requeued: 0 Reads Completed: 0, 0KiB Writes Completed: 13, 6KiB Read Merges: 0, 0KiB Write Merges: 0, 0KiB IO unplugs: 1 Timer unplugs: 0 Bug: 241198061 Signed-off-by: Hyeongseok Kim <hyeongseok@gmail.com> Acked-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> (cherry picked from commit f728760aa923f1dd3a4818368dbdbd2c7d63b370) Signed-off-by: liujinbao1 <liujinbao1@xiaomi.com> Change-Id: I3931f005491c17489f5950293783270eb888fb09 Signed-off-by: liujinbao1 <liujinbao1@xiaomi.com>
This commit is contained in:

committed by
Treehugger Robot

parent
00d3b8c0cc
commit
b0988144b0
@@ -158,7 +158,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
|
||||||
{
|
{
|
||||||
int i, b;
|
int i, b;
|
||||||
unsigned int ent_idx;
|
unsigned int ent_idx;
|
||||||
@@ -172,7 +172,7 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
|||||||
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
||||||
|
|
||||||
clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
||||||
exfat_update_bh(sbi->vol_amap[i], IS_DIRSYNC(inode));
|
exfat_update_bh(sbi->vol_amap[i], sync);
|
||||||
|
|
||||||
if (opts->discard) {
|
if (opts->discard) {
|
||||||
int ret_discard;
|
int ret_discard;
|
||||||
|
@@ -408,7 +408,7 @@ int exfat_count_num_clusters(struct super_block *sb,
|
|||||||
int exfat_load_bitmap(struct super_block *sb);
|
int exfat_load_bitmap(struct super_block *sb);
|
||||||
void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
||||||
int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
||||||
void exfat_clear_bitmap(struct inode *inode, unsigned int clu);
|
void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
||||||
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
||||||
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
||||||
|
|
||||||
|
@@ -157,6 +157,7 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|||||||
unsigned int clu;
|
unsigned int clu;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
int cur_cmap_i, next_cmap_i;
|
||||||
|
|
||||||
/* invalid cluster number */
|
/* invalid cluster number */
|
||||||
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
||||||
@@ -176,21 +177,53 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|||||||
|
|
||||||
clu = p_chain->dir;
|
clu = p_chain->dir;
|
||||||
|
|
||||||
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
cur_cmap_i = next_cmap_i =
|
||||||
do {
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu));
|
||||||
exfat_clear_bitmap(inode, clu);
|
|
||||||
clu++;
|
|
||||||
|
|
||||||
|
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||||
|
unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bool sync = false;
|
||||||
|
|
||||||
|
if (clu < last_cluster)
|
||||||
|
next_cmap_i =
|
||||||
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu+1));
|
||||||
|
|
||||||
|
/* flush bitmap only if index would be changed or for last cluster */
|
||||||
|
if (clu == last_cluster || cur_cmap_i != next_cmap_i) {
|
||||||
|
sync = true;
|
||||||
|
cur_cmap_i = next_cmap_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
||||||
|
clu++;
|
||||||
num_clusters++;
|
num_clusters++;
|
||||||
} while (num_clusters < p_chain->size);
|
} while (num_clusters < p_chain->size);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
exfat_clear_bitmap(inode, clu);
|
bool sync = false;
|
||||||
|
unsigned int n_clu = clu;
|
||||||
|
int err = exfat_get_next_cluster(sb, &n_clu);
|
||||||
|
|
||||||
if (exfat_get_next_cluster(sb, &clu))
|
if (err || n_clu == EXFAT_EOF_CLUSTER)
|
||||||
goto dec_used_clus;
|
sync = true;
|
||||||
|
else
|
||||||
|
next_cmap_i =
|
||||||
|
BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(n_clu));
|
||||||
|
|
||||||
|
if (cur_cmap_i != next_cmap_i) {
|
||||||
|
sync = true;
|
||||||
|
cur_cmap_i = next_cmap_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
||||||
|
clu = n_clu;
|
||||||
|
|
||||||
num_clusters++;
|
num_clusters++;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto dec_used_clus;
|
||||||
} while (clu != EXFAT_EOF_CLUSTER);
|
} while (clu != EXFAT_EOF_CLUSTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user