xref: /openbmc/linux/fs/exfat/fatent.c (revision d5c514b6)
131023864SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later
231023864SNamjae Jeon /*
331023864SNamjae Jeon  * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
431023864SNamjae Jeon  */
531023864SNamjae Jeon 
631023864SNamjae Jeon #include <linux/slab.h>
731023864SNamjae Jeon #include <asm/unaligned.h>
831023864SNamjae Jeon #include <linux/buffer_head.h>
91b613838SYuezhang Mo #include <linux/blkdev.h>
1031023864SNamjae Jeon 
1131023864SNamjae Jeon #include "exfat_raw.h"
1231023864SNamjae Jeon #include "exfat_fs.h"
1331023864SNamjae Jeon 
exfat_mirror_bh(struct super_block * sb,sector_t sec,struct buffer_head * bh)1431023864SNamjae Jeon static int exfat_mirror_bh(struct super_block *sb, sector_t sec,
1531023864SNamjae Jeon 		struct buffer_head *bh)
1631023864SNamjae Jeon {
1731023864SNamjae Jeon 	struct buffer_head *c_bh;
1831023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
1931023864SNamjae Jeon 	sector_t sec2;
2031023864SNamjae Jeon 	int err = 0;
2131023864SNamjae Jeon 
2231023864SNamjae Jeon 	if (sbi->FAT2_start_sector != sbi->FAT1_start_sector) {
2331023864SNamjae Jeon 		sec2 = sec - sbi->FAT1_start_sector + sbi->FAT2_start_sector;
2431023864SNamjae Jeon 		c_bh = sb_getblk(sb, sec2);
2531023864SNamjae Jeon 		if (!c_bh)
2631023864SNamjae Jeon 			return -ENOMEM;
2731023864SNamjae Jeon 		memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
2831023864SNamjae Jeon 		set_buffer_uptodate(c_bh);
2931023864SNamjae Jeon 		mark_buffer_dirty(c_bh);
3031023864SNamjae Jeon 		if (sb->s_flags & SB_SYNCHRONOUS)
3131023864SNamjae Jeon 			err = sync_dirty_buffer(c_bh);
3231023864SNamjae Jeon 		brelse(c_bh);
3331023864SNamjae Jeon 	}
3431023864SNamjae Jeon 
3531023864SNamjae Jeon 	return err;
3631023864SNamjae Jeon }
3731023864SNamjae Jeon 
__exfat_ent_get(struct super_block * sb,unsigned int loc,unsigned int * content)3831023864SNamjae Jeon static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
3931023864SNamjae Jeon 		unsigned int *content)
4031023864SNamjae Jeon {
4131023864SNamjae Jeon 	unsigned int off;
4231023864SNamjae Jeon 	sector_t sec;
4331023864SNamjae Jeon 	struct buffer_head *bh;
4431023864SNamjae Jeon 
4531023864SNamjae Jeon 	sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
4631023864SNamjae Jeon 	off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
4731023864SNamjae Jeon 
4831023864SNamjae Jeon 	bh = sb_bread(sb, sec);
4931023864SNamjae Jeon 	if (!bh)
5031023864SNamjae Jeon 		return -EIO;
5131023864SNamjae Jeon 
5231023864SNamjae Jeon 	*content = le32_to_cpu(*(__le32 *)(&bh->b_data[off]));
5331023864SNamjae Jeon 
5431023864SNamjae Jeon 	/* remap reserved clusters to simplify code */
5531023864SNamjae Jeon 	if (*content > EXFAT_BAD_CLUSTER)
5631023864SNamjae Jeon 		*content = EXFAT_EOF_CLUSTER;
5731023864SNamjae Jeon 
5831023864SNamjae Jeon 	brelse(bh);
5931023864SNamjae Jeon 	return 0;
6031023864SNamjae Jeon }
6131023864SNamjae Jeon 
exfat_ent_set(struct super_block * sb,unsigned int loc,unsigned int content)6231023864SNamjae Jeon int exfat_ent_set(struct super_block *sb, unsigned int loc,
6331023864SNamjae Jeon 		unsigned int content)
6431023864SNamjae Jeon {
6531023864SNamjae Jeon 	unsigned int off;
6631023864SNamjae Jeon 	sector_t sec;
6731023864SNamjae Jeon 	__le32 *fat_entry;
6831023864SNamjae Jeon 	struct buffer_head *bh;
6931023864SNamjae Jeon 
7031023864SNamjae Jeon 	sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
7131023864SNamjae Jeon 	off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
7231023864SNamjae Jeon 
7331023864SNamjae Jeon 	bh = sb_bread(sb, sec);
7431023864SNamjae Jeon 	if (!bh)
7531023864SNamjae Jeon 		return -EIO;
7631023864SNamjae Jeon 
7731023864SNamjae Jeon 	fat_entry = (__le32 *)&(bh->b_data[off]);
7831023864SNamjae Jeon 	*fat_entry = cpu_to_le32(content);
792c7f8937STetsuhiro Kohada 	exfat_update_bh(bh, sb->s_flags & SB_SYNCHRONOUS);
8031023864SNamjae Jeon 	exfat_mirror_bh(sb, sec, bh);
8131023864SNamjae Jeon 	brelse(bh);
8231023864SNamjae Jeon 	return 0;
8331023864SNamjae Jeon }
8431023864SNamjae Jeon 
exfat_ent_get(struct super_block * sb,unsigned int loc,unsigned int * content)8531023864SNamjae Jeon int exfat_ent_get(struct super_block *sb, unsigned int loc,
8631023864SNamjae Jeon 		unsigned int *content)
8731023864SNamjae Jeon {
8831023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
8931023864SNamjae Jeon 	int err;
9031023864SNamjae Jeon 
9131023864SNamjae Jeon 	if (!is_valid_cluster(sbi, loc)) {
9231023864SNamjae Jeon 		exfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)",
9331023864SNamjae Jeon 			loc);
9431023864SNamjae Jeon 		return -EIO;
9531023864SNamjae Jeon 	}
9631023864SNamjae Jeon 
9731023864SNamjae Jeon 	err = __exfat_ent_get(sb, loc, content);
9831023864SNamjae Jeon 	if (err) {
9931023864SNamjae Jeon 		exfat_fs_error(sb,
10031023864SNamjae Jeon 			"failed to access to FAT (entry 0x%08x, err:%d)",
10131023864SNamjae Jeon 			loc, err);
10231023864SNamjae Jeon 		return err;
10331023864SNamjae Jeon 	}
10431023864SNamjae Jeon 
10531023864SNamjae Jeon 	if (*content == EXFAT_FREE_CLUSTER) {
10631023864SNamjae Jeon 		exfat_fs_error(sb,
10731023864SNamjae Jeon 			"invalid access to FAT free cluster (entry 0x%08x)",
10831023864SNamjae Jeon 			loc);
10931023864SNamjae Jeon 		return -EIO;
11031023864SNamjae Jeon 	}
11131023864SNamjae Jeon 
11231023864SNamjae Jeon 	if (*content == EXFAT_BAD_CLUSTER) {
11331023864SNamjae Jeon 		exfat_fs_error(sb,
11431023864SNamjae Jeon 			"invalid access to FAT bad cluster (entry 0x%08x)",
11531023864SNamjae Jeon 			loc);
11631023864SNamjae Jeon 		return -EIO;
11731023864SNamjae Jeon 	}
11831023864SNamjae Jeon 
11931023864SNamjae Jeon 	if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) {
12031023864SNamjae Jeon 		exfat_fs_error(sb,
12131023864SNamjae Jeon 			"invalid access to FAT (entry 0x%08x) bogus content (0x%08x)",
12231023864SNamjae Jeon 			loc, *content);
12331023864SNamjae Jeon 		return -EIO;
12431023864SNamjae Jeon 	}
12531023864SNamjae Jeon 
12631023864SNamjae Jeon 	return 0;
12731023864SNamjae Jeon }
12831023864SNamjae Jeon 
exfat_chain_cont_cluster(struct super_block * sb,unsigned int chain,unsigned int len)12931023864SNamjae Jeon int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
13031023864SNamjae Jeon 		unsigned int len)
13131023864SNamjae Jeon {
13231023864SNamjae Jeon 	if (!len)
13331023864SNamjae Jeon 		return 0;
13431023864SNamjae Jeon 
13531023864SNamjae Jeon 	while (len > 1) {
13631023864SNamjae Jeon 		if (exfat_ent_set(sb, chain, chain + 1))
13731023864SNamjae Jeon 			return -EIO;
13831023864SNamjae Jeon 		chain++;
13931023864SNamjae Jeon 		len--;
14031023864SNamjae Jeon 	}
14131023864SNamjae Jeon 
14231023864SNamjae Jeon 	if (exfat_ent_set(sb, chain, EXFAT_EOF_CLUSTER))
14331023864SNamjae Jeon 		return -EIO;
14431023864SNamjae Jeon 	return 0;
14531023864SNamjae Jeon }
14631023864SNamjae Jeon 
1475c2d7285SHyeongseok Kim /* This function must be called with bitmap_lock held */
__exfat_free_cluster(struct inode * inode,struct exfat_chain * p_chain)1485c2d7285SHyeongseok Kim static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
14931023864SNamjae Jeon {
15031023864SNamjae Jeon 	struct super_block *sb = inode->i_sb;
15131023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
152f728760aSHyeongseok Kim 	int cur_cmap_i, next_cmap_i;
1535c2d7285SHyeongseok Kim 	unsigned int num_clusters = 0;
1545c2d7285SHyeongseok Kim 	unsigned int clu;
15531023864SNamjae Jeon 
15631023864SNamjae Jeon 	/* invalid cluster number */
15731023864SNamjae Jeon 	if (p_chain->dir == EXFAT_FREE_CLUSTER ||
15831023864SNamjae Jeon 	    p_chain->dir == EXFAT_EOF_CLUSTER ||
15931023864SNamjae Jeon 	    p_chain->dir < EXFAT_FIRST_CLUSTER)
16031023864SNamjae Jeon 		return 0;
16131023864SNamjae Jeon 
16231023864SNamjae Jeon 	/* no cluster to truncate */
16331023864SNamjae Jeon 	if (p_chain->size == 0)
16431023864SNamjae Jeon 		return 0;
16531023864SNamjae Jeon 
16631023864SNamjae Jeon 	/* check cluster validation */
167a949824fShyeongseok.kim 	if (!is_valid_cluster(sbi, p_chain->dir)) {
168d1727d55SJoe Perches 		exfat_err(sb, "invalid start cluster (%u)", p_chain->dir);
16931023864SNamjae Jeon 		return -EIO;
17031023864SNamjae Jeon 	}
17131023864SNamjae Jeon 
17231023864SNamjae Jeon 	clu = p_chain->dir;
17331023864SNamjae Jeon 
174f728760aSHyeongseok Kim 	cur_cmap_i = next_cmap_i =
175f728760aSHyeongseok Kim 		BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu));
17631023864SNamjae Jeon 
177f728760aSHyeongseok Kim 	if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
178f728760aSHyeongseok Kim 		unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
179f728760aSHyeongseok Kim 		do {
180f728760aSHyeongseok Kim 			bool sync = false;
181f728760aSHyeongseok Kim 
182f728760aSHyeongseok Kim 			if (clu < last_cluster)
183f728760aSHyeongseok Kim 				next_cmap_i =
184f728760aSHyeongseok Kim 				  BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu+1));
185f728760aSHyeongseok Kim 
186f728760aSHyeongseok Kim 			/* flush bitmap only if index would be changed or for last cluster */
187f728760aSHyeongseok Kim 			if (clu == last_cluster || cur_cmap_i != next_cmap_i) {
188f728760aSHyeongseok Kim 				sync = true;
189f728760aSHyeongseok Kim 				cur_cmap_i = next_cmap_i;
190f728760aSHyeongseok Kim 			}
191f728760aSHyeongseok Kim 
192f728760aSHyeongseok Kim 			exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
193f728760aSHyeongseok Kim 			clu++;
19431023864SNamjae Jeon 			num_clusters++;
19531023864SNamjae Jeon 		} while (num_clusters < p_chain->size);
19631023864SNamjae Jeon 	} else {
19731023864SNamjae Jeon 		do {
198f728760aSHyeongseok Kim 			bool sync = false;
199f728760aSHyeongseok Kim 			unsigned int n_clu = clu;
200f728760aSHyeongseok Kim 			int err = exfat_get_next_cluster(sb, &n_clu);
20131023864SNamjae Jeon 
202f728760aSHyeongseok Kim 			if (err || n_clu == EXFAT_EOF_CLUSTER)
203f728760aSHyeongseok Kim 				sync = true;
204f728760aSHyeongseok Kim 			else
205f728760aSHyeongseok Kim 				next_cmap_i =
206f728760aSHyeongseok Kim 				  BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(n_clu));
20731023864SNamjae Jeon 
208f728760aSHyeongseok Kim 			if (cur_cmap_i != next_cmap_i) {
209f728760aSHyeongseok Kim 				sync = true;
210f728760aSHyeongseok Kim 				cur_cmap_i = next_cmap_i;
211f728760aSHyeongseok Kim 			}
212f728760aSHyeongseok Kim 
213f728760aSHyeongseok Kim 			exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
214f728760aSHyeongseok Kim 			clu = n_clu;
21531023864SNamjae Jeon 			num_clusters++;
216f728760aSHyeongseok Kim 
217f728760aSHyeongseok Kim 			if (err)
218f728760aSHyeongseok Kim 				goto dec_used_clus;
21931023864SNamjae Jeon 		} while (clu != EXFAT_EOF_CLUSTER);
22031023864SNamjae Jeon 	}
22131023864SNamjae Jeon 
22231023864SNamjae Jeon dec_used_clus:
22331023864SNamjae Jeon 	sbi->used_clusters -= num_clusters;
22431023864SNamjae Jeon 	return 0;
22531023864SNamjae Jeon }
22631023864SNamjae Jeon 
exfat_free_cluster(struct inode * inode,struct exfat_chain * p_chain)2275c2d7285SHyeongseok Kim int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
2285c2d7285SHyeongseok Kim {
2295c2d7285SHyeongseok Kim 	int ret = 0;
2305c2d7285SHyeongseok Kim 
2315c2d7285SHyeongseok Kim 	mutex_lock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
2325c2d7285SHyeongseok Kim 	ret = __exfat_free_cluster(inode, p_chain);
2335c2d7285SHyeongseok Kim 	mutex_unlock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
2345c2d7285SHyeongseok Kim 
2355c2d7285SHyeongseok Kim 	return ret;
2365c2d7285SHyeongseok Kim }
2375c2d7285SHyeongseok Kim 
exfat_find_last_cluster(struct super_block * sb,struct exfat_chain * p_chain,unsigned int * ret_clu)23831023864SNamjae Jeon int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
23931023864SNamjae Jeon 		unsigned int *ret_clu)
24031023864SNamjae Jeon {
24131023864SNamjae Jeon 	unsigned int clu, next;
24231023864SNamjae Jeon 	unsigned int count = 0;
24331023864SNamjae Jeon 
24431023864SNamjae Jeon 	next = p_chain->dir;
24531023864SNamjae Jeon 	if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
24631023864SNamjae Jeon 		*ret_clu = next + p_chain->size - 1;
24731023864SNamjae Jeon 		return 0;
24831023864SNamjae Jeon 	}
24931023864SNamjae Jeon 
25031023864SNamjae Jeon 	do {
25131023864SNamjae Jeon 		count++;
25231023864SNamjae Jeon 		clu = next;
25331023864SNamjae Jeon 		if (exfat_ent_get(sb, clu, &next))
25431023864SNamjae Jeon 			return -EIO;
25531023864SNamjae Jeon 	} while (next != EXFAT_EOF_CLUSTER);
25631023864SNamjae Jeon 
25731023864SNamjae Jeon 	if (p_chain->size != count) {
25831023864SNamjae Jeon 		exfat_fs_error(sb,
25931023864SNamjae Jeon 			"bogus directory size (clus : ondisk(%d) != counted(%d))",
26031023864SNamjae Jeon 			p_chain->size, count);
26131023864SNamjae Jeon 		return -EIO;
26231023864SNamjae Jeon 	}
26331023864SNamjae Jeon 
26431023864SNamjae Jeon 	*ret_clu = clu;
26531023864SNamjae Jeon 	return 0;
26631023864SNamjae Jeon }
26731023864SNamjae Jeon 
exfat_zeroed_cluster(struct inode * dir,unsigned int clu)26831023864SNamjae Jeon int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
26931023864SNamjae Jeon {
27031023864SNamjae Jeon 	struct super_block *sb = dir->i_sb;
27131023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
2721b613838SYuezhang Mo 	struct buffer_head *bh;
2732e9ceb67SYuezhang Mo 	sector_t blknr, last_blknr, i;
27431023864SNamjae Jeon 
27531023864SNamjae Jeon 	blknr = exfat_cluster_to_sector(sbi, clu);
27631023864SNamjae Jeon 	last_blknr = blknr + sbi->sect_per_clus;
27731023864SNamjae Jeon 
27831023864SNamjae Jeon 	if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) {
27931023864SNamjae Jeon 		exfat_fs_error_ratelimit(sb,
28031023864SNamjae Jeon 			"%s: out of range(sect:%llu len:%u)",
28131023864SNamjae Jeon 			__func__, (unsigned long long)blknr,
28231023864SNamjae Jeon 			sbi->sect_per_clus);
28331023864SNamjae Jeon 		return -EIO;
28431023864SNamjae Jeon 	}
28531023864SNamjae Jeon 
28631023864SNamjae Jeon 	/* Zeroing the unused blocks on this cluster */
2871b613838SYuezhang Mo 	for (i = blknr; i < last_blknr; i++) {
2881b613838SYuezhang Mo 		bh = sb_getblk(sb, i);
2891b613838SYuezhang Mo 		if (!bh)
2901b613838SYuezhang Mo 			return -ENOMEM;
2911b613838SYuezhang Mo 
2921b613838SYuezhang Mo 		memset(bh->b_data, 0, sb->s_blocksize);
2931b613838SYuezhang Mo 		set_buffer_uptodate(bh);
2941b613838SYuezhang Mo 		mark_buffer_dirty(bh);
2951b613838SYuezhang Mo 		brelse(bh);
2964dc7d35eSTetsuhiro Kohada 	}
29731023864SNamjae Jeon 
2981b613838SYuezhang Mo 	if (IS_DIRSYNC(dir))
2991b613838SYuezhang Mo 		return sync_blockdev_range(sb->s_bdev,
3001b613838SYuezhang Mo 				EXFAT_BLK_TO_B(blknr, sb),
3011b613838SYuezhang Mo 				EXFAT_BLK_TO_B(last_blknr, sb) - 1);
30231023864SNamjae Jeon 
30331023864SNamjae Jeon 	return 0;
30431023864SNamjae Jeon }
30531023864SNamjae Jeon 
exfat_alloc_cluster(struct inode * inode,unsigned int num_alloc,struct exfat_chain * p_chain,bool sync_bmap)30631023864SNamjae Jeon int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
30723befe49SHyeongseok Kim 		struct exfat_chain *p_chain, bool sync_bmap)
30831023864SNamjae Jeon {
30931023864SNamjae Jeon 	int ret = -ENOSPC;
310*d5c514b6SYuezhang Mo 	unsigned int total_cnt;
31131023864SNamjae Jeon 	unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
31231023864SNamjae Jeon 	struct super_block *sb = inode->i_sb;
31331023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
31431023864SNamjae Jeon 
31531023864SNamjae Jeon 	total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi);
31631023864SNamjae Jeon 
31731023864SNamjae Jeon 	if (unlikely(total_cnt < sbi->used_clusters)) {
31831023864SNamjae Jeon 		exfat_fs_error_ratelimit(sb,
31931023864SNamjae Jeon 			"%s: invalid used clusters(t:%u,u:%u)\n",
32031023864SNamjae Jeon 			__func__, total_cnt, sbi->used_clusters);
32131023864SNamjae Jeon 		return -EIO;
32231023864SNamjae Jeon 	}
32331023864SNamjae Jeon 
32431023864SNamjae Jeon 	if (num_alloc > total_cnt - sbi->used_clusters)
32531023864SNamjae Jeon 		return -ENOSPC;
32631023864SNamjae Jeon 
3275c2d7285SHyeongseok Kim 	mutex_lock(&sbi->bitmap_lock);
3285c2d7285SHyeongseok Kim 
32931023864SNamjae Jeon 	hint_clu = p_chain->dir;
33031023864SNamjae Jeon 	/* find new cluster */
33131023864SNamjae Jeon 	if (hint_clu == EXFAT_EOF_CLUSTER) {
33231023864SNamjae Jeon 		if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
333512b74d1STakashi Iwai 			exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)",
33431023864SNamjae Jeon 				  sbi->clu_srch_ptr);
33531023864SNamjae Jeon 			sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
33631023864SNamjae Jeon 		}
33731023864SNamjae Jeon 
33831023864SNamjae Jeon 		hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
3395c2d7285SHyeongseok Kim 		if (hint_clu == EXFAT_EOF_CLUSTER) {
3405c2d7285SHyeongseok Kim 			ret = -ENOSPC;
3415c2d7285SHyeongseok Kim 			goto unlock;
3425c2d7285SHyeongseok Kim 		}
34331023864SNamjae Jeon 	}
34431023864SNamjae Jeon 
34531023864SNamjae Jeon 	/* check cluster validation */
346a949824fShyeongseok.kim 	if (!is_valid_cluster(sbi, hint_clu)) {
3473ce937cbSYuezhang Mo 		if (hint_clu != sbi->num_clusters)
3483ce937cbSYuezhang Mo 			exfat_err(sb, "hint_cluster is invalid (%u), rewind to the first cluster",
34931023864SNamjae Jeon 					hint_clu);
35031023864SNamjae Jeon 		hint_clu = EXFAT_FIRST_CLUSTER;
35131023864SNamjae Jeon 		p_chain->flags = ALLOC_FAT_CHAIN;
35231023864SNamjae Jeon 	}
35331023864SNamjae Jeon 
35431023864SNamjae Jeon 	p_chain->dir = EXFAT_EOF_CLUSTER;
35531023864SNamjae Jeon 
35631023864SNamjae Jeon 	while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) !=
35731023864SNamjae Jeon 	       EXFAT_EOF_CLUSTER) {
35831023864SNamjae Jeon 		if (new_clu != hint_clu &&
35931023864SNamjae Jeon 		    p_chain->flags == ALLOC_NO_FAT_CHAIN) {
36031023864SNamjae Jeon 			if (exfat_chain_cont_cluster(sb, p_chain->dir,
361*d5c514b6SYuezhang Mo 					p_chain->size)) {
36231023864SNamjae Jeon 				ret = -EIO;
36331023864SNamjae Jeon 				goto free_cluster;
36431023864SNamjae Jeon 			}
36531023864SNamjae Jeon 			p_chain->flags = ALLOC_FAT_CHAIN;
36631023864SNamjae Jeon 		}
36731023864SNamjae Jeon 
36831023864SNamjae Jeon 		/* update allocation bitmap */
36923befe49SHyeongseok Kim 		if (exfat_set_bitmap(inode, new_clu, sync_bmap)) {
37031023864SNamjae Jeon 			ret = -EIO;
37131023864SNamjae Jeon 			goto free_cluster;
37231023864SNamjae Jeon 		}
37331023864SNamjae Jeon 
37431023864SNamjae Jeon 		/* update FAT table */
37531023864SNamjae Jeon 		if (p_chain->flags == ALLOC_FAT_CHAIN) {
37631023864SNamjae Jeon 			if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
37731023864SNamjae Jeon 				ret = -EIO;
37831023864SNamjae Jeon 				goto free_cluster;
37931023864SNamjae Jeon 			}
38031023864SNamjae Jeon 		}
38131023864SNamjae Jeon 
38231023864SNamjae Jeon 		if (p_chain->dir == EXFAT_EOF_CLUSTER) {
38331023864SNamjae Jeon 			p_chain->dir = new_clu;
38431023864SNamjae Jeon 		} else if (p_chain->flags == ALLOC_FAT_CHAIN) {
38531023864SNamjae Jeon 			if (exfat_ent_set(sb, last_clu, new_clu)) {
38631023864SNamjae Jeon 				ret = -EIO;
38731023864SNamjae Jeon 				goto free_cluster;
38831023864SNamjae Jeon 			}
38931023864SNamjae Jeon 		}
390*d5c514b6SYuezhang Mo 		p_chain->size++;
391*d5c514b6SYuezhang Mo 
39231023864SNamjae Jeon 		last_clu = new_clu;
39331023864SNamjae Jeon 
394*d5c514b6SYuezhang Mo 		if (p_chain->size == num_alloc) {
39531023864SNamjae Jeon 			sbi->clu_srch_ptr = hint_clu;
396*d5c514b6SYuezhang Mo 			sbi->used_clusters += num_alloc;
39731023864SNamjae Jeon 
3985c2d7285SHyeongseok Kim 			mutex_unlock(&sbi->bitmap_lock);
39931023864SNamjae Jeon 			return 0;
40031023864SNamjae Jeon 		}
40131023864SNamjae Jeon 
40231023864SNamjae Jeon 		hint_clu = new_clu + 1;
40331023864SNamjae Jeon 		if (hint_clu >= sbi->num_clusters) {
40431023864SNamjae Jeon 			hint_clu = EXFAT_FIRST_CLUSTER;
40531023864SNamjae Jeon 
40631023864SNamjae Jeon 			if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
40731023864SNamjae Jeon 				if (exfat_chain_cont_cluster(sb, p_chain->dir,
408*d5c514b6SYuezhang Mo 						p_chain->size)) {
40931023864SNamjae Jeon 					ret = -EIO;
41031023864SNamjae Jeon 					goto free_cluster;
41131023864SNamjae Jeon 				}
41231023864SNamjae Jeon 				p_chain->flags = ALLOC_FAT_CHAIN;
41331023864SNamjae Jeon 			}
41431023864SNamjae Jeon 		}
41531023864SNamjae Jeon 	}
41631023864SNamjae Jeon free_cluster:
4175c2d7285SHyeongseok Kim 	__exfat_free_cluster(inode, p_chain);
4185c2d7285SHyeongseok Kim unlock:
4195c2d7285SHyeongseok Kim 	mutex_unlock(&sbi->bitmap_lock);
42031023864SNamjae Jeon 	return ret;
42131023864SNamjae Jeon }
42231023864SNamjae Jeon 
exfat_count_num_clusters(struct super_block * sb,struct exfat_chain * p_chain,unsigned int * ret_count)42331023864SNamjae Jeon int exfat_count_num_clusters(struct super_block *sb,
42431023864SNamjae Jeon 		struct exfat_chain *p_chain, unsigned int *ret_count)
42531023864SNamjae Jeon {
42631023864SNamjae Jeon 	unsigned int i, count;
42731023864SNamjae Jeon 	unsigned int clu;
42831023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
42931023864SNamjae Jeon 
43031023864SNamjae Jeon 	if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) {
43131023864SNamjae Jeon 		*ret_count = 0;
43231023864SNamjae Jeon 		return 0;
43331023864SNamjae Jeon 	}
43431023864SNamjae Jeon 
43531023864SNamjae Jeon 	if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
43631023864SNamjae Jeon 		*ret_count = p_chain->size;
43731023864SNamjae Jeon 		return 0;
43831023864SNamjae Jeon 	}
43931023864SNamjae Jeon 
44031023864SNamjae Jeon 	clu = p_chain->dir;
44131023864SNamjae Jeon 	count = 0;
44231023864SNamjae Jeon 	for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
44331023864SNamjae Jeon 		count++;
44431023864SNamjae Jeon 		if (exfat_ent_get(sb, clu, &clu))
44531023864SNamjae Jeon 			return -EIO;
44631023864SNamjae Jeon 		if (clu == EXFAT_EOF_CLUSTER)
44731023864SNamjae Jeon 			break;
44831023864SNamjae Jeon 	}
44931023864SNamjae Jeon 
45031023864SNamjae Jeon 	*ret_count = count;
45131023864SNamjae Jeon 	return 0;
45231023864SNamjae Jeon }
453