11e49a94cSNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later
21e49a94cSNamjae Jeon /*
31e49a94cSNamjae Jeon * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
41e49a94cSNamjae Jeon */
51e49a94cSNamjae Jeon
61e49a94cSNamjae Jeon #include <linux/blkdev.h>
71e49a94cSNamjae Jeon #include <linux/slab.h>
81e49a94cSNamjae Jeon #include <linux/buffer_head.h>
91e49a94cSNamjae Jeon
101e49a94cSNamjae Jeon #include "exfat_raw.h"
111e49a94cSNamjae Jeon #include "exfat_fs.h"
121e49a94cSNamjae Jeon
131e49a94cSNamjae Jeon static const unsigned char free_bit[] = {
141e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/* 0 ~ 19*/
151e49a94cSNamjae Jeon 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,/* 20 ~ 39*/
161e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/* 40 ~ 59*/
171e49a94cSNamjae Jeon 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/* 60 ~ 79*/
181e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,/* 80 ~ 99*/
191e49a94cSNamjae Jeon 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,/*100 ~ 119*/
201e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*120 ~ 139*/
211e49a94cSNamjae Jeon 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,/*140 ~ 159*/
221e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,/*160 ~ 179*/
231e49a94cSNamjae Jeon 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,/*180 ~ 199*/
241e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,/*200 ~ 219*/
251e49a94cSNamjae Jeon 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,/*220 ~ 239*/
261e49a94cSNamjae Jeon 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /*240 ~ 254*/
271e49a94cSNamjae Jeon };
281e49a94cSNamjae Jeon
291e49a94cSNamjae Jeon static const unsigned char used_bit[] = {
301e49a94cSNamjae Jeon 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,/* 0 ~ 19*/
311e49a94cSNamjae Jeon 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,/* 20 ~ 39*/
321e49a94cSNamjae Jeon 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,/* 40 ~ 59*/
331e49a94cSNamjae Jeon 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,/* 60 ~ 79*/
341e49a94cSNamjae Jeon 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,/* 80 ~ 99*/
351e49a94cSNamjae Jeon 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,/*100 ~ 119*/
361e49a94cSNamjae Jeon 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,/*120 ~ 139*/
371e49a94cSNamjae Jeon 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,/*140 ~ 159*/
381e49a94cSNamjae Jeon 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,/*160 ~ 179*/
391e49a94cSNamjae Jeon 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,/*180 ~ 199*/
401e49a94cSNamjae Jeon 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,/*200 ~ 219*/
411e49a94cSNamjae Jeon 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,/*220 ~ 239*/
421e49a94cSNamjae Jeon 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /*240 ~ 255*/
431e49a94cSNamjae Jeon };
441e49a94cSNamjae Jeon
451e49a94cSNamjae Jeon /*
461e49a94cSNamjae Jeon * Allocation Bitmap Management Functions
471e49a94cSNamjae Jeon */
exfat_allocate_bitmap(struct super_block * sb,struct exfat_dentry * ep)481e49a94cSNamjae Jeon static int exfat_allocate_bitmap(struct super_block *sb,
491e49a94cSNamjae Jeon struct exfat_dentry *ep)
501e49a94cSNamjae Jeon {
511e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
521e49a94cSNamjae Jeon long long map_size;
531e49a94cSNamjae Jeon unsigned int i, need_map_size;
541e49a94cSNamjae Jeon sector_t sector;
551e49a94cSNamjae Jeon
561e49a94cSNamjae Jeon sbi->map_clu = le32_to_cpu(ep->dentry.bitmap.start_clu);
571e49a94cSNamjae Jeon map_size = le64_to_cpu(ep->dentry.bitmap.size);
581e49a94cSNamjae Jeon need_map_size = ((EXFAT_DATA_CLUSTER_COUNT(sbi) - 1) / BITS_PER_BYTE)
591e49a94cSNamjae Jeon + 1;
601e49a94cSNamjae Jeon if (need_map_size != map_size) {
61d1727d55SJoe Perches exfat_err(sb, "bogus allocation bitmap size(need : %u, cur : %lld)",
621e49a94cSNamjae Jeon need_map_size, map_size);
631e49a94cSNamjae Jeon /*
641e49a94cSNamjae Jeon * Only allowed when bogus allocation
651e49a94cSNamjae Jeon * bitmap size is large
661e49a94cSNamjae Jeon */
671e49a94cSNamjae Jeon if (need_map_size > map_size)
681e49a94cSNamjae Jeon return -EIO;
691e49a94cSNamjae Jeon }
701e49a94cSNamjae Jeon sbi->map_sectors = ((need_map_size - 1) >>
711e49a94cSNamjae Jeon (sb->s_blocksize_bits)) + 1;
72daf60d6cSgaoming sbi->vol_amap = kvmalloc_array(sbi->map_sectors,
731e49a94cSNamjae Jeon sizeof(struct buffer_head *), GFP_KERNEL);
741e49a94cSNamjae Jeon if (!sbi->vol_amap)
751e49a94cSNamjae Jeon return -ENOMEM;
761e49a94cSNamjae Jeon
771e49a94cSNamjae Jeon sector = exfat_cluster_to_sector(sbi, sbi->map_clu);
781e49a94cSNamjae Jeon for (i = 0; i < sbi->map_sectors; i++) {
791e49a94cSNamjae Jeon sbi->vol_amap[i] = sb_bread(sb, sector + i);
801e49a94cSNamjae Jeon if (!sbi->vol_amap[i]) {
811e49a94cSNamjae Jeon /* release all buffers and free vol_amap */
821e49a94cSNamjae Jeon int j = 0;
831e49a94cSNamjae Jeon
841e49a94cSNamjae Jeon while (j < i)
851e49a94cSNamjae Jeon brelse(sbi->vol_amap[j++]);
861e49a94cSNamjae Jeon
87daf60d6cSgaoming kvfree(sbi->vol_amap);
881e49a94cSNamjae Jeon sbi->vol_amap = NULL;
891e49a94cSNamjae Jeon return -EIO;
901e49a94cSNamjae Jeon }
911e49a94cSNamjae Jeon }
921e49a94cSNamjae Jeon
931e49a94cSNamjae Jeon return 0;
941e49a94cSNamjae Jeon }
951e49a94cSNamjae Jeon
exfat_load_bitmap(struct super_block * sb)961e49a94cSNamjae Jeon int exfat_load_bitmap(struct super_block *sb)
971e49a94cSNamjae Jeon {
981e49a94cSNamjae Jeon unsigned int i, type;
991e49a94cSNamjae Jeon struct exfat_chain clu;
1001e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
1011e49a94cSNamjae Jeon
1021e49a94cSNamjae Jeon exfat_chain_set(&clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
1031e49a94cSNamjae Jeon while (clu.dir != EXFAT_EOF_CLUSTER) {
1041e49a94cSNamjae Jeon for (i = 0; i < sbi->dentries_per_clu; i++) {
1051e49a94cSNamjae Jeon struct exfat_dentry *ep;
1061e49a94cSNamjae Jeon struct buffer_head *bh;
1071e49a94cSNamjae Jeon
108c71510b3SYuezhang.Mo ep = exfat_get_dentry(sb, &clu, i, &bh);
1091e49a94cSNamjae Jeon if (!ep)
1101e49a94cSNamjae Jeon return -EIO;
1111e49a94cSNamjae Jeon
1121e49a94cSNamjae Jeon type = exfat_get_entry_type(ep);
113bf0b3b35SYuezhang Mo if (type == TYPE_BITMAP &&
114bf0b3b35SYuezhang Mo ep->dentry.bitmap.flags == 0x0) {
1151e49a94cSNamjae Jeon int err;
1161e49a94cSNamjae Jeon
1171e49a94cSNamjae Jeon err = exfat_allocate_bitmap(sb, ep);
1181e49a94cSNamjae Jeon brelse(bh);
1191e49a94cSNamjae Jeon return err;
1201e49a94cSNamjae Jeon }
1211e49a94cSNamjae Jeon brelse(bh);
122bf0b3b35SYuezhang Mo
123bf0b3b35SYuezhang Mo if (type == TYPE_UNUSED)
124bf0b3b35SYuezhang Mo return -EINVAL;
1251e49a94cSNamjae Jeon }
1261e49a94cSNamjae Jeon
1271e49a94cSNamjae Jeon if (exfat_get_next_cluster(sb, &clu.dir))
1281e49a94cSNamjae Jeon return -EIO;
1291e49a94cSNamjae Jeon }
1301e49a94cSNamjae Jeon
1311e49a94cSNamjae Jeon return -EINVAL;
1321e49a94cSNamjae Jeon }
1331e49a94cSNamjae Jeon
exfat_free_bitmap(struct exfat_sb_info * sbi)1341e49a94cSNamjae Jeon void exfat_free_bitmap(struct exfat_sb_info *sbi)
1351e49a94cSNamjae Jeon {
1361e49a94cSNamjae Jeon int i;
1371e49a94cSNamjae Jeon
1381e49a94cSNamjae Jeon for (i = 0; i < sbi->map_sectors; i++)
1391e49a94cSNamjae Jeon __brelse(sbi->vol_amap[i]);
1401e49a94cSNamjae Jeon
141daf60d6cSgaoming kvfree(sbi->vol_amap);
1421e49a94cSNamjae Jeon }
1431e49a94cSNamjae Jeon
exfat_set_bitmap(struct inode * inode,unsigned int clu,bool sync)14423befe49SHyeongseok Kim int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
1451e49a94cSNamjae Jeon {
1461e49a94cSNamjae Jeon int i, b;
1471e49a94cSNamjae Jeon unsigned int ent_idx;
1481e49a94cSNamjae Jeon struct super_block *sb = inode->i_sb;
1491e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
1501e49a94cSNamjae Jeon
15164ba4b15STadeusz Struk if (!is_valid_cluster(sbi, clu))
15264ba4b15STadeusz Struk return -EINVAL;
15364ba4b15STadeusz Struk
1541e49a94cSNamjae Jeon ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
1551e49a94cSNamjae Jeon i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
1561e49a94cSNamjae Jeon b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
1571e49a94cSNamjae Jeon
1581e49a94cSNamjae Jeon set_bit_le(b, sbi->vol_amap[i]->b_data);
15923befe49SHyeongseok Kim exfat_update_bh(sbi->vol_amap[i], sync);
1601e49a94cSNamjae Jeon return 0;
1611e49a94cSNamjae Jeon }
1621e49a94cSNamjae Jeon
exfat_clear_bitmap(struct inode * inode,unsigned int clu,bool sync)163*747de766SNamjae Jeon int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
1641e49a94cSNamjae Jeon {
1651e49a94cSNamjae Jeon int i, b;
1661e49a94cSNamjae Jeon unsigned int ent_idx;
1671e49a94cSNamjae Jeon struct super_block *sb = inode->i_sb;
1681e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
1691e49a94cSNamjae Jeon struct exfat_mount_options *opts = &sbi->options;
1701e49a94cSNamjae Jeon
17164ba4b15STadeusz Struk if (!is_valid_cluster(sbi, clu))
172*747de766SNamjae Jeon return -EIO;
17364ba4b15STadeusz Struk
1741e49a94cSNamjae Jeon ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
1751e49a94cSNamjae Jeon i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
1761e49a94cSNamjae Jeon b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx);
1771e49a94cSNamjae Jeon
178*747de766SNamjae Jeon if (!test_bit_le(b, sbi->vol_amap[i]->b_data))
179*747de766SNamjae Jeon return -EIO;
180*747de766SNamjae Jeon
1811e49a94cSNamjae Jeon clear_bit_le(b, sbi->vol_amap[i]->b_data);
182*747de766SNamjae Jeon
183f728760aSHyeongseok Kim exfat_update_bh(sbi->vol_amap[i], sync);
1841e49a94cSNamjae Jeon
1851e49a94cSNamjae Jeon if (opts->discard) {
1861e49a94cSNamjae Jeon int ret_discard;
1871e49a94cSNamjae Jeon
1881e49a94cSNamjae Jeon ret_discard = sb_issue_discard(sb,
18977edfc6eSHyeongseok Kim exfat_cluster_to_sector(sbi, clu),
1901e49a94cSNamjae Jeon (1 << sbi->sect_per_clus_bits), GFP_NOFS, 0);
1911e49a94cSNamjae Jeon
1921e49a94cSNamjae Jeon if (ret_discard == -EOPNOTSUPP) {
193d1727d55SJoe Perches exfat_err(sb, "discard not supported by device, disabling");
1941e49a94cSNamjae Jeon opts->discard = 0;
1951e49a94cSNamjae Jeon }
1961e49a94cSNamjae Jeon }
197*747de766SNamjae Jeon
198*747de766SNamjae Jeon return 0;
1991e49a94cSNamjae Jeon }
2001e49a94cSNamjae Jeon
2011e49a94cSNamjae Jeon /*
2021e49a94cSNamjae Jeon * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
2031e49a94cSNamjae Jeon * the cluster heap.
2041e49a94cSNamjae Jeon */
exfat_find_free_bitmap(struct super_block * sb,unsigned int clu)2051e49a94cSNamjae Jeon unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu)
2061e49a94cSNamjae Jeon {
2071e49a94cSNamjae Jeon unsigned int i, map_i, map_b, ent_idx;
2081e49a94cSNamjae Jeon unsigned int clu_base, clu_free;
2091e49a94cSNamjae Jeon unsigned char k, clu_mask;
2101e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
2111e49a94cSNamjae Jeon
2121e49a94cSNamjae Jeon WARN_ON(clu < EXFAT_FIRST_CLUSTER);
2131e49a94cSNamjae Jeon ent_idx = CLUSTER_TO_BITMAP_ENT(clu);
2141e49a94cSNamjae Jeon clu_base = BITMAP_ENT_TO_CLUSTER(ent_idx & ~(BITS_PER_BYTE_MASK));
2151e49a94cSNamjae Jeon clu_mask = IGNORED_BITS_REMAINED(clu, clu_base);
2161e49a94cSNamjae Jeon
2171e49a94cSNamjae Jeon map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx);
2181e49a94cSNamjae Jeon map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, ent_idx);
2191e49a94cSNamjae Jeon
2201e49a94cSNamjae Jeon for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters;
2211e49a94cSNamjae Jeon i += BITS_PER_BYTE) {
2221e49a94cSNamjae Jeon k = *(sbi->vol_amap[map_i]->b_data + map_b);
2231e49a94cSNamjae Jeon if (clu_mask > 0) {
2241e49a94cSNamjae Jeon k |= clu_mask;
2251e49a94cSNamjae Jeon clu_mask = 0;
2261e49a94cSNamjae Jeon }
2271e49a94cSNamjae Jeon if (k < 0xFF) {
2281e49a94cSNamjae Jeon clu_free = clu_base + free_bit[k];
2291e49a94cSNamjae Jeon if (clu_free < sbi->num_clusters)
2301e49a94cSNamjae Jeon return clu_free;
2311e49a94cSNamjae Jeon }
2321e49a94cSNamjae Jeon clu_base += BITS_PER_BYTE;
2331e49a94cSNamjae Jeon
2341e49a94cSNamjae Jeon if (++map_b >= sb->s_blocksize ||
2351e49a94cSNamjae Jeon clu_base >= sbi->num_clusters) {
2361e49a94cSNamjae Jeon if (++map_i >= sbi->map_sectors) {
2371e49a94cSNamjae Jeon clu_base = EXFAT_FIRST_CLUSTER;
2381e49a94cSNamjae Jeon map_i = 0;
2391e49a94cSNamjae Jeon }
2401e49a94cSNamjae Jeon map_b = 0;
2411e49a94cSNamjae Jeon }
2421e49a94cSNamjae Jeon }
2431e49a94cSNamjae Jeon
2441e49a94cSNamjae Jeon return EXFAT_EOF_CLUSTER;
2451e49a94cSNamjae Jeon }
2461e49a94cSNamjae Jeon
exfat_count_used_clusters(struct super_block * sb,unsigned int * ret_count)2471e49a94cSNamjae Jeon int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count)
2481e49a94cSNamjae Jeon {
2491e49a94cSNamjae Jeon struct exfat_sb_info *sbi = EXFAT_SB(sb);
2501e49a94cSNamjae Jeon unsigned int count = 0;
2511e49a94cSNamjae Jeon unsigned int i, map_i = 0, map_b = 0;
2521e49a94cSNamjae Jeon unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);
2531e49a94cSNamjae Jeon unsigned int last_mask = total_clus & BITS_PER_BYTE_MASK;
2541e49a94cSNamjae Jeon unsigned char clu_bits;
2551e49a94cSNamjae Jeon const unsigned char last_bit_mask[] = {0, 0b00000001, 0b00000011,
2561e49a94cSNamjae Jeon 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111};
2571e49a94cSNamjae Jeon
2581e49a94cSNamjae Jeon total_clus &= ~last_mask;
2591e49a94cSNamjae Jeon for (i = 0; i < total_clus; i += BITS_PER_BYTE) {
2601e49a94cSNamjae Jeon clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
2611e49a94cSNamjae Jeon count += used_bit[clu_bits];
2621e49a94cSNamjae Jeon if (++map_b >= (unsigned int)sb->s_blocksize) {
2631e49a94cSNamjae Jeon map_i++;
2641e49a94cSNamjae Jeon map_b = 0;
2651e49a94cSNamjae Jeon }
2661e49a94cSNamjae Jeon }
2671e49a94cSNamjae Jeon
2681e49a94cSNamjae Jeon if (last_mask) {
2691e49a94cSNamjae Jeon clu_bits = *(sbi->vol_amap[map_i]->b_data + map_b);
2701e49a94cSNamjae Jeon clu_bits &= last_bit_mask[last_mask];
2711e49a94cSNamjae Jeon count += used_bit[clu_bits];
2721e49a94cSNamjae Jeon }
2731e49a94cSNamjae Jeon
2741e49a94cSNamjae Jeon *ret_count = count;
2751e49a94cSNamjae Jeon return 0;
2761e49a94cSNamjae Jeon }
277654762dfSHyeongseok Kim
exfat_trim_fs(struct inode * inode,struct fstrim_range * range)278654762dfSHyeongseok Kim int exfat_trim_fs(struct inode *inode, struct fstrim_range *range)
279654762dfSHyeongseok Kim {
280654762dfSHyeongseok Kim unsigned int trim_begin, trim_end, count, next_free_clu;
281654762dfSHyeongseok Kim u64 clu_start, clu_end, trim_minlen, trimmed_total = 0;
282654762dfSHyeongseok Kim struct super_block *sb = inode->i_sb;
283654762dfSHyeongseok Kim struct exfat_sb_info *sbi = EXFAT_SB(sb);
284654762dfSHyeongseok Kim int err = 0;
285654762dfSHyeongseok Kim
286654762dfSHyeongseok Kim clu_start = max_t(u64, range->start >> sbi->cluster_size_bits,
287654762dfSHyeongseok Kim EXFAT_FIRST_CLUSTER);
288654762dfSHyeongseok Kim clu_end = clu_start + (range->len >> sbi->cluster_size_bits) - 1;
289654762dfSHyeongseok Kim trim_minlen = range->minlen >> sbi->cluster_size_bits;
290654762dfSHyeongseok Kim
291654762dfSHyeongseok Kim if (clu_start >= sbi->num_clusters || range->len < sbi->cluster_size)
292654762dfSHyeongseok Kim return -EINVAL;
293654762dfSHyeongseok Kim
294654762dfSHyeongseok Kim if (clu_end >= sbi->num_clusters)
295654762dfSHyeongseok Kim clu_end = sbi->num_clusters - 1;
296654762dfSHyeongseok Kim
297654762dfSHyeongseok Kim mutex_lock(&sbi->bitmap_lock);
298654762dfSHyeongseok Kim
299654762dfSHyeongseok Kim trim_begin = trim_end = exfat_find_free_bitmap(sb, clu_start);
300654762dfSHyeongseok Kim if (trim_begin == EXFAT_EOF_CLUSTER)
301654762dfSHyeongseok Kim goto unlock;
302654762dfSHyeongseok Kim
303654762dfSHyeongseok Kim next_free_clu = exfat_find_free_bitmap(sb, trim_end + 1);
304654762dfSHyeongseok Kim if (next_free_clu == EXFAT_EOF_CLUSTER)
305654762dfSHyeongseok Kim goto unlock;
306654762dfSHyeongseok Kim
307654762dfSHyeongseok Kim do {
308654762dfSHyeongseok Kim if (next_free_clu == trim_end + 1) {
309654762dfSHyeongseok Kim /* extend trim range for continuous free cluster */
310654762dfSHyeongseok Kim trim_end++;
311654762dfSHyeongseok Kim } else {
312654762dfSHyeongseok Kim /* trim current range if it's larger than trim_minlen */
313654762dfSHyeongseok Kim count = trim_end - trim_begin + 1;
314654762dfSHyeongseok Kim if (count >= trim_minlen) {
315654762dfSHyeongseok Kim err = sb_issue_discard(sb,
316654762dfSHyeongseok Kim exfat_cluster_to_sector(sbi, trim_begin),
317654762dfSHyeongseok Kim count * sbi->sect_per_clus, GFP_NOFS, 0);
318654762dfSHyeongseok Kim if (err)
319654762dfSHyeongseok Kim goto unlock;
320654762dfSHyeongseok Kim
321654762dfSHyeongseok Kim trimmed_total += count;
322654762dfSHyeongseok Kim }
323654762dfSHyeongseok Kim
324654762dfSHyeongseok Kim /* set next start point of the free hole */
325654762dfSHyeongseok Kim trim_begin = trim_end = next_free_clu;
326654762dfSHyeongseok Kim }
327654762dfSHyeongseok Kim
328654762dfSHyeongseok Kim if (next_free_clu >= clu_end)
329654762dfSHyeongseok Kim break;
330654762dfSHyeongseok Kim
331654762dfSHyeongseok Kim if (fatal_signal_pending(current)) {
332654762dfSHyeongseok Kim err = -ERESTARTSYS;
333654762dfSHyeongseok Kim goto unlock;
334654762dfSHyeongseok Kim }
335654762dfSHyeongseok Kim
336654762dfSHyeongseok Kim next_free_clu = exfat_find_free_bitmap(sb, next_free_clu + 1);
337654762dfSHyeongseok Kim } while (next_free_clu != EXFAT_EOF_CLUSTER &&
338654762dfSHyeongseok Kim next_free_clu > trim_end);
339654762dfSHyeongseok Kim
340654762dfSHyeongseok Kim /* try to trim remainder */
341654762dfSHyeongseok Kim count = trim_end - trim_begin + 1;
342654762dfSHyeongseok Kim if (count >= trim_minlen) {
343654762dfSHyeongseok Kim err = sb_issue_discard(sb, exfat_cluster_to_sector(sbi, trim_begin),
344654762dfSHyeongseok Kim count * sbi->sect_per_clus, GFP_NOFS, 0);
345654762dfSHyeongseok Kim if (err)
346654762dfSHyeongseok Kim goto unlock;
347654762dfSHyeongseok Kim
348654762dfSHyeongseok Kim trimmed_total += count;
349654762dfSHyeongseok Kim }
350654762dfSHyeongseok Kim
351654762dfSHyeongseok Kim unlock:
352654762dfSHyeongseok Kim mutex_unlock(&sbi->bitmap_lock);
353654762dfSHyeongseok Kim range->len = trimmed_total << sbi->cluster_size_bits;
354654762dfSHyeongseok Kim
355654762dfSHyeongseok Kim return err;
356654762dfSHyeongseok Kim }
357