33 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
44 */
55
6+ #include <linux/version.h>
67#include <linux/blkdev.h>
78#include <linux/slab.h>
89#include <linux/buffer_head.h>
10+ #if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 4 , 0 )
11+ #include <linux/sched/signal.h>
12+ #endif
913
1014#include "exfat_raw.h"
1115#include "exfat_fs.h"
@@ -141,11 +145,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
141145 kfree (sbi -> vol_amap );
142146}
143147
144- /*
145- * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
146- * the cluster heap.
147- */
148- int exfat_set_bitmap (struct inode * inode , unsigned int clu )
148+ int exfat_set_bitmap (struct inode * inode , unsigned int clu , bool sync )
149149{
150150 int i , b ;
151151 unsigned int ent_idx ;
@@ -158,15 +158,11 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu)
158158 b = BITMAP_OFFSET_BIT_IN_SECTOR (sb , ent_idx );
159159
160160 set_bit_le (b , sbi -> vol_amap [i ]-> b_data );
161- exfat_update_bh (sbi -> vol_amap [i ], IS_DIRSYNC ( inode ) );
161+ exfat_update_bh (sbi -> vol_amap [i ], sync );
162162 return 0 ;
163163}
164164
165- /*
166- * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
167- * the cluster heap.
168- */
169- void exfat_clear_bitmap (struct inode * inode , unsigned int clu )
165+ void exfat_clear_bitmap (struct inode * inode , unsigned int clu , bool sync )
170166{
171167 int i , b ;
172168 unsigned int ent_idx ;
@@ -180,14 +176,13 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu)
180176 b = BITMAP_OFFSET_BIT_IN_SECTOR (sb , ent_idx );
181177
182178 clear_bit_le (b , sbi -> vol_amap [i ]-> b_data );
183- exfat_update_bh (sbi -> vol_amap [i ], IS_DIRSYNC ( inode ) );
179+ exfat_update_bh (sbi -> vol_amap [i ], sync );
184180
185181 if (opts -> discard ) {
186182 int ret_discard ;
187183
188184 ret_discard = sb_issue_discard (sb ,
189- exfat_cluster_to_sector (sbi , clu +
190- EXFAT_RESERVED_CLUSTERS ),
185+ exfat_cluster_to_sector (sbi , clu ),
191186 (1 << sbi -> sect_per_clus_bits ), GFP_NOFS , 0 );
192187
193188 if (ret_discard == - EOPNOTSUPP ) {
@@ -273,3 +268,83 @@ int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count)
273268 * ret_count = count ;
274269 return 0 ;
275270}
271+
272+ int exfat_trim_fs (struct inode * inode , struct fstrim_range * range )
273+ {
274+ unsigned int trim_begin , trim_end , count , next_free_clu ;
275+ u64 clu_start , clu_end , trim_minlen , trimmed_total = 0 ;
276+ struct super_block * sb = inode -> i_sb ;
277+ struct exfat_sb_info * sbi = EXFAT_SB (sb );
278+ int err = 0 ;
279+
280+ clu_start = max_t (u64 , range -> start >> sbi -> cluster_size_bits ,
281+ EXFAT_FIRST_CLUSTER );
282+ clu_end = clu_start + (range -> len >> sbi -> cluster_size_bits ) - 1 ;
283+ trim_minlen = range -> minlen >> sbi -> cluster_size_bits ;
284+
285+ if (clu_start >= sbi -> num_clusters || range -> len < sbi -> cluster_size )
286+ return - EINVAL ;
287+
288+ if (clu_end >= sbi -> num_clusters )
289+ clu_end = sbi -> num_clusters - 1 ;
290+
291+ mutex_lock (& sbi -> bitmap_lock );
292+
293+ trim_begin = trim_end = exfat_find_free_bitmap (sb , clu_start );
294+ if (trim_begin == EXFAT_EOF_CLUSTER )
295+ goto unlock ;
296+
297+ next_free_clu = exfat_find_free_bitmap (sb , trim_end + 1 );
298+ if (next_free_clu == EXFAT_EOF_CLUSTER )
299+ goto unlock ;
300+
301+ do {
302+ if (next_free_clu == trim_end + 1 ) {
303+ /* extend trim range for continuous free cluster */
304+ trim_end ++ ;
305+ } else {
306+ /* trim current range if it's larger than trim_minlen */
307+ count = trim_end - trim_begin + 1 ;
308+ if (count >= trim_minlen ) {
309+ err = sb_issue_discard (sb ,
310+ exfat_cluster_to_sector (sbi , trim_begin ),
311+ count * sbi -> sect_per_clus , GFP_NOFS , 0 );
312+ if (err )
313+ goto unlock ;
314+
315+ trimmed_total += count ;
316+ }
317+
318+ /* set next start point of the free hole */
319+ trim_begin = trim_end = next_free_clu ;
320+ }
321+
322+ if (next_free_clu >= clu_end )
323+ break ;
324+
325+ if (fatal_signal_pending (current )) {
326+ err = - ERESTARTSYS ;
327+ goto unlock ;
328+ }
329+
330+ next_free_clu = exfat_find_free_bitmap (sb , next_free_clu + 1 );
331+ } while (next_free_clu != EXFAT_EOF_CLUSTER &&
332+ next_free_clu > trim_end );
333+
334+ /* try to trim remainder */
335+ count = trim_end - trim_begin + 1 ;
336+ if (count >= trim_minlen ) {
337+ err = sb_issue_discard (sb , exfat_cluster_to_sector (sbi , trim_begin ),
338+ count * sbi -> sect_per_clus , GFP_NOFS , 0 );
339+ if (err )
340+ goto unlock ;
341+
342+ trimmed_total += count ;
343+ }
344+
345+ unlock :
346+ mutex_unlock (& sbi -> bitmap_lock );
347+ range -> len = trimmed_total << sbi -> cluster_size_bits ;
348+
349+ return err ;
350+ }
0 commit comments