Blame SOURCES/0066-exfat-improve-performance-of-exfat_free_cluster-when.patch

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