Skip to content

Commit a36e0ab

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: support batch discard of clusters when freeing clusters
If the discard mount option is enabled, the file's clusters are discarded when the clusters are freed. Discarding clusters one by one will significantly reduce performance. Poor performance may cause soft lockup when lots of clusters are freed. This commit improves performance by discarding contiguous clusters in batches. Measure the performance by: # truncate -s 80G /mnt/file # time rm /mnt/file Without this commit: real 4m46.183s user 0m0.000s sys 0m12.863s With this commit: real 0m1.661s user 0m0.000s sys 0m0.017s Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent 1a9239b commit a36e0ab

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

fs/exfat/balloc.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
147147
unsigned int ent_idx;
148148
struct super_block *sb = inode->i_sb;
149149
struct exfat_sb_info *sbi = EXFAT_SB(sb);
150-
struct exfat_mount_options *opts = &sbi->options;
151150

152151
if (!is_valid_cluster(sbi, clu))
153152
return -EIO;
@@ -163,19 +162,6 @@ int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
163162

164163
exfat_update_bh(sbi->vol_amap[i], sync);
165164

166-
if (opts->discard) {
167-
int ret_discard;
168-
169-
ret_discard = sb_issue_discard(sb,
170-
exfat_cluster_to_sector(sbi, clu),
171-
(1 << sbi->sect_per_clus_bits), GFP_NOFS, 0);
172-
173-
if (ret_discard == -EOPNOTSUPP) {
174-
exfat_err(sb, "discard not supported by device, disabling");
175-
opts->discard = 0;
176-
}
177-
}
178-
179165
return 0;
180166
}
181167

fs/exfat/fatent.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@ int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
144144
return 0;
145145
}
146146

147+
static inline void exfat_discard_cluster(struct super_block *sb,
148+
unsigned int clu, unsigned int num_clusters)
149+
{
150+
int ret;
151+
struct exfat_sb_info *sbi = EXFAT_SB(sb);
152+
153+
ret = sb_issue_discard(sb, exfat_cluster_to_sector(sbi, clu),
154+
sbi->sect_per_clus * num_clusters, GFP_NOFS, 0);
155+
if (ret == -EOPNOTSUPP) {
156+
exfat_err(sb, "discard not supported by device, disabling");
157+
sbi->options.discard = 0;
158+
}
159+
}
160+
147161
/* This function must be called with bitmap_lock held */
148162
static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
149163
{
@@ -196,7 +210,12 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
196210
clu++;
197211
num_clusters++;
198212
} while (num_clusters < p_chain->size);
213+
214+
if (sbi->options.discard)
215+
exfat_discard_cluster(sb, p_chain->dir, p_chain->size);
199216
} else {
217+
unsigned int nr_clu = 1;
218+
200219
do {
201220
bool sync = false;
202221
unsigned int n_clu = clu;
@@ -215,6 +234,16 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
215234

216235
if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))))
217236
break;
237+
238+
if (sbi->options.discard) {
239+
if (n_clu == clu + 1)
240+
nr_clu++;
241+
else {
242+
exfat_discard_cluster(sb, clu - nr_clu + 1, nr_clu);
243+
nr_clu = 1;
244+
}
245+
}
246+
218247
clu = n_clu;
219248
num_clusters++;
220249

0 commit comments

Comments
 (0)