|
Kmods SIG |
9e3ffb |
From f728760aa923f1dd3a4818368dbdbd2c7d63b370 Mon Sep 17 00:00:00 2001
|
|
Kmods SIG |
9e3ffb |
From: Hyeongseok Kim <hyeongseok@gmail.com>
|
|
Kmods SIG |
9e3ffb |
Date: Mon, 1 Feb 2021 10:02:46 +0900
|
|
Kmods SIG |
9e3ffb |
Subject: [Backport f728760aa923] exfat: improve performance of
|
|
Kmods SIG |
9e3ffb |
exfat_free_cluster when using dirsync mount option
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
There are stressful update of cluster allocation bitmap when using
|
|
Kmods SIG |
9e3ffb |
dirsync mount option which is doing sync buffer on every cluster bit
|
|
Kmods SIG |
9e3ffb |
clearing. This could result in performance degradation when deleting
|
|
Kmods SIG |
9e3ffb |
big size file.
|
|
Kmods SIG |
9e3ffb |
Fix to update only when the bitmap buffer index is changed would make
|
|
Kmods SIG |
9e3ffb |
less disk access, improving performance especially for truncate operation.
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
Testing with Samsung 256GB sdcard, mounted with dirsync option
|
|
Kmods SIG |
9e3ffb |
(mount -t exfat /dev/block/mmcblk0p1 /temp/mount -o dirsync)
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
Remove 4GB file, blktrace result.
|
|
Kmods SIG |
9e3ffb |
[Before] : 39 secs.
|
|
Kmods SIG |
9e3ffb |
Total (blktrace):
|
|
Kmods SIG |
9e3ffb |
Reads Queued: 0, 0KiB Writes Queued: 32775, 16387KiB
|
|
Kmods SIG |
9e3ffb |
Read Dispatches: 0, 0KiB Write Dispatches: 32775, 16387KiB
|
|
Kmods SIG |
9e3ffb |
Reads Requeued: 0 Writes Requeued: 0
|
|
Kmods SIG |
9e3ffb |
Reads Completed: 0, 0KiB Writes Completed: 32775, 16387KiB
|
|
Kmods SIG |
9e3ffb |
Read Merges: 0, 0KiB Write Merges: 0, 0KiB
|
|
Kmods SIG |
9e3ffb |
IO unplugs: 2 Timer unplugs: 0
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
[After] : 1 sec.
|
|
Kmods SIG |
9e3ffb |
Total (blktrace):
|
|
Kmods SIG |
9e3ffb |
Reads Queued: 0, 0KiB Writes Queued: 13, 6KiB
|
|
Kmods SIG |
9e3ffb |
Read Dispatches: 0, 0KiB Write Dispatches: 13, 6KiB
|
|
Kmods SIG |
9e3ffb |
Reads Requeued: 0 Writes Requeued: 0
|
|
Kmods SIG |
9e3ffb |
Reads Completed: 0, 0KiB Writes Completed: 13, 6KiB
|
|
Kmods SIG |
9e3ffb |
Read Merges: 0, 0KiB Write Merges: 0, 0KiB
|
|
Kmods SIG |
9e3ffb |
IO unplugs: 1 Timer unplugs: 0
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
Signed-off-by: Hyeongseok Kim <hyeongseok@gmail.com>
|
|
Kmods SIG |
9e3ffb |
Acked-by: Sungjong Seo <sj1557.seo@samsung.com>
|
|
Kmods SIG |
9e3ffb |
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
|
|
Kmods SIG |
9e3ffb |
---
|
|
Kmods SIG |
9e3ffb |
src/balloc.c | 4 ++--
|
|
Kmods SIG |
9e3ffb |
src/exfat_fs.h | 2 +-
|
|
Kmods SIG |
9e3ffb |
src/fatent.c | 43 +++++++++++++++++++++++++++++++++++++------
|
|
Kmods SIG |
9e3ffb |
3 files changed, 40 insertions(+), 9 deletions(-)
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/balloc.c b/src/balloc.c
|
|
Kmods SIG |
9e3ffb |
index a987919686c0d4d339ce71d11887d9510280df77..761c79c3a4ba262870686608f3619c98312f65cb 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/balloc.c
|
|
Kmods SIG |
9e3ffb |
+++ b/src/balloc.c
|
|
Kmods SIG |
9e3ffb |
@@ -166,7 +166,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu)
|
|
Kmods SIG |
9e3ffb |
* If the value of "clu" is 0, it means cluster 2 which is the first cluster of
|
|
Kmods SIG |
9e3ffb |
* the cluster heap.
|
|
Kmods SIG |
9e3ffb |
*/
|
|
Kmods SIG |
9e3ffb |
-void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
|
Kmods SIG |
9e3ffb |
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
|
|
Kmods SIG |
9e3ffb |
{
|
|
Kmods SIG |
9e3ffb |
int i, b;
|
|
Kmods SIG |
9e3ffb |
unsigned int ent_idx;
|
|
Kmods SIG |
9e3ffb |
@@ -180,7 +180,7 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
|
|
Kmods SIG |
9e3ffb |
b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
clear_bit_le(b, sbi->vol_amap[i]->b_data);
|
|
Kmods SIG |
9e3ffb |
- exfat_update_bh(sbi->vol_amap[i], IS_DIRSYNC(inode));
|
|
Kmods SIG |
9e3ffb |
+ exfat_update_bh(sbi->vol_amap[i], sync);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
if (opts->discard) {
|
|
Kmods SIG |
9e3ffb |
int ret_discard;
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/exfat_fs.h b/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
index b8f0e829ecbd26c14788899de066e533b6dbaf1e..764bc645241ed8e401d34d73b28d347d29ceed56 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
+++ b/src/exfat_fs.h
|
|
Kmods SIG |
9e3ffb |
@@ -408,7 +408,7 @@ int exfat_count_num_clusters(struct super_block *sb,
|
|
Kmods SIG |
9e3ffb |
int exfat_load_bitmap(struct super_block *sb);
|
|
Kmods SIG |
9e3ffb |
void exfat_free_bitmap(struct exfat_sb_info *sbi);
|
|
Kmods SIG |
9e3ffb |
int exfat_set_bitmap(struct inode *inode, unsigned int clu);
|
|
Kmods SIG |
9e3ffb |
-void exfat_clear_bitmap(struct inode *inode, unsigned int clu);
|
|
Kmods SIG |
9e3ffb |
+void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
|
|
Kmods SIG |
9e3ffb |
unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
|
|
Kmods SIG |
9e3ffb |
int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
diff --git a/src/fatent.c b/src/fatent.c
|
|
Kmods SIG |
9e3ffb |
index c3c9afee7418f1871a65757d79f8d4a13fe650c2..7b2e8af17193bfffe00b4e0b8b88cccb34b1970a 100644
|
|
Kmods SIG |
9e3ffb |
--- a/src/fatent.c
|
|
Kmods SIG |
9e3ffb |
+++ b/src/fatent.c
|
|
Kmods SIG |
9e3ffb |
@@ -157,6 +157,7 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|
Kmods SIG |
9e3ffb |
unsigned int clu;
|
|
Kmods SIG |
9e3ffb |
struct super_block *sb = inode->i_sb;
|
|
Kmods SIG |
9e3ffb |
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
|
Kmods SIG |
9e3ffb |
+ int cur_cmap_i, next_cmap_i;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
/* invalid cluster number */
|
|
Kmods SIG |
9e3ffb |
if (p_chain->dir == EXFAT_FREE_CLUSTER ||
|
|
Kmods SIG |
9e3ffb |
@@ -176,21 +177,51 @@ int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
clu = p_chain->dir;
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
+ cur_cmap_i = next_cmap_i =
|
|
Kmods SIG |
9e3ffb |
+ BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu));
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
|
Kmods SIG |
9e3ffb |
+ unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
|
|
Kmods SIG |
9e3ffb |
do {
|
|
Kmods SIG |
9e3ffb |
- exfat_clear_bitmap(inode, clu);
|
|
Kmods SIG |
9e3ffb |
- clu++;
|
|
Kmods SIG |
9e3ffb |
+ bool sync = false;
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
+ if (clu < last_cluster)
|
|
Kmods SIG |
9e3ffb |
+ next_cmap_i =
|
|
Kmods SIG |
9e3ffb |
+ BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu+1));
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
+ /* flush bitmap only if index would be changed or for last cluster */
|
|
Kmods SIG |
9e3ffb |
+ if (clu == last_cluster || cur_cmap_i != next_cmap_i) {
|
|
Kmods SIG |
9e3ffb |
+ sync = true;
|
|
Kmods SIG |
9e3ffb |
+ cur_cmap_i = next_cmap_i;
|
|
Kmods SIG |
9e3ffb |
+ }
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
+ exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
|
Kmods SIG |
9e3ffb |
+ clu++;
|
|
Kmods SIG |
9e3ffb |
num_clusters++;
|
|
Kmods SIG |
9e3ffb |
} while (num_clusters < p_chain->size);
|
|
Kmods SIG |
9e3ffb |
} else {
|
|
Kmods SIG |
9e3ffb |
do {
|
|
Kmods SIG |
9e3ffb |
- exfat_clear_bitmap(inode, clu);
|
|
Kmods SIG |
9e3ffb |
-
|
|
Kmods SIG |
9e3ffb |
- if (exfat_get_next_cluster(sb, &clu))
|
|
Kmods SIG |
9e3ffb |
- goto dec_used_clus;
|
|
Kmods SIG |
9e3ffb |
+ bool sync = false;
|
|
Kmods SIG |
9e3ffb |
+ unsigned int n_clu = clu;
|
|
Kmods SIG |
9e3ffb |
+ int err = exfat_get_next_cluster(sb, &n_clu);
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
+ if (err || n_clu == EXFAT_EOF_CLUSTER)
|
|
Kmods SIG |
9e3ffb |
+ sync = true;
|
|
Kmods SIG |
9e3ffb |
+ else
|
|
Kmods SIG |
9e3ffb |
+ next_cmap_i =
|
|
Kmods SIG |
9e3ffb |
+ BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(n_clu));
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
+ if (cur_cmap_i != next_cmap_i) {
|
|
Kmods SIG |
9e3ffb |
+ sync = true;
|
|
Kmods SIG |
9e3ffb |
+ cur_cmap_i = next_cmap_i;
|
|
Kmods SIG |
9e3ffb |
+ }
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
+ exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
|
|
Kmods SIG |
9e3ffb |
+ clu = n_clu;
|
|
Kmods SIG |
9e3ffb |
num_clusters++;
|
|
Kmods SIG |
9e3ffb |
+
|
|
Kmods SIG |
9e3ffb |
+ if (err)
|
|
Kmods SIG |
9e3ffb |
+ goto dec_used_clus;
|
|
Kmods SIG |
9e3ffb |
} while (clu != EXFAT_EOF_CLUSTER);
|
|
Kmods SIG |
9e3ffb |
}
|
|
Kmods SIG |
9e3ffb |
|
|
Kmods SIG |
9e3ffb |
--
|
|
Kmods SIG |
9e3ffb |
2.31.1
|
|
Kmods SIG |
9e3ffb |
|