xref: /kernel/linux/linux-5.10/fs/exfat/inode.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/init.h>
78c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
88c2ecf20Sopenharmony_ci#include <linux/mpage.h>
98c2ecf20Sopenharmony_ci#include <linux/bio.h>
108c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
118c2ecf20Sopenharmony_ci#include <linux/time.h>
128c2ecf20Sopenharmony_ci#include <linux/writeback.h>
138c2ecf20Sopenharmony_ci#include <linux/uio.h>
148c2ecf20Sopenharmony_ci#include <linux/random.h>
158c2ecf20Sopenharmony_ci#include <linux/iversion.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "exfat_raw.h"
188c2ecf20Sopenharmony_ci#include "exfat_fs.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic int __exfat_write_inode(struct inode *inode, int sync)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	unsigned long long on_disk_size;
238c2ecf20Sopenharmony_ci	struct exfat_dentry *ep, *ep2;
248c2ecf20Sopenharmony_ci	struct exfat_entry_set_cache *es = NULL;
258c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
268c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(sb);
278c2ecf20Sopenharmony_ci	struct exfat_inode_info *ei = EXFAT_I(inode);
288c2ecf20Sopenharmony_ci	bool is_dir = (ei->type == TYPE_DIR) ? true : false;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (inode->i_ino == EXFAT_ROOT_INO)
318c2ecf20Sopenharmony_ci		return 0;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/*
348c2ecf20Sopenharmony_ci	 * If the indode is already unlinked, there is no need for updating it.
358c2ecf20Sopenharmony_ci	 */
368c2ecf20Sopenharmony_ci	if (ei->dir.dir == DIR_DELETED)
378c2ecf20Sopenharmony_ci		return 0;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (is_dir && ei->dir.dir == sbi->root_dir && ei->entry == -1)
408c2ecf20Sopenharmony_ci		return 0;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	exfat_set_volume_dirty(sb);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* get the directory entry of given file or directory */
458c2ecf20Sopenharmony_ci	es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES);
468c2ecf20Sopenharmony_ci	if (!es)
478c2ecf20Sopenharmony_ci		return -EIO;
488c2ecf20Sopenharmony_ci	ep = exfat_get_dentry_cached(es, 0);
498c2ecf20Sopenharmony_ci	ep2 = exfat_get_dentry_cached(es, 1);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode));
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/* set FILE_INFO structure using the acquired struct exfat_dentry */
548c2ecf20Sopenharmony_ci	exfat_set_entry_time(sbi, &ei->i_crtime,
558c2ecf20Sopenharmony_ci			&ep->dentry.file.create_tz,
568c2ecf20Sopenharmony_ci			&ep->dentry.file.create_time,
578c2ecf20Sopenharmony_ci			&ep->dentry.file.create_date,
588c2ecf20Sopenharmony_ci			&ep->dentry.file.create_time_cs);
598c2ecf20Sopenharmony_ci	exfat_set_entry_time(sbi, &inode->i_mtime,
608c2ecf20Sopenharmony_ci			&ep->dentry.file.modify_tz,
618c2ecf20Sopenharmony_ci			&ep->dentry.file.modify_time,
628c2ecf20Sopenharmony_ci			&ep->dentry.file.modify_date,
638c2ecf20Sopenharmony_ci			&ep->dentry.file.modify_time_cs);
648c2ecf20Sopenharmony_ci	exfat_set_entry_time(sbi, &inode->i_atime,
658c2ecf20Sopenharmony_ci			&ep->dentry.file.access_tz,
668c2ecf20Sopenharmony_ci			&ep->dentry.file.access_time,
678c2ecf20Sopenharmony_ci			&ep->dentry.file.access_date,
688c2ecf20Sopenharmony_ci			NULL);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* File size should be zero if there is no cluster allocated */
718c2ecf20Sopenharmony_ci	on_disk_size = i_size_read(inode);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	if (ei->start_clu == EXFAT_EOF_CLUSTER)
748c2ecf20Sopenharmony_ci		on_disk_size = 0;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);
778c2ecf20Sopenharmony_ci	ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	exfat_update_dir_chksum_with_entry_set(es);
808c2ecf20Sopenharmony_ci	return exfat_free_dentry_set(es, sync);
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciint exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	int ret;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
888c2ecf20Sopenharmony_ci	ret = __exfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
898c2ecf20Sopenharmony_ci	mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	return ret;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_civoid exfat_sync_inode(struct inode *inode)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	lockdep_assert_held(&EXFAT_SB(inode->i_sb)->s_lock);
978c2ecf20Sopenharmony_ci	__exfat_write_inode(inode, 1);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/*
1018c2ecf20Sopenharmony_ci * Input: inode, (logical) clu_offset, target allocation area
1028c2ecf20Sopenharmony_ci * Output: errcode, cluster number
1038c2ecf20Sopenharmony_ci * *clu = (~0), if it's unable to allocate a new cluster
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_cistatic int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
1068c2ecf20Sopenharmony_ci		unsigned int *clu, int create)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	int ret, modified = false;
1098c2ecf20Sopenharmony_ci	unsigned int last_clu;
1108c2ecf20Sopenharmony_ci	struct exfat_chain new_clu;
1118c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
1128c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(sb);
1138c2ecf20Sopenharmony_ci	struct exfat_inode_info *ei = EXFAT_I(inode);
1148c2ecf20Sopenharmony_ci	unsigned int local_clu_offset = clu_offset;
1158c2ecf20Sopenharmony_ci	unsigned int num_to_be_allocated = 0, num_clusters = 0;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (ei->i_size_ondisk > 0)
1188c2ecf20Sopenharmony_ci		num_clusters =
1198c2ecf20Sopenharmony_ci			EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	if (clu_offset >= num_clusters)
1228c2ecf20Sopenharmony_ci		num_to_be_allocated = clu_offset - num_clusters + 1;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (!create && (num_to_be_allocated > 0)) {
1258c2ecf20Sopenharmony_ci		*clu = EXFAT_EOF_CLUSTER;
1268c2ecf20Sopenharmony_ci		return 0;
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	*clu = last_clu = ei->start_clu;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (ei->flags == ALLOC_NO_FAT_CHAIN) {
1328c2ecf20Sopenharmony_ci		if (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) {
1338c2ecf20Sopenharmony_ci			last_clu += clu_offset - 1;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci			if (clu_offset == num_clusters)
1368c2ecf20Sopenharmony_ci				*clu = EXFAT_EOF_CLUSTER;
1378c2ecf20Sopenharmony_ci			else
1388c2ecf20Sopenharmony_ci				*clu += clu_offset;
1398c2ecf20Sopenharmony_ci		}
1408c2ecf20Sopenharmony_ci	} else if (ei->type == TYPE_FILE) {
1418c2ecf20Sopenharmony_ci		unsigned int fclus = 0;
1428c2ecf20Sopenharmony_ci		int err = exfat_get_cluster(inode, clu_offset,
1438c2ecf20Sopenharmony_ci				&fclus, clu, &last_clu, 1);
1448c2ecf20Sopenharmony_ci		if (err)
1458c2ecf20Sopenharmony_ci			return -EIO;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci		clu_offset -= fclus;
1488c2ecf20Sopenharmony_ci	} else {
1498c2ecf20Sopenharmony_ci		/* hint information */
1508c2ecf20Sopenharmony_ci		if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER &&
1518c2ecf20Sopenharmony_ci		    ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) {
1528c2ecf20Sopenharmony_ci			clu_offset -= ei->hint_bmap.off;
1538c2ecf20Sopenharmony_ci			/* hint_bmap.clu should be valid */
1548c2ecf20Sopenharmony_ci			WARN_ON(ei->hint_bmap.clu < 2);
1558c2ecf20Sopenharmony_ci			*clu = ei->hint_bmap.clu;
1568c2ecf20Sopenharmony_ci		}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci		while (clu_offset > 0 && *clu != EXFAT_EOF_CLUSTER) {
1598c2ecf20Sopenharmony_ci			last_clu = *clu;
1608c2ecf20Sopenharmony_ci			if (exfat_get_next_cluster(sb, clu))
1618c2ecf20Sopenharmony_ci				return -EIO;
1628c2ecf20Sopenharmony_ci			clu_offset--;
1638c2ecf20Sopenharmony_ci		}
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (*clu == EXFAT_EOF_CLUSTER) {
1678c2ecf20Sopenharmony_ci		exfat_set_volume_dirty(sb);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci		new_clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
1708c2ecf20Sopenharmony_ci				EXFAT_EOF_CLUSTER : last_clu + 1;
1718c2ecf20Sopenharmony_ci		new_clu.size = 0;
1728c2ecf20Sopenharmony_ci		new_clu.flags = ei->flags;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		/* allocate a cluster */
1758c2ecf20Sopenharmony_ci		if (num_to_be_allocated < 1) {
1768c2ecf20Sopenharmony_ci			/* Broken FAT (i_sze > allocated FAT) */
1778c2ecf20Sopenharmony_ci			exfat_fs_error(sb, "broken FAT chain.");
1788c2ecf20Sopenharmony_ci			return -EIO;
1798c2ecf20Sopenharmony_ci		}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		ret = exfat_alloc_cluster(inode, num_to_be_allocated, &new_clu);
1828c2ecf20Sopenharmony_ci		if (ret)
1838c2ecf20Sopenharmony_ci			return ret;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci		if (new_clu.dir == EXFAT_EOF_CLUSTER ||
1868c2ecf20Sopenharmony_ci		    new_clu.dir == EXFAT_FREE_CLUSTER) {
1878c2ecf20Sopenharmony_ci			exfat_fs_error(sb,
1888c2ecf20Sopenharmony_ci				"bogus cluster new allocated (last_clu : %u, new_clu : %u)",
1898c2ecf20Sopenharmony_ci				last_clu, new_clu.dir);
1908c2ecf20Sopenharmony_ci			return -EIO;
1918c2ecf20Sopenharmony_ci		}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		/* append to the FAT chain */
1948c2ecf20Sopenharmony_ci		if (last_clu == EXFAT_EOF_CLUSTER) {
1958c2ecf20Sopenharmony_ci			if (new_clu.flags == ALLOC_FAT_CHAIN)
1968c2ecf20Sopenharmony_ci				ei->flags = ALLOC_FAT_CHAIN;
1978c2ecf20Sopenharmony_ci			ei->start_clu = new_clu.dir;
1988c2ecf20Sopenharmony_ci			modified = true;
1998c2ecf20Sopenharmony_ci		} else {
2008c2ecf20Sopenharmony_ci			if (new_clu.flags != ei->flags) {
2018c2ecf20Sopenharmony_ci				/* no-fat-chain bit is disabled,
2028c2ecf20Sopenharmony_ci				 * so fat-chain should be synced with
2038c2ecf20Sopenharmony_ci				 * alloc-bitmap
2048c2ecf20Sopenharmony_ci				 */
2058c2ecf20Sopenharmony_ci				exfat_chain_cont_cluster(sb, ei->start_clu,
2068c2ecf20Sopenharmony_ci					num_clusters);
2078c2ecf20Sopenharmony_ci				ei->flags = ALLOC_FAT_CHAIN;
2088c2ecf20Sopenharmony_ci				modified = true;
2098c2ecf20Sopenharmony_ci			}
2108c2ecf20Sopenharmony_ci			if (new_clu.flags == ALLOC_FAT_CHAIN)
2118c2ecf20Sopenharmony_ci				if (exfat_ent_set(sb, last_clu, new_clu.dir))
2128c2ecf20Sopenharmony_ci					return -EIO;
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		num_clusters += num_to_be_allocated;
2168c2ecf20Sopenharmony_ci		*clu = new_clu.dir;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		if (ei->dir.dir != DIR_DELETED && modified) {
2198c2ecf20Sopenharmony_ci			struct exfat_dentry *ep;
2208c2ecf20Sopenharmony_ci			struct exfat_entry_set_cache *es;
2218c2ecf20Sopenharmony_ci			int err;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci			es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
2248c2ecf20Sopenharmony_ci				ES_ALL_ENTRIES);
2258c2ecf20Sopenharmony_ci			if (!es)
2268c2ecf20Sopenharmony_ci				return -EIO;
2278c2ecf20Sopenharmony_ci			/* get stream entry */
2288c2ecf20Sopenharmony_ci			ep = exfat_get_dentry_cached(es, 1);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci			/* update directory entry */
2318c2ecf20Sopenharmony_ci			ep->dentry.stream.flags = ei->flags;
2328c2ecf20Sopenharmony_ci			ep->dentry.stream.start_clu =
2338c2ecf20Sopenharmony_ci				cpu_to_le32(ei->start_clu);
2348c2ecf20Sopenharmony_ci			ep->dentry.stream.valid_size =
2358c2ecf20Sopenharmony_ci				cpu_to_le64(i_size_read(inode));
2368c2ecf20Sopenharmony_ci			ep->dentry.stream.size =
2378c2ecf20Sopenharmony_ci				ep->dentry.stream.valid_size;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci			exfat_update_dir_chksum_with_entry_set(es);
2408c2ecf20Sopenharmony_ci			err = exfat_free_dentry_set(es, inode_needs_sync(inode));
2418c2ecf20Sopenharmony_ci			if (err)
2428c2ecf20Sopenharmony_ci				return err;
2438c2ecf20Sopenharmony_ci		} /* end of if != DIR_DELETED */
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci		inode->i_blocks += EXFAT_CLU_TO_B(num_to_be_allocated, sbi) >> 9;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		/*
2488c2ecf20Sopenharmony_ci		 * Move *clu pointer along FAT chains (hole care) because the
2498c2ecf20Sopenharmony_ci		 * caller of this function expect *clu to be the last cluster.
2508c2ecf20Sopenharmony_ci		 * This only works when num_to_be_allocated >= 2,
2518c2ecf20Sopenharmony_ci		 * *clu = (the first cluster of the allocated chain) =>
2528c2ecf20Sopenharmony_ci		 * (the last cluster of ...)
2538c2ecf20Sopenharmony_ci		 */
2548c2ecf20Sopenharmony_ci		if (ei->flags == ALLOC_NO_FAT_CHAIN) {
2558c2ecf20Sopenharmony_ci			*clu += num_to_be_allocated - 1;
2568c2ecf20Sopenharmony_ci		} else {
2578c2ecf20Sopenharmony_ci			while (num_to_be_allocated > 1) {
2588c2ecf20Sopenharmony_ci				if (exfat_get_next_cluster(sb, clu))
2598c2ecf20Sopenharmony_ci					return -EIO;
2608c2ecf20Sopenharmony_ci				num_to_be_allocated--;
2618c2ecf20Sopenharmony_ci			}
2628c2ecf20Sopenharmony_ci		}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* hint information */
2678c2ecf20Sopenharmony_ci	ei->hint_bmap.off = local_clu_offset;
2688c2ecf20Sopenharmony_ci	ei->hint_bmap.clu = *clu;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	return 0;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic int exfat_map_new_buffer(struct exfat_inode_info *ei,
2748c2ecf20Sopenharmony_ci		struct buffer_head *bh, loff_t pos)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	if (buffer_delay(bh) && pos > ei->i_size_aligned)
2778c2ecf20Sopenharmony_ci		return -EIO;
2788c2ecf20Sopenharmony_ci	set_buffer_new(bh);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	/*
2818c2ecf20Sopenharmony_ci	 * Adjust i_size_aligned if i_size_ondisk is bigger than it.
2828c2ecf20Sopenharmony_ci	 */
2838c2ecf20Sopenharmony_ci	if (ei->i_size_ondisk > ei->i_size_aligned)
2848c2ecf20Sopenharmony_ci		ei->i_size_aligned = ei->i_size_ondisk;
2858c2ecf20Sopenharmony_ci	return 0;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic int exfat_get_block(struct inode *inode, sector_t iblock,
2898c2ecf20Sopenharmony_ci		struct buffer_head *bh_result, int create)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct exfat_inode_info *ei = EXFAT_I(inode);
2928c2ecf20Sopenharmony_ci	struct super_block *sb = inode->i_sb;
2938c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(sb);
2948c2ecf20Sopenharmony_ci	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
2958c2ecf20Sopenharmony_ci	int err = 0;
2968c2ecf20Sopenharmony_ci	unsigned long mapped_blocks = 0;
2978c2ecf20Sopenharmony_ci	unsigned int cluster, sec_offset;
2988c2ecf20Sopenharmony_ci	sector_t last_block;
2998c2ecf20Sopenharmony_ci	sector_t phys = 0;
3008c2ecf20Sopenharmony_ci	loff_t pos;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	mutex_lock(&sbi->s_lock);
3038c2ecf20Sopenharmony_ci	last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb);
3048c2ecf20Sopenharmony_ci	if (iblock >= last_block && !create)
3058c2ecf20Sopenharmony_ci		goto done;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* Is this block already allocated? */
3088c2ecf20Sopenharmony_ci	err = exfat_map_cluster(inode, iblock >> sbi->sect_per_clus_bits,
3098c2ecf20Sopenharmony_ci			&cluster, create);
3108c2ecf20Sopenharmony_ci	if (err) {
3118c2ecf20Sopenharmony_ci		if (err != -ENOSPC)
3128c2ecf20Sopenharmony_ci			exfat_fs_error_ratelimit(sb,
3138c2ecf20Sopenharmony_ci				"failed to bmap (inode : %p iblock : %llu, err : %d)",
3148c2ecf20Sopenharmony_ci				inode, (unsigned long long)iblock, err);
3158c2ecf20Sopenharmony_ci		goto unlock_ret;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	if (cluster == EXFAT_EOF_CLUSTER)
3198c2ecf20Sopenharmony_ci		goto done;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/* sector offset in cluster */
3228c2ecf20Sopenharmony_ci	sec_offset = iblock & (sbi->sect_per_clus - 1);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	phys = exfat_cluster_to_sector(sbi, cluster) + sec_offset;
3258c2ecf20Sopenharmony_ci	mapped_blocks = sbi->sect_per_clus - sec_offset;
3268c2ecf20Sopenharmony_ci	max_blocks = min(mapped_blocks, max_blocks);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	/* Treat newly added block / cluster */
3298c2ecf20Sopenharmony_ci	if (iblock < last_block)
3308c2ecf20Sopenharmony_ci		create = 0;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (create || buffer_delay(bh_result)) {
3338c2ecf20Sopenharmony_ci		pos = EXFAT_BLK_TO_B((iblock + 1), sb);
3348c2ecf20Sopenharmony_ci		if (ei->i_size_ondisk < pos)
3358c2ecf20Sopenharmony_ci			ei->i_size_ondisk = pos;
3368c2ecf20Sopenharmony_ci	}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (create) {
3398c2ecf20Sopenharmony_ci		err = exfat_map_new_buffer(ei, bh_result, pos);
3408c2ecf20Sopenharmony_ci		if (err) {
3418c2ecf20Sopenharmony_ci			exfat_fs_error(sb,
3428c2ecf20Sopenharmony_ci					"requested for bmap out of range(pos : (%llu) > i_size_aligned(%llu)\n",
3438c2ecf20Sopenharmony_ci					pos, ei->i_size_aligned);
3448c2ecf20Sopenharmony_ci			goto unlock_ret;
3458c2ecf20Sopenharmony_ci		}
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	if (buffer_delay(bh_result))
3498c2ecf20Sopenharmony_ci		clear_buffer_delay(bh_result);
3508c2ecf20Sopenharmony_ci	map_bh(bh_result, sb, phys);
3518c2ecf20Sopenharmony_cidone:
3528c2ecf20Sopenharmony_ci	bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
3538c2ecf20Sopenharmony_ciunlock_ret:
3548c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->s_lock);
3558c2ecf20Sopenharmony_ci	return err;
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic int exfat_readpage(struct file *file, struct page *page)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	return mpage_readpage(page, exfat_get_block);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic void exfat_readahead(struct readahead_control *rac)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	mpage_readahead(rac, exfat_get_block);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic int exfat_writepage(struct page *page, struct writeback_control *wbc)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	return block_write_full_page(page, exfat_get_block, wbc);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic int exfat_writepages(struct address_space *mapping,
3748c2ecf20Sopenharmony_ci		struct writeback_control *wbc)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	return mpage_writepages(mapping, wbc, exfat_get_block);
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic void exfat_write_failed(struct address_space *mapping, loff_t to)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	if (to > i_size_read(inode)) {
3848c2ecf20Sopenharmony_ci		truncate_pagecache(inode, i_size_read(inode));
3858c2ecf20Sopenharmony_ci		exfat_truncate(inode, EXFAT_I(inode)->i_size_aligned);
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic int exfat_write_begin(struct file *file, struct address_space *mapping,
3908c2ecf20Sopenharmony_ci		loff_t pos, unsigned int len, unsigned int flags,
3918c2ecf20Sopenharmony_ci		struct page **pagep, void **fsdata)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	int ret;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	*pagep = NULL;
3968c2ecf20Sopenharmony_ci	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
3978c2ecf20Sopenharmony_ci			       exfat_get_block,
3988c2ecf20Sopenharmony_ci			       &EXFAT_I(mapping->host)->i_size_ondisk);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	if (ret < 0)
4018c2ecf20Sopenharmony_ci		exfat_write_failed(mapping, pos+len);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	return ret;
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic int exfat_write_end(struct file *file, struct address_space *mapping,
4078c2ecf20Sopenharmony_ci		loff_t pos, unsigned int len, unsigned int copied,
4088c2ecf20Sopenharmony_ci		struct page *pagep, void *fsdata)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
4118c2ecf20Sopenharmony_ci	struct exfat_inode_info *ei = EXFAT_I(inode);
4128c2ecf20Sopenharmony_ci	int err;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	if (ei->i_size_aligned < i_size_read(inode)) {
4178c2ecf20Sopenharmony_ci		exfat_fs_error(inode->i_sb,
4188c2ecf20Sopenharmony_ci			"invalid size(size(%llu) > aligned(%llu)\n",
4198c2ecf20Sopenharmony_ci			i_size_read(inode), ei->i_size_aligned);
4208c2ecf20Sopenharmony_ci		return -EIO;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	if (err < len)
4248c2ecf20Sopenharmony_ci		exfat_write_failed(mapping, pos+len);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (!(err < 0) && !(ei->attr & ATTR_ARCHIVE)) {
4278c2ecf20Sopenharmony_ci		inode->i_mtime = inode->i_ctime = current_time(inode);
4288c2ecf20Sopenharmony_ci		ei->attr |= ATTR_ARCHIVE;
4298c2ecf20Sopenharmony_ci		mark_inode_dirty(inode);
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	return err;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	struct address_space *mapping = iocb->ki_filp->f_mapping;
4388c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
4398c2ecf20Sopenharmony_ci	loff_t size = iocb->ki_pos + iov_iter_count(iter);
4408c2ecf20Sopenharmony_ci	int rw = iov_iter_rw(iter);
4418c2ecf20Sopenharmony_ci	ssize_t ret;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	if (rw == WRITE) {
4448c2ecf20Sopenharmony_ci		/*
4458c2ecf20Sopenharmony_ci		 * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
4468c2ecf20Sopenharmony_ci		 * so we need to update the ->i_size_aligned to block boundary.
4478c2ecf20Sopenharmony_ci		 *
4488c2ecf20Sopenharmony_ci		 * But we must fill the remaining area or hole by nul for
4498c2ecf20Sopenharmony_ci		 * updating ->i_size_aligned
4508c2ecf20Sopenharmony_ci		 *
4518c2ecf20Sopenharmony_ci		 * Return 0, and fallback to normal buffered write.
4528c2ecf20Sopenharmony_ci		 */
4538c2ecf20Sopenharmony_ci		if (EXFAT_I(inode)->i_size_aligned < size)
4548c2ecf20Sopenharmony_ci			return 0;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/*
4588c2ecf20Sopenharmony_ci	 * Need to use the DIO_LOCKING for avoiding the race
4598c2ecf20Sopenharmony_ci	 * condition of exfat_get_block() and ->truncate().
4608c2ecf20Sopenharmony_ci	 */
4618c2ecf20Sopenharmony_ci	ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);
4628c2ecf20Sopenharmony_ci	if (ret < 0 && (rw & WRITE))
4638c2ecf20Sopenharmony_ci		exfat_write_failed(mapping, size);
4648c2ecf20Sopenharmony_ci	return ret;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic sector_t exfat_aop_bmap(struct address_space *mapping, sector_t block)
4688c2ecf20Sopenharmony_ci{
4698c2ecf20Sopenharmony_ci	sector_t blocknr;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* exfat_get_cluster() assumes the requested blocknr isn't truncated. */
4728c2ecf20Sopenharmony_ci	down_read(&EXFAT_I(mapping->host)->truncate_lock);
4738c2ecf20Sopenharmony_ci	blocknr = generic_block_bmap(mapping, block, exfat_get_block);
4748c2ecf20Sopenharmony_ci	up_read(&EXFAT_I(mapping->host)->truncate_lock);
4758c2ecf20Sopenharmony_ci	return blocknr;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci/*
4798c2ecf20Sopenharmony_ci * exfat_block_truncate_page() zeroes out a mapping from file offset `from'
4808c2ecf20Sopenharmony_ci * up to the end of the block which corresponds to `from'.
4818c2ecf20Sopenharmony_ci * This is required during truncate to physically zeroout the tail end
4828c2ecf20Sopenharmony_ci * of that block so it doesn't yield old data if the file is later grown.
4838c2ecf20Sopenharmony_ci * Also, avoid causing failure from fsx for cases of "data past EOF"
4848c2ecf20Sopenharmony_ci */
4858c2ecf20Sopenharmony_ciint exfat_block_truncate_page(struct inode *inode, loff_t from)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	return block_truncate_page(inode->i_mapping, from, exfat_get_block);
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic const struct address_space_operations exfat_aops = {
4918c2ecf20Sopenharmony_ci	.readpage	= exfat_readpage,
4928c2ecf20Sopenharmony_ci	.readahead	= exfat_readahead,
4938c2ecf20Sopenharmony_ci	.writepage	= exfat_writepage,
4948c2ecf20Sopenharmony_ci	.writepages	= exfat_writepages,
4958c2ecf20Sopenharmony_ci	.write_begin	= exfat_write_begin,
4968c2ecf20Sopenharmony_ci	.write_end	= exfat_write_end,
4978c2ecf20Sopenharmony_ci	.direct_IO	= exfat_direct_IO,
4988c2ecf20Sopenharmony_ci	.bmap		= exfat_aop_bmap
4998c2ecf20Sopenharmony_ci};
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic inline unsigned long exfat_hash(loff_t i_pos)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	return hash_32(i_pos, EXFAT_HASH_BITS);
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_civoid exfat_hash_inode(struct inode *inode, loff_t i_pos)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
5098c2ecf20Sopenharmony_ci	struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	spin_lock(&sbi->inode_hash_lock);
5128c2ecf20Sopenharmony_ci	EXFAT_I(inode)->i_pos = i_pos;
5138c2ecf20Sopenharmony_ci	hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head);
5148c2ecf20Sopenharmony_ci	spin_unlock(&sbi->inode_hash_lock);
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_civoid exfat_unhash_inode(struct inode *inode)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	spin_lock(&sbi->inode_hash_lock);
5228c2ecf20Sopenharmony_ci	hlist_del_init(&EXFAT_I(inode)->i_hash_fat);
5238c2ecf20Sopenharmony_ci	EXFAT_I(inode)->i_pos = 0;
5248c2ecf20Sopenharmony_ci	spin_unlock(&sbi->inode_hash_lock);
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_cistruct inode *exfat_iget(struct super_block *sb, loff_t i_pos)
5288c2ecf20Sopenharmony_ci{
5298c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(sb);
5308c2ecf20Sopenharmony_ci	struct exfat_inode_info *info;
5318c2ecf20Sopenharmony_ci	struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos);
5328c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	spin_lock(&sbi->inode_hash_lock);
5358c2ecf20Sopenharmony_ci	hlist_for_each_entry(info, head, i_hash_fat) {
5368c2ecf20Sopenharmony_ci		WARN_ON(info->vfs_inode.i_sb != sb);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci		if (i_pos != info->i_pos)
5398c2ecf20Sopenharmony_ci			continue;
5408c2ecf20Sopenharmony_ci		inode = igrab(&info->vfs_inode);
5418c2ecf20Sopenharmony_ci		if (inode)
5428c2ecf20Sopenharmony_ci			break;
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci	spin_unlock(&sbi->inode_hash_lock);
5458c2ecf20Sopenharmony_ci	return inode;
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci/* doesn't deal with root inode */
5498c2ecf20Sopenharmony_cistatic int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
5528c2ecf20Sopenharmony_ci	struct exfat_inode_info *ei = EXFAT_I(inode);
5538c2ecf20Sopenharmony_ci	loff_t size = info->size;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	ei->dir = info->dir;
5568c2ecf20Sopenharmony_ci	ei->entry = info->entry;
5578c2ecf20Sopenharmony_ci	ei->attr = info->attr;
5588c2ecf20Sopenharmony_ci	ei->start_clu = info->start_clu;
5598c2ecf20Sopenharmony_ci	ei->flags = info->flags;
5608c2ecf20Sopenharmony_ci	ei->type = info->type;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	ei->version = 0;
5638c2ecf20Sopenharmony_ci	ei->hint_stat.eidx = 0;
5648c2ecf20Sopenharmony_ci	ei->hint_stat.clu = info->start_clu;
5658c2ecf20Sopenharmony_ci	ei->hint_femp.eidx = EXFAT_HINT_NONE;
5668c2ecf20Sopenharmony_ci	ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
5678c2ecf20Sopenharmony_ci	ei->i_pos = 0;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	inode->i_uid = sbi->options.fs_uid;
5708c2ecf20Sopenharmony_ci	inode->i_gid = sbi->options.fs_gid;
5718c2ecf20Sopenharmony_ci	inode_inc_iversion(inode);
5728c2ecf20Sopenharmony_ci	inode->i_generation = prandom_u32();
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	if (info->attr & ATTR_SUBDIR) { /* directory */
5758c2ecf20Sopenharmony_ci		inode->i_generation &= ~1;
5768c2ecf20Sopenharmony_ci		inode->i_mode = exfat_make_mode(sbi, info->attr, 0777);
5778c2ecf20Sopenharmony_ci		inode->i_op = &exfat_dir_inode_operations;
5788c2ecf20Sopenharmony_ci		inode->i_fop = &exfat_dir_operations;
5798c2ecf20Sopenharmony_ci		set_nlink(inode, info->num_subdirs);
5808c2ecf20Sopenharmony_ci	} else { /* regular file */
5818c2ecf20Sopenharmony_ci		inode->i_generation |= 1;
5828c2ecf20Sopenharmony_ci		inode->i_mode = exfat_make_mode(sbi, info->attr, 0777);
5838c2ecf20Sopenharmony_ci		inode->i_op = &exfat_file_inode_operations;
5848c2ecf20Sopenharmony_ci		inode->i_fop = &exfat_file_operations;
5858c2ecf20Sopenharmony_ci		inode->i_mapping->a_ops = &exfat_aops;
5868c2ecf20Sopenharmony_ci		inode->i_mapping->nrpages = 0;
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	i_size_write(inode, size);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	/* ondisk and aligned size should be aligned with block size */
5928c2ecf20Sopenharmony_ci	if (size & (inode->i_sb->s_blocksize - 1)) {
5938c2ecf20Sopenharmony_ci		size |= (inode->i_sb->s_blocksize - 1);
5948c2ecf20Sopenharmony_ci		size++;
5958c2ecf20Sopenharmony_ci	}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	ei->i_size_aligned = size;
5988c2ecf20Sopenharmony_ci	ei->i_size_ondisk = size;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	exfat_save_attr(inode, info->attr);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9;
6038c2ecf20Sopenharmony_ci	inode->i_mtime = info->mtime;
6048c2ecf20Sopenharmony_ci	inode->i_ctime = info->mtime;
6058c2ecf20Sopenharmony_ci	ei->i_crtime = info->crtime;
6068c2ecf20Sopenharmony_ci	inode->i_atime = info->atime;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	return 0;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistruct inode *exfat_build_inode(struct super_block *sb,
6128c2ecf20Sopenharmony_ci		struct exfat_dir_entry *info, loff_t i_pos)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	struct inode *inode;
6158c2ecf20Sopenharmony_ci	int err;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	inode = exfat_iget(sb, i_pos);
6188c2ecf20Sopenharmony_ci	if (inode)
6198c2ecf20Sopenharmony_ci		goto out;
6208c2ecf20Sopenharmony_ci	inode = new_inode(sb);
6218c2ecf20Sopenharmony_ci	if (!inode) {
6228c2ecf20Sopenharmony_ci		inode = ERR_PTR(-ENOMEM);
6238c2ecf20Sopenharmony_ci		goto out;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci	inode->i_ino = iunique(sb, EXFAT_ROOT_INO);
6268c2ecf20Sopenharmony_ci	inode_set_iversion(inode, 1);
6278c2ecf20Sopenharmony_ci	err = exfat_fill_inode(inode, info);
6288c2ecf20Sopenharmony_ci	if (err) {
6298c2ecf20Sopenharmony_ci		iput(inode);
6308c2ecf20Sopenharmony_ci		inode = ERR_PTR(err);
6318c2ecf20Sopenharmony_ci		goto out;
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci	exfat_hash_inode(inode, i_pos);
6348c2ecf20Sopenharmony_ci	insert_inode_hash(inode);
6358c2ecf20Sopenharmony_ciout:
6368c2ecf20Sopenharmony_ci	return inode;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_civoid exfat_evict_inode(struct inode *inode)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	truncate_inode_pages(&inode->i_data, 0);
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	if (!inode->i_nlink) {
6448c2ecf20Sopenharmony_ci		i_size_write(inode, 0);
6458c2ecf20Sopenharmony_ci		mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
6468c2ecf20Sopenharmony_ci		__exfat_truncate(inode, 0);
6478c2ecf20Sopenharmony_ci		mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
6488c2ecf20Sopenharmony_ci	}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	invalidate_inode_buffers(inode);
6518c2ecf20Sopenharmony_ci	clear_inode(inode);
6528c2ecf20Sopenharmony_ci	exfat_cache_inval_inode(inode);
6538c2ecf20Sopenharmony_ci	exfat_unhash_inode(inode);
6548c2ecf20Sopenharmony_ci}
655