xref: /openbmc/linux/fs/exfat/fatent.c (revision 8ebc80a25f9d9bf7a8e368b266d5b740c485c362)
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) {
178*747de766SNamjae Jeon 		int err;
179f728760aSHyeongseok Kim 		unsigned int last_cluster = p_chain->dir + p_chain->size - 1;
180f728760aSHyeongseok Kim 		do {
181f728760aSHyeongseok Kim 			bool sync = false;
182f728760aSHyeongseok Kim 
183f728760aSHyeongseok Kim 			if (clu < last_cluster)
184f728760aSHyeongseok Kim 				next_cmap_i =
185f728760aSHyeongseok Kim 				  BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu+1));
186f728760aSHyeongseok Kim 
187f728760aSHyeongseok Kim 			/* flush bitmap only if index would be changed or for last cluster */
188f728760aSHyeongseok Kim 			if (clu == last_cluster || cur_cmap_i != next_cmap_i) {
189f728760aSHyeongseok Kim 				sync = true;
190f728760aSHyeongseok Kim 				cur_cmap_i = next_cmap_i;
191f728760aSHyeongseok Kim 			}
192f728760aSHyeongseok Kim 
193*747de766SNamjae Jeon 			err = exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)));
194*747de766SNamjae Jeon 			if (err)
195*747de766SNamjae Jeon 				break;
196f728760aSHyeongseok Kim 			clu++;
19731023864SNamjae Jeon 			num_clusters++;
19831023864SNamjae Jeon 		} while (num_clusters < p_chain->size);
19931023864SNamjae Jeon 	} else {
20031023864SNamjae Jeon 		do {
201f728760aSHyeongseok Kim 			bool sync = false;
202f728760aSHyeongseok Kim 			unsigned int n_clu = clu;
203f728760aSHyeongseok Kim 			int err = exfat_get_next_cluster(sb, &n_clu);
20431023864SNamjae Jeon 
205f728760aSHyeongseok Kim 			if (err || n_clu == EXFAT_EOF_CLUSTER)
206f728760aSHyeongseok Kim 				sync = true;
207f728760aSHyeongseok Kim 			else
208f728760aSHyeongseok Kim 				next_cmap_i =
209f728760aSHyeongseok Kim 				  BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(n_clu));
21031023864SNamjae Jeon 
211f728760aSHyeongseok Kim 			if (cur_cmap_i != next_cmap_i) {
212f728760aSHyeongseok Kim 				sync = true;
213f728760aSHyeongseok Kim 				cur_cmap_i = next_cmap_i;
214f728760aSHyeongseok Kim 			}
215f728760aSHyeongseok Kim 
216*747de766SNamjae Jeon 			if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))))
217*747de766SNamjae Jeon 				break;
218f728760aSHyeongseok Kim 			clu = n_clu;
21931023864SNamjae Jeon 			num_clusters++;
220f728760aSHyeongseok Kim 
221f728760aSHyeongseok Kim 			if (err)
222*747de766SNamjae Jeon 				break;
2231e92afe8SYuezhang Mo 
2241e92afe8SYuezhang Mo 			if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) {
2251e92afe8SYuezhang Mo 				/*
2261e92afe8SYuezhang Mo 				 * The cluster chain includes a loop, scan the
2271e92afe8SYuezhang Mo 				 * bitmap to get the number of used clusters.
2281e92afe8SYuezhang Mo 				 */
2291e92afe8SYuezhang Mo 				exfat_count_used_clusters(sb, &sbi->used_clusters);
2301e92afe8SYuezhang Mo 
2311e92afe8SYuezhang Mo 				return 0;
2321e92afe8SYuezhang Mo 			}
23331023864SNamjae Jeon 		} while (clu != EXFAT_EOF_CLUSTER);
23431023864SNamjae Jeon 	}
23531023864SNamjae Jeon 
23631023864SNamjae Jeon 	sbi->used_clusters -= num_clusters;
23731023864SNamjae Jeon 	return 0;
23831023864SNamjae Jeon }
23931023864SNamjae Jeon 
exfat_free_cluster(struct inode * inode,struct exfat_chain * p_chain)2405c2d7285SHyeongseok Kim int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain)
2415c2d7285SHyeongseok Kim {
2425c2d7285SHyeongseok Kim 	int ret = 0;
2435c2d7285SHyeongseok Kim 
2445c2d7285SHyeongseok Kim 	mutex_lock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
2455c2d7285SHyeongseok Kim 	ret = __exfat_free_cluster(inode, p_chain);
2465c2d7285SHyeongseok Kim 	mutex_unlock(&EXFAT_SB(inode->i_sb)->bitmap_lock);
2475c2d7285SHyeongseok Kim 
2485c2d7285SHyeongseok Kim 	return ret;
2495c2d7285SHyeongseok Kim }
2505c2d7285SHyeongseok Kim 
exfat_find_last_cluster(struct super_block * sb,struct exfat_chain * p_chain,unsigned int * ret_clu)25131023864SNamjae Jeon int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
25231023864SNamjae Jeon 		unsigned int *ret_clu)
25331023864SNamjae Jeon {
25431023864SNamjae Jeon 	unsigned int clu, next;
25531023864SNamjae Jeon 	unsigned int count = 0;
25631023864SNamjae Jeon 
25731023864SNamjae Jeon 	next = p_chain->dir;
25831023864SNamjae Jeon 	if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
25931023864SNamjae Jeon 		*ret_clu = next + p_chain->size - 1;
26031023864SNamjae Jeon 		return 0;
26131023864SNamjae Jeon 	}
26231023864SNamjae Jeon 
26331023864SNamjae Jeon 	do {
26431023864SNamjae Jeon 		count++;
26531023864SNamjae Jeon 		clu = next;
26631023864SNamjae Jeon 		if (exfat_ent_get(sb, clu, &next))
26731023864SNamjae Jeon 			return -EIO;
26831023864SNamjae Jeon 	} while (next != EXFAT_EOF_CLUSTER);
26931023864SNamjae Jeon 
27031023864SNamjae Jeon 	if (p_chain->size != count) {
27131023864SNamjae Jeon 		exfat_fs_error(sb,
27231023864SNamjae Jeon 			"bogus directory size (clus : ondisk(%d) != counted(%d))",
27331023864SNamjae Jeon 			p_chain->size, count);
27431023864SNamjae Jeon 		return -EIO;
27531023864SNamjae Jeon 	}
27631023864SNamjae Jeon 
27731023864SNamjae Jeon 	*ret_clu = clu;
27831023864SNamjae Jeon 	return 0;
27931023864SNamjae Jeon }
28031023864SNamjae Jeon 
exfat_zeroed_cluster(struct inode * dir,unsigned int clu)28131023864SNamjae Jeon int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
28231023864SNamjae Jeon {
28331023864SNamjae Jeon 	struct super_block *sb = dir->i_sb;
28431023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
2851b613838SYuezhang Mo 	struct buffer_head *bh;
2862e9ceb67SYuezhang Mo 	sector_t blknr, last_blknr, i;
28731023864SNamjae Jeon 
28831023864SNamjae Jeon 	blknr = exfat_cluster_to_sector(sbi, clu);
28931023864SNamjae Jeon 	last_blknr = blknr + sbi->sect_per_clus;
29031023864SNamjae Jeon 
29131023864SNamjae Jeon 	if (last_blknr > sbi->num_sectors && sbi->num_sectors > 0) {
29231023864SNamjae Jeon 		exfat_fs_error_ratelimit(sb,
29331023864SNamjae Jeon 			"%s: out of range(sect:%llu len:%u)",
29431023864SNamjae Jeon 			__func__, (unsigned long long)blknr,
29531023864SNamjae Jeon 			sbi->sect_per_clus);
29631023864SNamjae Jeon 		return -EIO;
29731023864SNamjae Jeon 	}
29831023864SNamjae Jeon 
29931023864SNamjae Jeon 	/* Zeroing the unused blocks on this cluster */
3001b613838SYuezhang Mo 	for (i = blknr; i < last_blknr; i++) {
3011b613838SYuezhang Mo 		bh = sb_getblk(sb, i);
3021b613838SYuezhang Mo 		if (!bh)
3031b613838SYuezhang Mo 			return -ENOMEM;
3041b613838SYuezhang Mo 
3051b613838SYuezhang Mo 		memset(bh->b_data, 0, sb->s_blocksize);
3061b613838SYuezhang Mo 		set_buffer_uptodate(bh);
3071b613838SYuezhang Mo 		mark_buffer_dirty(bh);
3081b613838SYuezhang Mo 		brelse(bh);
3094dc7d35eSTetsuhiro Kohada 	}
31031023864SNamjae Jeon 
3111b613838SYuezhang Mo 	if (IS_DIRSYNC(dir))
3121b613838SYuezhang Mo 		return sync_blockdev_range(sb->s_bdev,
3131b613838SYuezhang Mo 				EXFAT_BLK_TO_B(blknr, sb),
3141b613838SYuezhang Mo 				EXFAT_BLK_TO_B(last_blknr, sb) - 1);
31531023864SNamjae Jeon 
31631023864SNamjae Jeon 	return 0;
31731023864SNamjae Jeon }
31831023864SNamjae Jeon 
exfat_alloc_cluster(struct inode * inode,unsigned int num_alloc,struct exfat_chain * p_chain,bool sync_bmap)31931023864SNamjae Jeon int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
32023befe49SHyeongseok Kim 		struct exfat_chain *p_chain, bool sync_bmap)
32131023864SNamjae Jeon {
32231023864SNamjae Jeon 	int ret = -ENOSPC;
323d5c514b6SYuezhang Mo 	unsigned int total_cnt;
32431023864SNamjae Jeon 	unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
32531023864SNamjae Jeon 	struct super_block *sb = inode->i_sb;
32631023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
32731023864SNamjae Jeon 
32831023864SNamjae Jeon 	total_cnt = EXFAT_DATA_CLUSTER_COUNT(sbi);
32931023864SNamjae Jeon 
33031023864SNamjae Jeon 	if (unlikely(total_cnt < sbi->used_clusters)) {
33131023864SNamjae Jeon 		exfat_fs_error_ratelimit(sb,
33231023864SNamjae Jeon 			"%s: invalid used clusters(t:%u,u:%u)\n",
33331023864SNamjae Jeon 			__func__, total_cnt, sbi->used_clusters);
33431023864SNamjae Jeon 		return -EIO;
33531023864SNamjae Jeon 	}
33631023864SNamjae Jeon 
33731023864SNamjae Jeon 	if (num_alloc > total_cnt - sbi->used_clusters)
33831023864SNamjae Jeon 		return -ENOSPC;
33931023864SNamjae Jeon 
3405c2d7285SHyeongseok Kim 	mutex_lock(&sbi->bitmap_lock);
3415c2d7285SHyeongseok Kim 
34231023864SNamjae Jeon 	hint_clu = p_chain->dir;
34331023864SNamjae Jeon 	/* find new cluster */
34431023864SNamjae Jeon 	if (hint_clu == EXFAT_EOF_CLUSTER) {
34531023864SNamjae Jeon 		if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
346512b74d1STakashi Iwai 			exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)",
34731023864SNamjae Jeon 				  sbi->clu_srch_ptr);
34831023864SNamjae Jeon 			sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
34931023864SNamjae Jeon 		}
35031023864SNamjae Jeon 
35131023864SNamjae Jeon 		hint_clu = exfat_find_free_bitmap(sb, sbi->clu_srch_ptr);
3525c2d7285SHyeongseok Kim 		if (hint_clu == EXFAT_EOF_CLUSTER) {
3535c2d7285SHyeongseok Kim 			ret = -ENOSPC;
3545c2d7285SHyeongseok Kim 			goto unlock;
3555c2d7285SHyeongseok Kim 		}
35631023864SNamjae Jeon 	}
35731023864SNamjae Jeon 
35831023864SNamjae Jeon 	/* check cluster validation */
359a949824fShyeongseok.kim 	if (!is_valid_cluster(sbi, hint_clu)) {
3603ce937cbSYuezhang Mo 		if (hint_clu != sbi->num_clusters)
3613ce937cbSYuezhang Mo 			exfat_err(sb, "hint_cluster is invalid (%u), rewind to the first cluster",
36231023864SNamjae Jeon 					hint_clu);
36331023864SNamjae Jeon 		hint_clu = EXFAT_FIRST_CLUSTER;
36431023864SNamjae Jeon 		p_chain->flags = ALLOC_FAT_CHAIN;
36531023864SNamjae Jeon 	}
36631023864SNamjae Jeon 
36731023864SNamjae Jeon 	p_chain->dir = EXFAT_EOF_CLUSTER;
36831023864SNamjae Jeon 
36931023864SNamjae Jeon 	while ((new_clu = exfat_find_free_bitmap(sb, hint_clu)) !=
37031023864SNamjae Jeon 	       EXFAT_EOF_CLUSTER) {
37131023864SNamjae Jeon 		if (new_clu != hint_clu &&
37231023864SNamjae Jeon 		    p_chain->flags == ALLOC_NO_FAT_CHAIN) {
37331023864SNamjae Jeon 			if (exfat_chain_cont_cluster(sb, p_chain->dir,
374d5c514b6SYuezhang Mo 					p_chain->size)) {
37531023864SNamjae Jeon 				ret = -EIO;
37631023864SNamjae Jeon 				goto free_cluster;
37731023864SNamjae Jeon 			}
37831023864SNamjae Jeon 			p_chain->flags = ALLOC_FAT_CHAIN;
37931023864SNamjae Jeon 		}
38031023864SNamjae Jeon 
38131023864SNamjae Jeon 		/* update allocation bitmap */
38223befe49SHyeongseok Kim 		if (exfat_set_bitmap(inode, new_clu, sync_bmap)) {
38331023864SNamjae Jeon 			ret = -EIO;
38431023864SNamjae Jeon 			goto free_cluster;
38531023864SNamjae Jeon 		}
38631023864SNamjae Jeon 
38731023864SNamjae Jeon 		/* update FAT table */
38831023864SNamjae Jeon 		if (p_chain->flags == ALLOC_FAT_CHAIN) {
38931023864SNamjae Jeon 			if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
39031023864SNamjae Jeon 				ret = -EIO;
39131023864SNamjae Jeon 				goto free_cluster;
39231023864SNamjae Jeon 			}
39331023864SNamjae Jeon 		}
39431023864SNamjae Jeon 
39531023864SNamjae Jeon 		if (p_chain->dir == EXFAT_EOF_CLUSTER) {
39631023864SNamjae Jeon 			p_chain->dir = new_clu;
39731023864SNamjae Jeon 		} else if (p_chain->flags == ALLOC_FAT_CHAIN) {
39831023864SNamjae Jeon 			if (exfat_ent_set(sb, last_clu, new_clu)) {
39931023864SNamjae Jeon 				ret = -EIO;
40031023864SNamjae Jeon 				goto free_cluster;
40131023864SNamjae Jeon 			}
40231023864SNamjae Jeon 		}
403d5c514b6SYuezhang Mo 		p_chain->size++;
404d5c514b6SYuezhang Mo 
40531023864SNamjae Jeon 		last_clu = new_clu;
40631023864SNamjae Jeon 
407d5c514b6SYuezhang Mo 		if (p_chain->size == num_alloc) {
40831023864SNamjae Jeon 			sbi->clu_srch_ptr = hint_clu;
409d5c514b6SYuezhang Mo 			sbi->used_clusters += num_alloc;
41031023864SNamjae Jeon 
4115c2d7285SHyeongseok Kim 			mutex_unlock(&sbi->bitmap_lock);
41231023864SNamjae Jeon 			return 0;
41331023864SNamjae Jeon 		}
41431023864SNamjae Jeon 
41531023864SNamjae Jeon 		hint_clu = new_clu + 1;
41631023864SNamjae Jeon 		if (hint_clu >= sbi->num_clusters) {
41731023864SNamjae Jeon 			hint_clu = EXFAT_FIRST_CLUSTER;
41831023864SNamjae Jeon 
41931023864SNamjae Jeon 			if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
42031023864SNamjae Jeon 				if (exfat_chain_cont_cluster(sb, p_chain->dir,
421d5c514b6SYuezhang Mo 						p_chain->size)) {
42231023864SNamjae Jeon 					ret = -EIO;
42331023864SNamjae Jeon 					goto free_cluster;
42431023864SNamjae Jeon 				}
42531023864SNamjae Jeon 				p_chain->flags = ALLOC_FAT_CHAIN;
42631023864SNamjae Jeon 			}
42731023864SNamjae Jeon 		}
42831023864SNamjae Jeon 	}
42931023864SNamjae Jeon free_cluster:
4305c2d7285SHyeongseok Kim 	__exfat_free_cluster(inode, p_chain);
4315c2d7285SHyeongseok Kim unlock:
4325c2d7285SHyeongseok Kim 	mutex_unlock(&sbi->bitmap_lock);
43331023864SNamjae Jeon 	return ret;
43431023864SNamjae Jeon }
43531023864SNamjae Jeon 
exfat_count_num_clusters(struct super_block * sb,struct exfat_chain * p_chain,unsigned int * ret_count)43631023864SNamjae Jeon int exfat_count_num_clusters(struct super_block *sb,
43731023864SNamjae Jeon 		struct exfat_chain *p_chain, unsigned int *ret_count)
43831023864SNamjae Jeon {
43931023864SNamjae Jeon 	unsigned int i, count;
44031023864SNamjae Jeon 	unsigned int clu;
44131023864SNamjae Jeon 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
44231023864SNamjae Jeon 
44331023864SNamjae Jeon 	if (!p_chain->dir || p_chain->dir == EXFAT_EOF_CLUSTER) {
44431023864SNamjae Jeon 		*ret_count = 0;
44531023864SNamjae Jeon 		return 0;
44631023864SNamjae Jeon 	}
44731023864SNamjae Jeon 
44831023864SNamjae Jeon 	if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
44931023864SNamjae Jeon 		*ret_count = p_chain->size;
45031023864SNamjae Jeon 		return 0;
45131023864SNamjae Jeon 	}
45231023864SNamjae Jeon 
45331023864SNamjae Jeon 	clu = p_chain->dir;
45431023864SNamjae Jeon 	count = 0;
45531023864SNamjae Jeon 	for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
45631023864SNamjae Jeon 		count++;
45731023864SNamjae Jeon 		if (exfat_ent_get(sb, clu, &clu))
45831023864SNamjae Jeon 			return -EIO;
45931023864SNamjae Jeon 		if (clu == EXFAT_EOF_CLUSTER)
46031023864SNamjae Jeon 			break;
46131023864SNamjae Jeon 	}
46231023864SNamjae Jeon 
46331023864SNamjae Jeon 	*ret_count = count;
46431023864SNamjae Jeon 	return 0;
46531023864SNamjae Jeon }
466