xref: /linux/fs/ntfs/file.c (revision cdd4dc3aebeab43a72ce0bc2b5bab6f0a80b97a5)
11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later
21e9ea7e0SNamjae Jeon /*
39c879596SNamjae Jeon  * NTFS kernel file operations.
41e9ea7e0SNamjae Jeon  *
51e9ea7e0SNamjae Jeon  * Copyright (c) 2001-2015 Anton Altaparmakov and Tuxera Inc.
69c879596SNamjae Jeon  * Copyright (c) 2025 LG Electronics Co., Ltd.
71e9ea7e0SNamjae Jeon  */
81e9ea7e0SNamjae Jeon 
91e9ea7e0SNamjae Jeon #include <linux/writeback.h>
109c879596SNamjae Jeon #include <linux/blkdev.h>
119c879596SNamjae Jeon #include <linux/fs.h>
129c879596SNamjae Jeon #include <linux/iomap.h>
139c879596SNamjae Jeon #include <linux/uio.h>
149c879596SNamjae Jeon #include <linux/posix_acl.h>
159c879596SNamjae Jeon #include <linux/posix_acl_xattr.h>
169c879596SNamjae Jeon #include <linux/compat.h>
179c879596SNamjae Jeon #include <linux/falloc.h>
181e9ea7e0SNamjae Jeon 
191e9ea7e0SNamjae Jeon #include "lcnalloc.h"
201e9ea7e0SNamjae Jeon #include "ntfs.h"
219c879596SNamjae Jeon #include "reparse.h"
229c879596SNamjae Jeon #include "ea.h"
239c879596SNamjae Jeon #include "iomap.h"
249c879596SNamjae Jeon #include "bitmap.h"
251e9ea7e0SNamjae Jeon 
269c879596SNamjae Jeon #include <linux/filelock.h>
279c879596SNamjae Jeon 
289c879596SNamjae Jeon /*
291e9ea7e0SNamjae Jeon  * ntfs_file_open - called when an inode is about to be opened
301e9ea7e0SNamjae Jeon  * @vi:		inode to be opened
311e9ea7e0SNamjae Jeon  * @filp:	file structure describing the inode
321e9ea7e0SNamjae Jeon  *
331e9ea7e0SNamjae Jeon  * Limit file size to the page cache limit on architectures where unsigned long
341e9ea7e0SNamjae Jeon  * is 32-bits. This is the most we can do for now without overflowing the page
351e9ea7e0SNamjae Jeon  * cache page index. Doing it this way means we don't run into problems because
361e9ea7e0SNamjae Jeon  * of existing too large files. It would be better to allow the user to read
371e9ea7e0SNamjae Jeon  * the beginning of the file but I doubt very much anyone is going to hit this
381e9ea7e0SNamjae Jeon  * check on a 32-bit architecture, so there is no point in adding the extra
391e9ea7e0SNamjae Jeon  * complexity required to support this.
401e9ea7e0SNamjae Jeon  *
411e9ea7e0SNamjae Jeon  * On 64-bit architectures, the check is hopefully optimized away by the
421e9ea7e0SNamjae Jeon  * compiler.
431e9ea7e0SNamjae Jeon  *
441e9ea7e0SNamjae Jeon  * After the check passes, just call generic_file_open() to do its work.
451e9ea7e0SNamjae Jeon  */
461e9ea7e0SNamjae Jeon static int ntfs_file_open(struct inode *vi, struct file *filp)
471e9ea7e0SNamjae Jeon {
489c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
499c879596SNamjae Jeon 
509c879596SNamjae Jeon 	if (NVolShutdown(ni->vol))
519c879596SNamjae Jeon 		return -EIO;
529c879596SNamjae Jeon 
531e9ea7e0SNamjae Jeon 	if (sizeof(unsigned long) < 8) {
541e9ea7e0SNamjae Jeon 		if (i_size_read(vi) > MAX_LFS_FILESIZE)
551e9ea7e0SNamjae Jeon 			return -EOVERFLOW;
561e9ea7e0SNamjae Jeon 	}
579c879596SNamjae Jeon 
589c879596SNamjae Jeon 	filp->f_mode |= FMODE_NOWAIT | FMODE_CAN_ODIRECT;
599c879596SNamjae Jeon 
601e9ea7e0SNamjae Jeon 	return generic_file_open(vi, filp);
611e9ea7e0SNamjae Jeon }
621e9ea7e0SNamjae Jeon 
639c879596SNamjae Jeon /*
649c879596SNamjae Jeon  * Trim preallocated space on file release.
651e9ea7e0SNamjae Jeon  *
669c879596SNamjae Jeon  * When the preallo_size mount option is set (default 64KB), writes extend
679c879596SNamjae Jeon  * allocated_size and runlist in units of preallocated size to reduce
689c879596SNamjae Jeon  * runlist merge overhead for small writes. This can leave
699c879596SNamjae Jeon  * allocated_size > data_size if not all preallocated space is used.
701e9ea7e0SNamjae Jeon  *
719c879596SNamjae Jeon  * We perform the trim here because ->release() is called only when
729c879596SNamjae Jeon  * the file is no longer open. At this point, no further writes can occur,
739c879596SNamjae Jeon  * so it is safe to reclaim the unused preallocated space.
741e9ea7e0SNamjae Jeon  *
759c879596SNamjae Jeon  * Returns 0 on success, or negative error on failure.
761e9ea7e0SNamjae Jeon  */
779c879596SNamjae Jeon static int ntfs_trim_prealloc(struct inode *vi)
781e9ea7e0SNamjae Jeon {
799c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
809c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
819c879596SNamjae Jeon 	struct runlist_element *rl;
829c879596SNamjae Jeon 	s64 aligned_data_size;
839c879596SNamjae Jeon 	s64 vcn_ds, vcn_tr;
849c879596SNamjae Jeon 	ssize_t rc;
859c879596SNamjae Jeon 	int err = 0;
861e9ea7e0SNamjae Jeon 
871e9ea7e0SNamjae Jeon 	inode_lock(vi);
889c879596SNamjae Jeon 	mutex_lock(&ni->mrec_lock);
899c879596SNamjae Jeon 	down_write(&ni->runlist.lock);
909c879596SNamjae Jeon 
919c879596SNamjae Jeon 	aligned_data_size = round_up(ni->data_size, vol->cluster_size);
929c879596SNamjae Jeon 	if (aligned_data_size >= ni->allocated_size)
939c879596SNamjae Jeon 		goto out_unlock;
949c879596SNamjae Jeon 
959c879596SNamjae Jeon 	vcn_ds = ntfs_bytes_to_cluster(vol, aligned_data_size);
969c879596SNamjae Jeon 	vcn_tr = -1;
979c879596SNamjae Jeon 	rc = ni->runlist.count - 2;
989c879596SNamjae Jeon 	rl = ni->runlist.rl;
999c879596SNamjae Jeon 
1009c879596SNamjae Jeon 	while (rc >= 0 && rl[rc].lcn == LCN_HOLE && vcn_ds <= rl[rc].vcn) {
1019c879596SNamjae Jeon 		vcn_tr = rl[rc].vcn;
1029c879596SNamjae Jeon 		rc--;
1031e9ea7e0SNamjae Jeon 	}
1041e9ea7e0SNamjae Jeon 
1059c879596SNamjae Jeon 	if (vcn_tr >= 0) {
1069c879596SNamjae Jeon 		err = ntfs_rl_truncate_nolock(vol, &ni->runlist, vcn_tr);
1079c879596SNamjae Jeon 		if (err) {
1089c879596SNamjae Jeon 			kvfree(ni->runlist.rl);
1099c879596SNamjae Jeon 			ni->runlist.rl = NULL;
1109c879596SNamjae Jeon 			ntfs_error(vol->sb, "Preallocated block rollback failed");
1119c879596SNamjae Jeon 		} else {
1129c879596SNamjae Jeon 			ni->allocated_size = ntfs_cluster_to_bytes(vol, vcn_tr);
1139c879596SNamjae Jeon 			err = ntfs_attr_update_mapping_pairs(ni, 0);
1149c879596SNamjae Jeon 			if (err)
1159c879596SNamjae Jeon 				ntfs_error(vol->sb,
1169c879596SNamjae Jeon 					   "Failed to rollback mapping pairs for prealloc");
1179c879596SNamjae Jeon 		}
1189c879596SNamjae Jeon 	}
1199c879596SNamjae Jeon 
1209c879596SNamjae Jeon out_unlock:
1219c879596SNamjae Jeon 	up_write(&ni->runlist.lock);
1229c879596SNamjae Jeon 	mutex_unlock(&ni->mrec_lock);
1239c879596SNamjae Jeon 	inode_unlock(vi);
1249c879596SNamjae Jeon 
1259c879596SNamjae Jeon 	return err;
1269c879596SNamjae Jeon }
1279c879596SNamjae Jeon 
1289c879596SNamjae Jeon static int ntfs_file_release(struct inode *vi, struct file *filp)
1299c879596SNamjae Jeon {
1309c879596SNamjae Jeon 	if (!NInoCompressed(NTFS_I(vi)))
1319c879596SNamjae Jeon 		return ntfs_trim_prealloc(vi);
1329c879596SNamjae Jeon 
1339c879596SNamjae Jeon 	return 0;
1349c879596SNamjae Jeon }
1359c879596SNamjae Jeon 
1369c879596SNamjae Jeon /*
1371e9ea7e0SNamjae Jeon  * ntfs_file_fsync - sync a file to disk
1381e9ea7e0SNamjae Jeon  * @filp:	file to be synced
1399c879596SNamjae Jeon  * @start:	start offset to be synced
1409c879596SNamjae Jeon  * @end:	end offset to be synced
1411e9ea7e0SNamjae Jeon  * @datasync:	if non-zero only flush user data and not metadata
1421e9ea7e0SNamjae Jeon  *
1431e9ea7e0SNamjae Jeon  * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
1441e9ea7e0SNamjae Jeon  * system calls.  This function is inspired by fs/buffer.c::file_fsync().
1451e9ea7e0SNamjae Jeon  *
1461e9ea7e0SNamjae Jeon  * If @datasync is false, write the mft record and all associated extent mft
1471e9ea7e0SNamjae Jeon  * records as well as the $DATA attribute and then sync the block device.
1481e9ea7e0SNamjae Jeon  *
1491e9ea7e0SNamjae Jeon  * If @datasync is true and the attribute is non-resident, we skip the writing
1501e9ea7e0SNamjae Jeon  * of the mft record and all associated extent mft records (this might still
1511e9ea7e0SNamjae Jeon  * happen due to the write_inode_now() call).
1521e9ea7e0SNamjae Jeon  *
1531e9ea7e0SNamjae Jeon  * Also, if @datasync is true, we do not wait on the inode to be written out
1541e9ea7e0SNamjae Jeon  * but we always wait on the page cache pages to be written out.
1551e9ea7e0SNamjae Jeon  */
1561e9ea7e0SNamjae Jeon static int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end,
1571e9ea7e0SNamjae Jeon 			   int datasync)
1581e9ea7e0SNamjae Jeon {
1591e9ea7e0SNamjae Jeon 	struct inode *vi = filp->f_mapping->host;
1609c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
1619c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
1621e9ea7e0SNamjae Jeon 	int err, ret = 0;
1639c879596SNamjae Jeon 	struct inode *parent_vi, *ia_vi;
1649c879596SNamjae Jeon 	struct ntfs_attr_search_ctx *ctx;
1651e9ea7e0SNamjae Jeon 
166e7d82353SNamjae Jeon 	ntfs_debug("Entering for inode 0x%llx.", ni->mft_no);
1671e9ea7e0SNamjae Jeon 
1689c879596SNamjae Jeon 	if (NVolShutdown(vol))
1699c879596SNamjae Jeon 		return -EIO;
1709c879596SNamjae Jeon 
1711e9ea7e0SNamjae Jeon 	err = file_write_and_wait_range(filp, start, end);
1721e9ea7e0SNamjae Jeon 	if (err)
1731e9ea7e0SNamjae Jeon 		return err;
1741e9ea7e0SNamjae Jeon 
1751e9ea7e0SNamjae Jeon 	if (!datasync || !NInoNonResident(NTFS_I(vi)))
1761e9ea7e0SNamjae Jeon 		ret = __ntfs_write_inode(vi, 1);
1771e9ea7e0SNamjae Jeon 	write_inode_now(vi, !datasync);
1789c879596SNamjae Jeon 
1799c879596SNamjae Jeon 	ctx = ntfs_attr_get_search_ctx(ni, NULL);
1809c879596SNamjae Jeon 	if (!ctx)
1819c879596SNamjae Jeon 		return -ENOMEM;
1829c879596SNamjae Jeon 
1839c879596SNamjae Jeon 	mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL_CHILD);
1849c879596SNamjae Jeon 	while (!(err = ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx))) {
1859c879596SNamjae Jeon 		if (ctx->attr->type == AT_FILE_NAME) {
1869c879596SNamjae Jeon 			struct file_name_attr *fn = (struct file_name_attr *)((u8 *)ctx->attr +
1879c879596SNamjae Jeon 					le16_to_cpu(ctx->attr->data.resident.value_offset));
1889c879596SNamjae Jeon 
1899c879596SNamjae Jeon 			parent_vi = ntfs_iget(vi->i_sb, MREF_LE(fn->parent_directory));
1909c879596SNamjae Jeon 			if (IS_ERR(parent_vi))
1919c879596SNamjae Jeon 				continue;
1929c879596SNamjae Jeon 			mutex_lock_nested(&NTFS_I(parent_vi)->mrec_lock, NTFS_INODE_MUTEX_NORMAL);
1939c879596SNamjae Jeon 			ia_vi = ntfs_index_iget(parent_vi, I30, 4);
1949c879596SNamjae Jeon 			mutex_unlock(&NTFS_I(parent_vi)->mrec_lock);
1959c879596SNamjae Jeon 			if (IS_ERR(ia_vi)) {
1969c879596SNamjae Jeon 				iput(parent_vi);
1979c879596SNamjae Jeon 				continue;
1989c879596SNamjae Jeon 			}
1999c879596SNamjae Jeon 			write_inode_now(ia_vi, 1);
2009c879596SNamjae Jeon 			iput(ia_vi);
2019c879596SNamjae Jeon 			write_inode_now(parent_vi, 1);
2029c879596SNamjae Jeon 			iput(parent_vi);
2039c879596SNamjae Jeon 		} else if (ctx->attr->non_resident) {
2049c879596SNamjae Jeon 			struct inode *attr_vi;
2059c879596SNamjae Jeon 			__le16 *name;
2069c879596SNamjae Jeon 
2079c879596SNamjae Jeon 			name = (__le16 *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->name_offset));
2089c879596SNamjae Jeon 			if (ctx->attr->type == AT_DATA && ctx->attr->name_length == 0)
2099c879596SNamjae Jeon 				continue;
2109c879596SNamjae Jeon 
2119c879596SNamjae Jeon 			attr_vi = ntfs_attr_iget(vi, ctx->attr->type,
2129c879596SNamjae Jeon 						 name, ctx->attr->name_length);
2139c879596SNamjae Jeon 			if (IS_ERR(attr_vi))
2149c879596SNamjae Jeon 				continue;
2159c879596SNamjae Jeon 			spin_lock(&attr_vi->i_lock);
2169c879596SNamjae Jeon 			if (inode_state_read_once(attr_vi) & I_DIRTY_PAGES) {
2179c879596SNamjae Jeon 				spin_unlock(&attr_vi->i_lock);
2189c879596SNamjae Jeon 				filemap_write_and_wait(attr_vi->i_mapping);
2199c879596SNamjae Jeon 			} else
2209c879596SNamjae Jeon 				spin_unlock(&attr_vi->i_lock);
2219c879596SNamjae Jeon 			iput(attr_vi);
2229c879596SNamjae Jeon 		}
2239c879596SNamjae Jeon 	}
2249c879596SNamjae Jeon 	mutex_unlock(&ni->mrec_lock);
2259c879596SNamjae Jeon 	ntfs_attr_put_search_ctx(ctx);
2269c879596SNamjae Jeon 
2279c879596SNamjae Jeon 	write_inode_now(vol->mftbmp_ino, 1);
2289c879596SNamjae Jeon 	down_write(&vol->lcnbmp_lock);
2299c879596SNamjae Jeon 	write_inode_now(vol->lcnbmp_ino, 1);
2309c879596SNamjae Jeon 	up_write(&vol->lcnbmp_lock);
2319c879596SNamjae Jeon 	write_inode_now(vol->mft_ino, 1);
2329c879596SNamjae Jeon 
2331e9ea7e0SNamjae Jeon 	/*
2341e9ea7e0SNamjae Jeon 	 * NOTE: If we were to use mapping->private_list (see ext2 and
2351e9ea7e0SNamjae Jeon 	 * fs/buffer.c) for dirty blocks then we could optimize the below to be
2361e9ea7e0SNamjae Jeon 	 * sync_mapping_buffers(vi->i_mapping).
2371e9ea7e0SNamjae Jeon 	 */
2381e9ea7e0SNamjae Jeon 	err = sync_blockdev(vi->i_sb->s_bdev);
2391e9ea7e0SNamjae Jeon 	if (unlikely(err && !ret))
2401e9ea7e0SNamjae Jeon 		ret = err;
2411e9ea7e0SNamjae Jeon 	if (likely(!ret))
2421e9ea7e0SNamjae Jeon 		ntfs_debug("Done.");
2431e9ea7e0SNamjae Jeon 	else
2449c879596SNamjae Jeon 		ntfs_warning(vi->i_sb,
245e7d82353SNamjae Jeon 				"Failed to f%ssync inode 0x%llx.  Error %u.",
246e7d82353SNamjae Jeon 				datasync ? "data" : "", ni->mft_no, -ret);
2479c879596SNamjae Jeon 	if (!ret)
2489c879596SNamjae Jeon 		blkdev_issue_flush(vi->i_sb->s_bdev);
2491e9ea7e0SNamjae Jeon 	return ret;
2501e9ea7e0SNamjae Jeon }
2511e9ea7e0SNamjae Jeon 
2529c879596SNamjae Jeon static int ntfs_setattr_size(struct inode *vi, struct iattr *attr)
2539c879596SNamjae Jeon {
2549c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
2559c879596SNamjae Jeon 	int err;
2569c879596SNamjae Jeon 	loff_t old_size = vi->i_size;
2579c879596SNamjae Jeon 
2589c879596SNamjae Jeon 	if (NInoCompressed(ni) || NInoEncrypted(ni)) {
2599c879596SNamjae Jeon 		ntfs_warning(vi->i_sb,
2609c879596SNamjae Jeon 			"Changes in inode size are not supported yet for %s files, ignoring.",
2619c879596SNamjae Jeon 			NInoCompressed(ni) ? "compressed" : "encrypted");
2629c879596SNamjae Jeon 		return -EOPNOTSUPP;
2639c879596SNamjae Jeon 	}
2649c879596SNamjae Jeon 
2659c879596SNamjae Jeon 	err = inode_newsize_ok(vi, attr->ia_size);
2669c879596SNamjae Jeon 	if (err)
2679c879596SNamjae Jeon 		return err;
2689c879596SNamjae Jeon 
2699c879596SNamjae Jeon 	inode_dio_wait(vi);
2709c879596SNamjae Jeon 	/* Serialize against page faults */
2719c879596SNamjae Jeon 	if (NInoNonResident(NTFS_I(vi)) && attr->ia_size < old_size) {
2729c879596SNamjae Jeon 		err = iomap_truncate_page(vi, attr->ia_size, NULL,
2739c879596SNamjae Jeon 				&ntfs_read_iomap_ops,
2749c879596SNamjae Jeon 				&ntfs_iomap_folio_ops, NULL);
2759c879596SNamjae Jeon 		if (err)
2769c879596SNamjae Jeon 			return err;
2779c879596SNamjae Jeon 	}
2789c879596SNamjae Jeon 
2799c879596SNamjae Jeon 	truncate_setsize(vi, attr->ia_size);
2809c879596SNamjae Jeon 	err = ntfs_truncate_vfs(vi, attr->ia_size, old_size);
2819c879596SNamjae Jeon 	if (err) {
2829c879596SNamjae Jeon 		i_size_write(vi, old_size);
2839c879596SNamjae Jeon 		return err;
2849c879596SNamjae Jeon 	}
2859c879596SNamjae Jeon 
2869c879596SNamjae Jeon 	if (NInoNonResident(ni) && attr->ia_size > old_size &&
2879c879596SNamjae Jeon 	    old_size % PAGE_SIZE != 0) {
2889c879596SNamjae Jeon 		loff_t len = min_t(loff_t,
2899c879596SNamjae Jeon 				round_up(old_size, PAGE_SIZE) - old_size,
2909c879596SNamjae Jeon 				attr->ia_size - old_size);
2919c879596SNamjae Jeon 		err = iomap_zero_range(vi, old_size, len,
2929c879596SNamjae Jeon 				NULL, &ntfs_seek_iomap_ops,
2939c879596SNamjae Jeon 				&ntfs_iomap_folio_ops, NULL);
2949c879596SNamjae Jeon 	}
2959c879596SNamjae Jeon 
2969c879596SNamjae Jeon 	return err;
2979c879596SNamjae Jeon }
2989c879596SNamjae Jeon 
2999c879596SNamjae Jeon /*
3009c879596SNamjae Jeon  * ntfs_setattr
3019c879596SNamjae Jeon  *
3029c879596SNamjae Jeon  * Called from notify_change() when an attribute is being changed.
3039c879596SNamjae Jeon  *
3049c879596SNamjae Jeon  * NOTE: Changes in inode size are not supported yet for compressed or
3059c879596SNamjae Jeon  * encrypted files.
3069c879596SNamjae Jeon  */
3079c879596SNamjae Jeon int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
3089c879596SNamjae Jeon 		 struct iattr *attr)
3099c879596SNamjae Jeon {
3109c879596SNamjae Jeon 	struct inode *vi = d_inode(dentry);
3119c879596SNamjae Jeon 	int err;
3129c879596SNamjae Jeon 	unsigned int ia_valid = attr->ia_valid;
3139c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
3149c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
3159c879596SNamjae Jeon 
3169c879596SNamjae Jeon 	if (NVolShutdown(vol))
3179c879596SNamjae Jeon 		return -EIO;
3189c879596SNamjae Jeon 
3199c879596SNamjae Jeon 	err = setattr_prepare(idmap, dentry, attr);
3209c879596SNamjae Jeon 	if (err)
3219c879596SNamjae Jeon 		goto out;
3229c879596SNamjae Jeon 
3239c879596SNamjae Jeon 	if (!(vol->vol_flags & VOLUME_IS_DIRTY))
3249c879596SNamjae Jeon 		ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY);
3259c879596SNamjae Jeon 
3269c879596SNamjae Jeon 	if (ia_valid & ATTR_SIZE) {
3279c879596SNamjae Jeon 		err = ntfs_setattr_size(vi, attr);
3289c879596SNamjae Jeon 		if (err)
3299c879596SNamjae Jeon 			goto out;
3309c879596SNamjae Jeon 
3319c879596SNamjae Jeon 		ia_valid |= ATTR_MTIME | ATTR_CTIME;
3329c879596SNamjae Jeon 	}
3339c879596SNamjae Jeon 
3349c879596SNamjae Jeon 	setattr_copy(idmap, vi, attr);
3359c879596SNamjae Jeon 
3369c879596SNamjae Jeon 	if (vol->sb->s_flags & SB_POSIXACL && !S_ISLNK(vi->i_mode)) {
3379c879596SNamjae Jeon 		err = posix_acl_chmod(idmap, dentry, vi->i_mode);
3389c879596SNamjae Jeon 		if (err)
3399c879596SNamjae Jeon 			goto out;
3409c879596SNamjae Jeon 	}
3419c879596SNamjae Jeon 
3429c879596SNamjae Jeon 	if (0222 & vi->i_mode)
3439c879596SNamjae Jeon 		ni->flags &= ~FILE_ATTR_READONLY;
3449c879596SNamjae Jeon 	else
3459c879596SNamjae Jeon 		ni->flags |= FILE_ATTR_READONLY;
3469c879596SNamjae Jeon 
3479c879596SNamjae Jeon 	if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) {
3489c879596SNamjae Jeon 		unsigned int flags = 0;
3499c879596SNamjae Jeon 
3509c879596SNamjae Jeon 		if (ia_valid & ATTR_UID)
3519c879596SNamjae Jeon 			flags |= NTFS_EA_UID;
3529c879596SNamjae Jeon 		if (ia_valid & ATTR_GID)
3539c879596SNamjae Jeon 			flags |= NTFS_EA_GID;
3549c879596SNamjae Jeon 		if (ia_valid & ATTR_MODE)
3559c879596SNamjae Jeon 			flags |= NTFS_EA_MODE;
3569c879596SNamjae Jeon 
3579c879596SNamjae Jeon 		if (S_ISDIR(vi->i_mode))
3589c879596SNamjae Jeon 			vi->i_mode &= ~vol->dmask;
3599c879596SNamjae Jeon 		else
3609c879596SNamjae Jeon 			vi->i_mode &= ~vol->fmask;
3619c879596SNamjae Jeon 
3629c879596SNamjae Jeon 		mutex_lock(&ni->mrec_lock);
3639c879596SNamjae Jeon 		ntfs_ea_set_wsl_inode(vi, 0, NULL, flags);
3649c879596SNamjae Jeon 		mutex_unlock(&ni->mrec_lock);
3659c879596SNamjae Jeon 	}
3669c879596SNamjae Jeon 
3679c879596SNamjae Jeon 	mark_inode_dirty(vi);
3689c879596SNamjae Jeon out:
3699c879596SNamjae Jeon 	return err;
3709c879596SNamjae Jeon }
3719c879596SNamjae Jeon 
3729c879596SNamjae Jeon int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
3739c879596SNamjae Jeon 		struct kstat *stat, unsigned int request_mask,
3749c879596SNamjae Jeon 		unsigned int query_flags)
3759c879596SNamjae Jeon {
3769c879596SNamjae Jeon 	struct inode *inode = d_backing_inode(path->dentry);
3779c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(inode);
3789c879596SNamjae Jeon 
3799c879596SNamjae Jeon 	generic_fillattr(idmap, request_mask, inode, stat);
3809c879596SNamjae Jeon 
3819c879596SNamjae Jeon 	stat->blksize = NTFS_SB(inode->i_sb)->cluster_size;
3829c879596SNamjae Jeon 	stat->blocks = (((u64)NTFS_I(inode)->i_dealloc_clusters <<
3839c879596SNamjae Jeon 			NTFS_SB(inode->i_sb)->cluster_size_bits) >> 9) + inode->i_blocks;
3849c879596SNamjae Jeon 	stat->result_mask |= STATX_BTIME;
3859c879596SNamjae Jeon 	stat->btime = NTFS_I(inode)->i_crtime;
3869c879596SNamjae Jeon 
3879c879596SNamjae Jeon 	if (NInoCompressed(ni))
3889c879596SNamjae Jeon 		stat->attributes |= STATX_ATTR_COMPRESSED;
3899c879596SNamjae Jeon 
3909c879596SNamjae Jeon 	if (NInoEncrypted(ni))
3919c879596SNamjae Jeon 		stat->attributes |= STATX_ATTR_ENCRYPTED;
3929c879596SNamjae Jeon 
3939c879596SNamjae Jeon 	if (inode->i_flags & S_IMMUTABLE)
3949c879596SNamjae Jeon 		stat->attributes |= STATX_ATTR_IMMUTABLE;
3959c879596SNamjae Jeon 
3969c879596SNamjae Jeon 	if (inode->i_flags & S_APPEND)
3979c879596SNamjae Jeon 		stat->attributes |= STATX_ATTR_APPEND;
3989c879596SNamjae Jeon 
3999c879596SNamjae Jeon 	stat->attributes_mask |= STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED |
4009c879596SNamjae Jeon 				 STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND;
4019c879596SNamjae Jeon 
4029c879596SNamjae Jeon 	/*
4039c879596SNamjae Jeon 	 * If it's a compressed or encrypted file, NTFS currently
4049c879596SNamjae Jeon 	 * does not support DIO. For normal files, we report the bdev
4059c879596SNamjae Jeon 	 * logical block size.
4069c879596SNamjae Jeon 	 */
4079c879596SNamjae Jeon 	if (request_mask & STATX_DIOALIGN && S_ISREG(inode->i_mode)) {
4089c879596SNamjae Jeon 		unsigned int align =
4099c879596SNamjae Jeon 			bdev_logical_block_size(inode->i_sb->s_bdev);
4109c879596SNamjae Jeon 
4119c879596SNamjae Jeon 		stat->result_mask |= STATX_DIOALIGN;
4129c879596SNamjae Jeon 		if (!NInoCompressed(ni) && !NInoEncrypted(ni)) {
4139c879596SNamjae Jeon 			stat->dio_mem_align = align;
4149c879596SNamjae Jeon 			stat->dio_offset_align = align;
4159c879596SNamjae Jeon 		}
4169c879596SNamjae Jeon 	}
4179c879596SNamjae Jeon 
4189c879596SNamjae Jeon 	return 0;
4199c879596SNamjae Jeon }
4209c879596SNamjae Jeon 
4219c879596SNamjae Jeon static loff_t ntfs_file_llseek(struct file *file, loff_t offset, int whence)
4229c879596SNamjae Jeon {
4239c879596SNamjae Jeon 	struct inode *inode = file->f_mapping->host;
4249c879596SNamjae Jeon 
4259c879596SNamjae Jeon 	switch (whence) {
4269c879596SNamjae Jeon 	case SEEK_HOLE:
4279c879596SNamjae Jeon 		inode_lock_shared(inode);
4289c879596SNamjae Jeon 		offset = iomap_seek_hole(inode, offset, &ntfs_seek_iomap_ops);
4299c879596SNamjae Jeon 		inode_unlock_shared(inode);
4309c879596SNamjae Jeon 		break;
4319c879596SNamjae Jeon 	case SEEK_DATA:
4329c879596SNamjae Jeon 		inode_lock_shared(inode);
4339c879596SNamjae Jeon 		offset = iomap_seek_data(inode, offset, &ntfs_seek_iomap_ops);
4349c879596SNamjae Jeon 		inode_unlock_shared(inode);
4359c879596SNamjae Jeon 		break;
4369c879596SNamjae Jeon 	default:
4379c879596SNamjae Jeon 		return generic_file_llseek_size(file, offset, whence,
4389c879596SNamjae Jeon 						inode->i_sb->s_maxbytes,
4399c879596SNamjae Jeon 						i_size_read(inode));
4409c879596SNamjae Jeon 	}
4419c879596SNamjae Jeon 	if (offset < 0)
4429c879596SNamjae Jeon 		return offset;
4439c879596SNamjae Jeon 	return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
4449c879596SNamjae Jeon }
4459c879596SNamjae Jeon 
4469c879596SNamjae Jeon static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
4479c879596SNamjae Jeon {
4489c879596SNamjae Jeon 	struct inode *vi = file_inode(iocb->ki_filp);
4499c879596SNamjae Jeon 	struct super_block *sb = vi->i_sb;
4509c879596SNamjae Jeon 	ssize_t ret;
4519c879596SNamjae Jeon 
4529c879596SNamjae Jeon 	if (NVolShutdown(NTFS_SB(sb)))
4539c879596SNamjae Jeon 		return -EIO;
4549c879596SNamjae Jeon 
4559c879596SNamjae Jeon 	if (NInoCompressed(NTFS_I(vi)) && iocb->ki_flags & IOCB_DIRECT)
4569c879596SNamjae Jeon 		return -EOPNOTSUPP;
4579c879596SNamjae Jeon 
4589c879596SNamjae Jeon 	inode_lock_shared(vi);
4599c879596SNamjae Jeon 
4609c879596SNamjae Jeon 	if (iocb->ki_flags & IOCB_DIRECT) {
4619c879596SNamjae Jeon 		size_t count = iov_iter_count(to);
4629c879596SNamjae Jeon 
4639c879596SNamjae Jeon 		if ((iocb->ki_pos | count) & (sb->s_blocksize - 1)) {
4649c879596SNamjae Jeon 			ret = -EINVAL;
4659c879596SNamjae Jeon 			goto inode_unlock;
4669c879596SNamjae Jeon 		}
4679c879596SNamjae Jeon 
4689c879596SNamjae Jeon 		file_accessed(iocb->ki_filp);
4699c879596SNamjae Jeon 		ret = iomap_dio_rw(iocb, to, &ntfs_read_iomap_ops, NULL, 0,
4709c879596SNamjae Jeon 				NULL, 0);
4719c879596SNamjae Jeon 	} else {
4729c879596SNamjae Jeon 		ret = generic_file_read_iter(iocb, to);
4739c879596SNamjae Jeon 	}
4749c879596SNamjae Jeon 
4759c879596SNamjae Jeon inode_unlock:
4769c879596SNamjae Jeon 	inode_unlock_shared(vi);
4779c879596SNamjae Jeon 
4789c879596SNamjae Jeon 	return ret;
4799c879596SNamjae Jeon }
4809c879596SNamjae Jeon 
4819c879596SNamjae Jeon static int ntfs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
4829c879596SNamjae Jeon 		int error, unsigned int flags)
4839c879596SNamjae Jeon {
4849c879596SNamjae Jeon 	struct inode *inode = file_inode(iocb->ki_filp);
4859c879596SNamjae Jeon 
4869c879596SNamjae Jeon 	if (error)
4879c879596SNamjae Jeon 		return error;
4889c879596SNamjae Jeon 
4899c879596SNamjae Jeon 	if (size) {
4909c879596SNamjae Jeon 		if (i_size_read(inode) < iocb->ki_pos + size) {
4919c879596SNamjae Jeon 			i_size_write(inode, iocb->ki_pos + size);
4929c879596SNamjae Jeon 			mark_inode_dirty(inode);
4939c879596SNamjae Jeon 		}
4949c879596SNamjae Jeon 	}
4959c879596SNamjae Jeon 
4969c879596SNamjae Jeon 	return 0;
4979c879596SNamjae Jeon }
4989c879596SNamjae Jeon 
4999c879596SNamjae Jeon static const struct iomap_dio_ops ntfs_write_dio_ops = {
5009c879596SNamjae Jeon 	.end_io			= ntfs_file_write_dio_end_io,
5019c879596SNamjae Jeon };
5029c879596SNamjae Jeon 
5039c879596SNamjae Jeon static ssize_t ntfs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
5049c879596SNamjae Jeon {
5059c879596SNamjae Jeon 	ssize_t ret;
5069c879596SNamjae Jeon 
5079c879596SNamjae Jeon 	ret = iomap_dio_rw(iocb, from, &ntfs_dio_iomap_ops,
5089c879596SNamjae Jeon 			&ntfs_write_dio_ops, 0, NULL, 0);
5099c879596SNamjae Jeon 	if (ret == -ENOTBLK)
5109c879596SNamjae Jeon 		ret = 0;
5119c879596SNamjae Jeon 	else if (ret < 0)
5129c879596SNamjae Jeon 		goto out;
5139c879596SNamjae Jeon 
5149c879596SNamjae Jeon 	if (iov_iter_count(from)) {
5159c879596SNamjae Jeon 		loff_t offset, end;
5169c879596SNamjae Jeon 		ssize_t written;
5179c879596SNamjae Jeon 		int ret2;
5189c879596SNamjae Jeon 
5199c879596SNamjae Jeon 		offset = iocb->ki_pos;
5209c879596SNamjae Jeon 		iocb->ki_flags &= ~IOCB_DIRECT;
5219c879596SNamjae Jeon 		written = iomap_file_buffered_write(iocb, from,
5229c879596SNamjae Jeon 				&ntfs_write_iomap_ops, &ntfs_iomap_folio_ops,
5239c879596SNamjae Jeon 				NULL);
5249c879596SNamjae Jeon 		if (written < 0) {
5259c879596SNamjae Jeon 			ret = written;
5269c879596SNamjae Jeon 			goto out;
5279c879596SNamjae Jeon 		}
5289c879596SNamjae Jeon 
5299c879596SNamjae Jeon 		ret += written;
5309c879596SNamjae Jeon 		end = iocb->ki_pos + written - 1;
5319c879596SNamjae Jeon 		ret2 = filemap_write_and_wait_range(iocb->ki_filp->f_mapping,
5329c879596SNamjae Jeon 				offset, end);
5339c879596SNamjae Jeon 		if (ret2) {
5349c879596SNamjae Jeon 			ret = -EIO;
5359c879596SNamjae Jeon 			goto out;
5369c879596SNamjae Jeon 		}
5379c879596SNamjae Jeon 		if (!ret2)
5389c879596SNamjae Jeon 			invalidate_mapping_pages(iocb->ki_filp->f_mapping,
5399c879596SNamjae Jeon 						 offset >> PAGE_SHIFT,
5409c879596SNamjae Jeon 						 end >> PAGE_SHIFT);
5419c879596SNamjae Jeon 	}
5429c879596SNamjae Jeon 
5439c879596SNamjae Jeon out:
5449c879596SNamjae Jeon 	return ret;
5459c879596SNamjae Jeon }
5469c879596SNamjae Jeon 
5479c879596SNamjae Jeon static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
5489c879596SNamjae Jeon {
5499c879596SNamjae Jeon 	struct file *file = iocb->ki_filp;
5509c879596SNamjae Jeon 	struct inode *vi = file->f_mapping->host;
5519c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
5529c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
5539c879596SNamjae Jeon 	ssize_t ret;
5549c879596SNamjae Jeon 	ssize_t count;
5559c879596SNamjae Jeon 	loff_t pos;
5569c879596SNamjae Jeon 	int err;
5579c879596SNamjae Jeon 	loff_t old_data_size, old_init_size;
5589c879596SNamjae Jeon 
5599c879596SNamjae Jeon 	if (NVolShutdown(vol))
5609c879596SNamjae Jeon 		return -EIO;
5619c879596SNamjae Jeon 
5629c879596SNamjae Jeon 	if (NInoEncrypted(ni)) {
5639c879596SNamjae Jeon 		ntfs_error(vi->i_sb, "Writing for %s files is not supported yet",
5649c879596SNamjae Jeon 			   NInoCompressed(ni) ? "Compressed" : "Encrypted");
5659c879596SNamjae Jeon 		return -EOPNOTSUPP;
5669c879596SNamjae Jeon 	}
5679c879596SNamjae Jeon 
5689c879596SNamjae Jeon 	if (NInoCompressed(ni) && iocb->ki_flags & IOCB_DIRECT)
5699c879596SNamjae Jeon 		return -EOPNOTSUPP;
5709c879596SNamjae Jeon 
5719c879596SNamjae Jeon 	if (iocb->ki_flags & IOCB_NOWAIT) {
5729c879596SNamjae Jeon 		if (!inode_trylock(vi))
5739c879596SNamjae Jeon 			return -EAGAIN;
5749c879596SNamjae Jeon 	} else
5759c879596SNamjae Jeon 		inode_lock(vi);
5769c879596SNamjae Jeon 
5779c879596SNamjae Jeon 	ret = generic_write_checks(iocb, from);
5789c879596SNamjae Jeon 	if (ret <= 0)
5799c879596SNamjae Jeon 		goto out_lock;
5809c879596SNamjae Jeon 
5819c879596SNamjae Jeon 	err = file_modified(iocb->ki_filp);
5829c879596SNamjae Jeon 	if (err) {
5839c879596SNamjae Jeon 		ret = err;
5849c879596SNamjae Jeon 		goto out_lock;
5859c879596SNamjae Jeon 	}
5869c879596SNamjae Jeon 
5879c879596SNamjae Jeon 	if (!(vol->vol_flags & VOLUME_IS_DIRTY))
5889c879596SNamjae Jeon 		ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY);
5899c879596SNamjae Jeon 
5909c879596SNamjae Jeon 	pos = iocb->ki_pos;
5919c879596SNamjae Jeon 	count = ret;
5929c879596SNamjae Jeon 
5939c879596SNamjae Jeon 	old_data_size = ni->data_size;
5949c879596SNamjae Jeon 	old_init_size = ni->initialized_size;
5959c879596SNamjae Jeon 
5969c879596SNamjae Jeon 	if (NInoNonResident(ni) && NInoCompressed(ni)) {
5979c879596SNamjae Jeon 		ret = ntfs_compress_write(ni, pos, count, from);
5989c879596SNamjae Jeon 		if (ret > 0)
5999c879596SNamjae Jeon 			iocb->ki_pos += ret;
6009c879596SNamjae Jeon 		goto out;
6019c879596SNamjae Jeon 	}
6029c879596SNamjae Jeon 
6039c879596SNamjae Jeon 	if (NInoNonResident(ni) && iocb->ki_flags & IOCB_DIRECT)
6049c879596SNamjae Jeon 		ret = ntfs_dio_write_iter(iocb, from);
6059c879596SNamjae Jeon 	else
6069c879596SNamjae Jeon 		ret = iomap_file_buffered_write(iocb, from, &ntfs_write_iomap_ops,
6079c879596SNamjae Jeon 				&ntfs_iomap_folio_ops, NULL);
6089c879596SNamjae Jeon out:
6099c879596SNamjae Jeon 	if (ret < 0 && ret != -EIOCBQUEUED) {
6109c879596SNamjae Jeon 		if (ni->initialized_size != old_init_size) {
6119c879596SNamjae Jeon 			mutex_lock(&ni->mrec_lock);
6129c879596SNamjae Jeon 			ntfs_attr_set_initialized_size(ni, old_init_size);
6139c879596SNamjae Jeon 			mutex_unlock(&ni->mrec_lock);
6149c879596SNamjae Jeon 		}
6159c879596SNamjae Jeon 		if (ni->data_size != old_data_size) {
6169c879596SNamjae Jeon 			truncate_setsize(vi, old_data_size);
6179c879596SNamjae Jeon 			ntfs_attr_truncate(ni, old_data_size);
6189c879596SNamjae Jeon 		}
6199c879596SNamjae Jeon 	}
6209c879596SNamjae Jeon out_lock:
6219c879596SNamjae Jeon 	inode_unlock(vi);
6229c879596SNamjae Jeon 	if (ret > 0)
6239c879596SNamjae Jeon 		ret = generic_write_sync(iocb, ret);
6249c879596SNamjae Jeon 	return ret;
6259c879596SNamjae Jeon }
6269c879596SNamjae Jeon 
6279c879596SNamjae Jeon static vm_fault_t ntfs_filemap_page_mkwrite(struct vm_fault *vmf)
6289c879596SNamjae Jeon {
6299c879596SNamjae Jeon 	struct inode *inode = file_inode(vmf->vma->vm_file);
6309c879596SNamjae Jeon 	vm_fault_t ret;
6319c879596SNamjae Jeon 
6329c879596SNamjae Jeon 	sb_start_pagefault(inode->i_sb);
6339c879596SNamjae Jeon 	file_update_time(vmf->vma->vm_file);
6349c879596SNamjae Jeon 
6359c879596SNamjae Jeon 	ret = iomap_page_mkwrite(vmf, &ntfs_page_mkwrite_iomap_ops, NULL);
6369c879596SNamjae Jeon 	sb_end_pagefault(inode->i_sb);
6379c879596SNamjae Jeon 	return ret;
6389c879596SNamjae Jeon }
6399c879596SNamjae Jeon 
6409c879596SNamjae Jeon static const struct vm_operations_struct ntfs_file_vm_ops = {
6419c879596SNamjae Jeon 	.fault		= filemap_fault,
6429c879596SNamjae Jeon 	.map_pages	= filemap_map_pages,
6439c879596SNamjae Jeon 	.page_mkwrite	= ntfs_filemap_page_mkwrite,
6449c879596SNamjae Jeon };
6459c879596SNamjae Jeon 
6469c879596SNamjae Jeon static int ntfs_file_mmap_prepare(struct vm_area_desc *desc)
6479c879596SNamjae Jeon {
6489c879596SNamjae Jeon 	struct file *file = desc->file;
6499c879596SNamjae Jeon 	struct inode *inode = file_inode(file);
6509c879596SNamjae Jeon 
6519c879596SNamjae Jeon 	if (NVolShutdown(NTFS_SB(file->f_mapping->host->i_sb)))
6529c879596SNamjae Jeon 		return -EIO;
6539c879596SNamjae Jeon 
6549c879596SNamjae Jeon 	if (NInoCompressed(NTFS_I(inode)))
6559c879596SNamjae Jeon 		return -EOPNOTSUPP;
6569c879596SNamjae Jeon 
657*cdd4dc3aSLinus Torvalds 	if (vma_desc_test(desc, VMA_WRITE_BIT)) {
6589c879596SNamjae Jeon 		struct inode *inode = file_inode(file);
6599c879596SNamjae Jeon 		loff_t from, to;
6609c879596SNamjae Jeon 		int err;
6619c879596SNamjae Jeon 
6629c879596SNamjae Jeon 		from = ((loff_t)desc->pgoff << PAGE_SHIFT);
6639c879596SNamjae Jeon 		to = min_t(loff_t, i_size_read(inode),
6649c879596SNamjae Jeon 			   from + desc->end - desc->start);
6659c879596SNamjae Jeon 
6669c879596SNamjae Jeon 		if (NTFS_I(inode)->initialized_size < to) {
6679c879596SNamjae Jeon 			err = ntfs_extend_initialized_size(inode, to, to, false);
6689c879596SNamjae Jeon 			if (err)
6699c879596SNamjae Jeon 				return err;
6709c879596SNamjae Jeon 		}
6719c879596SNamjae Jeon 	}
6729c879596SNamjae Jeon 
6739c879596SNamjae Jeon 
6749c879596SNamjae Jeon 	file_accessed(file);
6759c879596SNamjae Jeon 	desc->vm_ops = &ntfs_file_vm_ops;
6769c879596SNamjae Jeon 	return 0;
6779c879596SNamjae Jeon }
6789c879596SNamjae Jeon 
6799c879596SNamjae Jeon static int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
6809c879596SNamjae Jeon 		u64 start, u64 len)
6819c879596SNamjae Jeon {
6829c879596SNamjae Jeon 	return iomap_fiemap(inode, fieinfo, start, len, &ntfs_read_iomap_ops);
6839c879596SNamjae Jeon }
6849c879596SNamjae Jeon 
6859c879596SNamjae Jeon static const char *ntfs_get_link(struct dentry *dentry, struct inode *inode,
6869c879596SNamjae Jeon 		struct delayed_call *done)
6879c879596SNamjae Jeon {
6889c879596SNamjae Jeon 	if (!NTFS_I(inode)->target)
6899c879596SNamjae Jeon 		return ERR_PTR(-EINVAL);
6909c879596SNamjae Jeon 
6919c879596SNamjae Jeon 	return NTFS_I(inode)->target;
6929c879596SNamjae Jeon }
6939c879596SNamjae Jeon 
6949c879596SNamjae Jeon static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos,
6959c879596SNamjae Jeon 		struct pipe_inode_info *pipe, size_t len, unsigned int flags)
6969c879596SNamjae Jeon {
6979c879596SNamjae Jeon 	if (NVolShutdown(NTFS_SB(in->f_mapping->host->i_sb)))
6989c879596SNamjae Jeon 		return -EIO;
6999c879596SNamjae Jeon 
7009c879596SNamjae Jeon 	return filemap_splice_read(in, ppos, pipe, len, flags);
7019c879596SNamjae Jeon }
7029c879596SNamjae Jeon 
7039c879596SNamjae Jeon static int ntfs_ioctl_shutdown(struct super_block *sb, unsigned long arg)
7049c879596SNamjae Jeon {
7059c879596SNamjae Jeon 	u32 flags;
7069c879596SNamjae Jeon 
7079c879596SNamjae Jeon 	if (!capable(CAP_SYS_ADMIN))
7089c879596SNamjae Jeon 		return -EPERM;
7099c879596SNamjae Jeon 
7109c879596SNamjae Jeon 	if (get_user(flags, (__u32 __user *)arg))
7119c879596SNamjae Jeon 		return -EFAULT;
7129c879596SNamjae Jeon 
7139c879596SNamjae Jeon 	return ntfs_force_shutdown(sb, flags);
7149c879596SNamjae Jeon }
7159c879596SNamjae Jeon 
7169c879596SNamjae Jeon static int ntfs_ioctl_get_volume_label(struct file *filp, unsigned long arg)
7179c879596SNamjae Jeon {
7189c879596SNamjae Jeon 	struct ntfs_volume *vol = NTFS_SB(file_inode(filp)->i_sb);
7199c879596SNamjae Jeon 	char __user *buf = (char __user *)arg;
7209c879596SNamjae Jeon 
7219c879596SNamjae Jeon 	if (!vol->volume_label) {
7229c879596SNamjae Jeon 		if (copy_to_user(buf, "", 1))
7239c879596SNamjae Jeon 			return -EFAULT;
7249c879596SNamjae Jeon 	} else if (copy_to_user(buf, vol->volume_label,
7259c879596SNamjae Jeon 				MIN(FSLABEL_MAX, strlen(vol->volume_label) + 1)))
7269c879596SNamjae Jeon 		return -EFAULT;
7279c879596SNamjae Jeon 	return 0;
7289c879596SNamjae Jeon }
7299c879596SNamjae Jeon 
7309c879596SNamjae Jeon static int ntfs_ioctl_set_volume_label(struct file *filp, unsigned long arg)
7319c879596SNamjae Jeon {
7329c879596SNamjae Jeon 	struct ntfs_volume *vol = NTFS_SB(file_inode(filp)->i_sb);
7339c879596SNamjae Jeon 	char *label;
7349c879596SNamjae Jeon 	int ret;
7359c879596SNamjae Jeon 
7369c879596SNamjae Jeon 	if (!capable(CAP_SYS_ADMIN))
7379c879596SNamjae Jeon 		return -EPERM;
7389c879596SNamjae Jeon 
7399c879596SNamjae Jeon 	label = strndup_user((const char __user *)arg, FSLABEL_MAX);
7409c879596SNamjae Jeon 	if (IS_ERR(label))
7419c879596SNamjae Jeon 		return PTR_ERR(label);
7429c879596SNamjae Jeon 
7439c879596SNamjae Jeon 	ret = mnt_want_write_file(filp);
7449c879596SNamjae Jeon 	if (ret)
7459c879596SNamjae Jeon 		goto out;
7469c879596SNamjae Jeon 
7479c879596SNamjae Jeon 	ret = ntfs_write_volume_label(vol, label);
7489c879596SNamjae Jeon 	mnt_drop_write_file(filp);
7499c879596SNamjae Jeon out:
7509c879596SNamjae Jeon 	kfree(label);
7519c879596SNamjae Jeon 	return ret;
7529c879596SNamjae Jeon }
7539c879596SNamjae Jeon 
7549c879596SNamjae Jeon static int ntfs_ioctl_fitrim(struct ntfs_volume *vol, unsigned long arg)
7559c879596SNamjae Jeon {
7569c879596SNamjae Jeon 	struct fstrim_range __user *user_range;
7579c879596SNamjae Jeon 	struct fstrim_range range;
7589c879596SNamjae Jeon 	struct block_device *dev;
7599c879596SNamjae Jeon 	int err;
7609c879596SNamjae Jeon 
7619c879596SNamjae Jeon 	if (!capable(CAP_SYS_ADMIN))
7629c879596SNamjae Jeon 		return -EPERM;
7639c879596SNamjae Jeon 
7649c879596SNamjae Jeon 	dev = vol->sb->s_bdev;
7659c879596SNamjae Jeon 	if (!bdev_max_discard_sectors(dev))
7669c879596SNamjae Jeon 		return -EOPNOTSUPP;
7679c879596SNamjae Jeon 
7689c879596SNamjae Jeon 	user_range = (struct fstrim_range __user *)arg;
7699c879596SNamjae Jeon 	if (copy_from_user(&range, user_range, sizeof(range)))
7709c879596SNamjae Jeon 		return -EFAULT;
7719c879596SNamjae Jeon 
7729c879596SNamjae Jeon 	if (range.len == 0)
7739c879596SNamjae Jeon 		return -EINVAL;
7749c879596SNamjae Jeon 
7759c879596SNamjae Jeon 	if (range.len < vol->cluster_size)
7769c879596SNamjae Jeon 		return -EINVAL;
7779c879596SNamjae Jeon 
7789c879596SNamjae Jeon 	range.minlen = max_t(u32, range.minlen, bdev_discard_granularity(dev));
7799c879596SNamjae Jeon 
7809c879596SNamjae Jeon 	err = ntfs_trim_fs(vol, &range);
7819c879596SNamjae Jeon 	if (err < 0)
7829c879596SNamjae Jeon 		return err;
7839c879596SNamjae Jeon 
7849c879596SNamjae Jeon 	if (copy_to_user(user_range, &range, sizeof(range)))
7859c879596SNamjae Jeon 		return -EFAULT;
7869c879596SNamjae Jeon 
7879c879596SNamjae Jeon 	return 0;
7889c879596SNamjae Jeon }
7899c879596SNamjae Jeon 
7909c879596SNamjae Jeon long ntfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
7919c879596SNamjae Jeon {
7929c879596SNamjae Jeon 	switch (cmd) {
7939c879596SNamjae Jeon 	case FS_IOC_SHUTDOWN:
7949c879596SNamjae Jeon 		return ntfs_ioctl_shutdown(file_inode(filp)->i_sb, arg);
7959c879596SNamjae Jeon 	case FS_IOC_GETFSLABEL:
7969c879596SNamjae Jeon 		return ntfs_ioctl_get_volume_label(filp, arg);
7979c879596SNamjae Jeon 	case FS_IOC_SETFSLABEL:
7989c879596SNamjae Jeon 		return ntfs_ioctl_set_volume_label(filp, arg);
7999c879596SNamjae Jeon 	case FITRIM:
8009c879596SNamjae Jeon 		return ntfs_ioctl_fitrim(NTFS_SB(file_inode(filp)->i_sb), arg);
8019c879596SNamjae Jeon 	default:
8029c879596SNamjae Jeon 		return -ENOTTY;
8039c879596SNamjae Jeon 	}
8049c879596SNamjae Jeon }
8059c879596SNamjae Jeon 
8069c879596SNamjae Jeon #ifdef CONFIG_COMPAT
8079c879596SNamjae Jeon long ntfs_compat_ioctl(struct file *filp, unsigned int cmd,
8089c879596SNamjae Jeon 		unsigned long arg)
8099c879596SNamjae Jeon {
8109c879596SNamjae Jeon 	return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
8119c879596SNamjae Jeon }
8129c879596SNamjae Jeon #endif
8139c879596SNamjae Jeon 
8149c879596SNamjae Jeon static int ntfs_allocate_range(struct ntfs_inode *ni, int mode, loff_t offset,
8159c879596SNamjae Jeon 		loff_t len)
8169c879596SNamjae Jeon {
8179c879596SNamjae Jeon 	struct inode *vi = VFS_I(ni);
8189c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
8199c879596SNamjae Jeon 	s64 need_space;
8209c879596SNamjae Jeon 	loff_t old_size, new_size;
8219c879596SNamjae Jeon 	s64 start_vcn, end_vcn;
8229c879596SNamjae Jeon 	int err;
8239c879596SNamjae Jeon 
8249c879596SNamjae Jeon 	old_size = i_size_read(vi);
8259c879596SNamjae Jeon 	new_size = max_t(loff_t, old_size, offset + len);
8269c879596SNamjae Jeon 	start_vcn = ntfs_bytes_to_cluster(vol, offset);
8279c879596SNamjae Jeon 	end_vcn = ntfs_bytes_to_cluster(vol, offset + len - 1) + 1;
8289c879596SNamjae Jeon 
8299c879596SNamjae Jeon 	err = inode_newsize_ok(vi, new_size);
8309c879596SNamjae Jeon 	if (err)
8319c879596SNamjae Jeon 		goto out;
8329c879596SNamjae Jeon 
8339c879596SNamjae Jeon 	need_space = ntfs_bytes_to_cluster(vol, ni->allocated_size);
8349c879596SNamjae Jeon 	if (need_space > start_vcn)
8359c879596SNamjae Jeon 		need_space = end_vcn - need_space;
8369c879596SNamjae Jeon 	else
8379c879596SNamjae Jeon 		need_space = end_vcn - start_vcn;
8389c879596SNamjae Jeon 	if (need_space > 0 &&
8399c879596SNamjae Jeon 	    need_space > (atomic64_read(&vol->free_clusters) -
8409c879596SNamjae Jeon 			  atomic64_read(&vol->dirty_clusters))) {
8419c879596SNamjae Jeon 		err = -ENOSPC;
8429c879596SNamjae Jeon 		goto out;
8439c879596SNamjae Jeon 	}
8449c879596SNamjae Jeon 
8459c879596SNamjae Jeon 	err = ntfs_attr_fallocate(ni, offset, len,
8469c879596SNamjae Jeon 			mode & FALLOC_FL_KEEP_SIZE ? true : false);
8479c879596SNamjae Jeon 
8489c879596SNamjae Jeon 	if (!(mode & FALLOC_FL_KEEP_SIZE) && new_size != old_size)
8499c879596SNamjae Jeon 		i_size_write(vi, ni->data_size);
8509c879596SNamjae Jeon out:
8519c879596SNamjae Jeon 	return err;
8529c879596SNamjae Jeon }
8539c879596SNamjae Jeon 
8549c879596SNamjae Jeon static int ntfs_punch_hole(struct ntfs_inode *ni, int mode, loff_t offset,
8559c879596SNamjae Jeon 		loff_t len)
8569c879596SNamjae Jeon {
8579c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
8589c879596SNamjae Jeon 	struct inode *vi = VFS_I(ni);
8599c879596SNamjae Jeon 	loff_t end_offset;
8609c879596SNamjae Jeon 	s64 start_vcn, end_vcn;
8619c879596SNamjae Jeon 	int err = 0;
8629c879596SNamjae Jeon 
8639c879596SNamjae Jeon 	loff_t offset_down = round_down(offset, max_t(unsigned int,
8649c879596SNamjae Jeon 				vol->cluster_size, PAGE_SIZE));
8659c879596SNamjae Jeon 
8669c879596SNamjae Jeon 	if (NVolDisableSparse(vol)) {
8679c879596SNamjae Jeon 		err = -EOPNOTSUPP;
8689c879596SNamjae Jeon 		goto out;
8699c879596SNamjae Jeon 	}
8709c879596SNamjae Jeon 
8719c879596SNamjae Jeon 	if (offset >= ni->data_size)
8729c879596SNamjae Jeon 		goto out;
8739c879596SNamjae Jeon 
8749c879596SNamjae Jeon 	if (offset + len > ni->data_size)
8759c879596SNamjae Jeon 		end_offset = ni->data_size;
8769c879596SNamjae Jeon 	else
8779c879596SNamjae Jeon 		end_offset = offset + len;
8789c879596SNamjae Jeon 
8799c879596SNamjae Jeon 	err = filemap_write_and_wait_range(vi->i_mapping, offset_down, LLONG_MAX);
8809c879596SNamjae Jeon 	if (err)
8819c879596SNamjae Jeon 		goto out;
8829c879596SNamjae Jeon 	truncate_pagecache(vi, offset_down);
8839c879596SNamjae Jeon 
8849c879596SNamjae Jeon 	start_vcn = ntfs_bytes_to_cluster(vol, offset);
8859c879596SNamjae Jeon 	end_vcn = ntfs_bytes_to_cluster(vol, end_offset - 1) + 1;
8869c879596SNamjae Jeon 
8879c879596SNamjae Jeon 	if (offset & vol->cluster_size_mask) {
8889c879596SNamjae Jeon 		loff_t to;
8899c879596SNamjae Jeon 
8909c879596SNamjae Jeon 		to = min_t(loff_t, ntfs_cluster_to_bytes(vol, start_vcn + 1),
8919c879596SNamjae Jeon 				end_offset);
8929c879596SNamjae Jeon 		err = iomap_zero_range(vi, offset, to - offset, NULL,
8939c879596SNamjae Jeon 				&ntfs_seek_iomap_ops,
8949c879596SNamjae Jeon 				&ntfs_iomap_folio_ops, NULL);
8959c879596SNamjae Jeon 		if (err < 0 || (end_vcn - start_vcn) == 1)
8969c879596SNamjae Jeon 			goto out;
8979c879596SNamjae Jeon 		start_vcn++;
8989c879596SNamjae Jeon 	}
8999c879596SNamjae Jeon 
9009c879596SNamjae Jeon 	if (end_offset & vol->cluster_size_mask) {
9019c879596SNamjae Jeon 		loff_t from;
9029c879596SNamjae Jeon 
9039c879596SNamjae Jeon 		from = ntfs_cluster_to_bytes(vol, end_vcn - 1);
9049c879596SNamjae Jeon 		err = iomap_zero_range(vi, from, end_offset - from, NULL,
9059c879596SNamjae Jeon 				&ntfs_seek_iomap_ops,
9069c879596SNamjae Jeon 				&ntfs_iomap_folio_ops, NULL);
9079c879596SNamjae Jeon 		if (err < 0 || (end_vcn - start_vcn) == 1)
9089c879596SNamjae Jeon 			goto out;
9099c879596SNamjae Jeon 		end_vcn--;
9109c879596SNamjae Jeon 	}
9119c879596SNamjae Jeon 
9129c879596SNamjae Jeon 	mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL);
9139c879596SNamjae Jeon 	err = ntfs_non_resident_attr_punch_hole(ni, start_vcn,
9149c879596SNamjae Jeon 			end_vcn - start_vcn);
9159c879596SNamjae Jeon 	mutex_unlock(&ni->mrec_lock);
9169c879596SNamjae Jeon out:
9179c879596SNamjae Jeon 	return err;
9189c879596SNamjae Jeon }
9199c879596SNamjae Jeon 
9209c879596SNamjae Jeon static int ntfs_collapse_range(struct ntfs_inode *ni, loff_t offset, loff_t len)
9219c879596SNamjae Jeon {
9229c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
9239c879596SNamjae Jeon 	struct inode *vi = VFS_I(ni);
9249c879596SNamjae Jeon 	loff_t old_size, new_size;
9259c879596SNamjae Jeon 	s64 start_vcn, end_vcn;
9269c879596SNamjae Jeon 	int err;
9279c879596SNamjae Jeon 
9289c879596SNamjae Jeon 	loff_t offset_down = round_down(offset,
9299c879596SNamjae Jeon 			max_t(unsigned long, vol->cluster_size, PAGE_SIZE));
9309c879596SNamjae Jeon 
9319c879596SNamjae Jeon 	if ((offset & vol->cluster_size_mask) ||
9329c879596SNamjae Jeon 	    (len & vol->cluster_size_mask) ||
9339c879596SNamjae Jeon 	    offset >= ni->allocated_size) {
9349c879596SNamjae Jeon 		err = -EINVAL;
9359c879596SNamjae Jeon 		goto out;
9369c879596SNamjae Jeon 	}
9379c879596SNamjae Jeon 
9389c879596SNamjae Jeon 	old_size = i_size_read(vi);
9399c879596SNamjae Jeon 	start_vcn = ntfs_bytes_to_cluster(vol, offset);
9409c879596SNamjae Jeon 	end_vcn = ntfs_bytes_to_cluster(vol, offset + len - 1) + 1;
9419c879596SNamjae Jeon 
9429c879596SNamjae Jeon 	if (ntfs_cluster_to_bytes(vol, end_vcn) > ni->allocated_size)
9439c879596SNamjae Jeon 		end_vcn = (round_up(ni->allocated_size - 1,
9449c879596SNamjae Jeon 			   vol->cluster_size) >> vol->cluster_size_bits) + 1;
9459c879596SNamjae Jeon 	new_size = old_size - ntfs_cluster_to_bytes(vol, end_vcn - start_vcn);
9469c879596SNamjae Jeon 	if (new_size < 0)
9479c879596SNamjae Jeon 		new_size = 0;
9489c879596SNamjae Jeon 	err = filemap_write_and_wait_range(vi->i_mapping,
9499c879596SNamjae Jeon 			offset_down, LLONG_MAX);
9509c879596SNamjae Jeon 	if (err)
9519c879596SNamjae Jeon 		goto out;
9529c879596SNamjae Jeon 
9539c879596SNamjae Jeon 	truncate_pagecache(vi, offset_down);
9549c879596SNamjae Jeon 
9559c879596SNamjae Jeon 	mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL);
9569c879596SNamjae Jeon 	err = ntfs_non_resident_attr_collapse_range(ni, start_vcn,
9579c879596SNamjae Jeon 			end_vcn - start_vcn);
9589c879596SNamjae Jeon 	mutex_unlock(&ni->mrec_lock);
9599c879596SNamjae Jeon 
9609c879596SNamjae Jeon 	if (new_size != old_size)
9619c879596SNamjae Jeon 		i_size_write(vi, ni->data_size);
9629c879596SNamjae Jeon out:
9639c879596SNamjae Jeon 	return err;
9649c879596SNamjae Jeon }
9659c879596SNamjae Jeon 
9669c879596SNamjae Jeon static int ntfs_insert_range(struct ntfs_inode *ni, loff_t offset, loff_t len)
9679c879596SNamjae Jeon {
9689c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
9699c879596SNamjae Jeon 	struct inode *vi = VFS_I(ni);
9709c879596SNamjae Jeon 	loff_t offset_down = round_down(offset,
9719c879596SNamjae Jeon 			max_t(unsigned long, vol->cluster_size, PAGE_SIZE));
9729c879596SNamjae Jeon 	loff_t alloc_size, end_offset = offset + len;
9739c879596SNamjae Jeon 	loff_t old_size, new_size;
9749c879596SNamjae Jeon 	s64 start_vcn, end_vcn;
9759c879596SNamjae Jeon 	int err;
9769c879596SNamjae Jeon 
9779c879596SNamjae Jeon 	if (NVolDisableSparse(vol)) {
9789c879596SNamjae Jeon 		err = -EOPNOTSUPP;
9799c879596SNamjae Jeon 		goto out;
9809c879596SNamjae Jeon 	}
9819c879596SNamjae Jeon 
9829c879596SNamjae Jeon 	if ((offset & vol->cluster_size_mask) ||
9839c879596SNamjae Jeon 	    (len & vol->cluster_size_mask) ||
9849c879596SNamjae Jeon 	     offset >= ni->allocated_size) {
9859c879596SNamjae Jeon 		err = -EINVAL;
9869c879596SNamjae Jeon 		goto out;
9879c879596SNamjae Jeon 	}
9889c879596SNamjae Jeon 
9899c879596SNamjae Jeon 	old_size = i_size_read(vi);
9909c879596SNamjae Jeon 	start_vcn = ntfs_bytes_to_cluster(vol, offset);
9919c879596SNamjae Jeon 	end_vcn = ntfs_bytes_to_cluster(vol, end_offset - 1) + 1;
9929c879596SNamjae Jeon 
9939c879596SNamjae Jeon 	new_size = old_size + ntfs_cluster_to_bytes(vol, end_vcn - start_vcn);
9949c879596SNamjae Jeon 	alloc_size = ni->allocated_size +
9959c879596SNamjae Jeon 		ntfs_cluster_to_bytes(vol, end_vcn - start_vcn);
9969c879596SNamjae Jeon 	if (alloc_size < 0) {
9979c879596SNamjae Jeon 		err = -EFBIG;
9989c879596SNamjae Jeon 		goto out;
9999c879596SNamjae Jeon 	}
10009c879596SNamjae Jeon 	err = inode_newsize_ok(vi, alloc_size);
10019c879596SNamjae Jeon 	if (err)
10029c879596SNamjae Jeon 		goto out;
10039c879596SNamjae Jeon 
10049c879596SNamjae Jeon 	err = filemap_write_and_wait_range(vi->i_mapping,
10059c879596SNamjae Jeon 			offset_down, LLONG_MAX);
10069c879596SNamjae Jeon 	if (err)
10079c879596SNamjae Jeon 		goto out;
10089c879596SNamjae Jeon 
10099c879596SNamjae Jeon 	truncate_pagecache(vi, offset_down);
10109c879596SNamjae Jeon 
10119c879596SNamjae Jeon 	mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL);
10129c879596SNamjae Jeon 	err = ntfs_non_resident_attr_insert_range(ni, start_vcn,
10139c879596SNamjae Jeon 			end_vcn - start_vcn);
10149c879596SNamjae Jeon 	mutex_unlock(&ni->mrec_lock);
10159c879596SNamjae Jeon 
10169c879596SNamjae Jeon 	if (new_size != old_size)
10179c879596SNamjae Jeon 		i_size_write(vi, ni->data_size);
10189c879596SNamjae Jeon out:
10199c879596SNamjae Jeon 	return err;
10209c879596SNamjae Jeon }
10219c879596SNamjae Jeon 
10229c879596SNamjae Jeon #define NTFS_FALLOC_FL_SUPPORTED					\
10239c879596SNamjae Jeon 		(FALLOC_FL_ALLOCATE_RANGE | FALLOC_FL_KEEP_SIZE |	\
10249c879596SNamjae Jeon 		 FALLOC_FL_INSERT_RANGE | FALLOC_FL_PUNCH_HOLE |	\
10259c879596SNamjae Jeon 		 FALLOC_FL_COLLAPSE_RANGE)
10269c879596SNamjae Jeon 
10279c879596SNamjae Jeon static long ntfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
10289c879596SNamjae Jeon {
10299c879596SNamjae Jeon 	struct inode *vi = file_inode(file);
10309c879596SNamjae Jeon 	struct ntfs_inode *ni = NTFS_I(vi);
10319c879596SNamjae Jeon 	struct ntfs_volume *vol = ni->vol;
10329c879596SNamjae Jeon 	int err = 0;
10339c879596SNamjae Jeon 	loff_t old_size;
10349c879596SNamjae Jeon 	bool map_locked = false;
10359c879596SNamjae Jeon 
10369c879596SNamjae Jeon 	if (mode & ~(NTFS_FALLOC_FL_SUPPORTED))
10379c879596SNamjae Jeon 		return -EOPNOTSUPP;
10389c879596SNamjae Jeon 
10399c879596SNamjae Jeon 	if (!NVolFreeClusterKnown(vol))
10409c879596SNamjae Jeon 		wait_event(vol->free_waitq, NVolFreeClusterKnown(vol));
10419c879596SNamjae Jeon 
10429c879596SNamjae Jeon 	if ((ni->vol->mft_zone_end - ni->vol->mft_zone_start) == 0)
10439c879596SNamjae Jeon 		return -ENOSPC;
10449c879596SNamjae Jeon 
10459c879596SNamjae Jeon 	if (NInoNonResident(ni) && !NInoFullyMapped(ni)) {
10469c879596SNamjae Jeon 		down_write(&ni->runlist.lock);
10479c879596SNamjae Jeon 		err = ntfs_attr_map_whole_runlist(ni);
10489c879596SNamjae Jeon 		up_write(&ni->runlist.lock);
10499c879596SNamjae Jeon 		if (err)
10509c879596SNamjae Jeon 			return err;
10519c879596SNamjae Jeon 	}
10529c879596SNamjae Jeon 
10539c879596SNamjae Jeon 	if (!(vol->vol_flags & VOLUME_IS_DIRTY)) {
10549c879596SNamjae Jeon 		err = ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY);
10559c879596SNamjae Jeon 		if (err)
10569c879596SNamjae Jeon 			return err;
10579c879596SNamjae Jeon 	}
10589c879596SNamjae Jeon 
10599c879596SNamjae Jeon 	old_size = i_size_read(vi);
10609c879596SNamjae Jeon 
10619c879596SNamjae Jeon 	inode_lock(vi);
10629c879596SNamjae Jeon 	if (NInoCompressed(ni) || NInoEncrypted(ni)) {
10639c879596SNamjae Jeon 		err = -EOPNOTSUPP;
10649c879596SNamjae Jeon 		goto out;
10659c879596SNamjae Jeon 	}
10669c879596SNamjae Jeon 
10679c879596SNamjae Jeon 	inode_dio_wait(vi);
10689c879596SNamjae Jeon 	if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
10699c879596SNamjae Jeon 		    FALLOC_FL_INSERT_RANGE)) {
10709c879596SNamjae Jeon 		filemap_invalidate_lock(vi->i_mapping);
10719c879596SNamjae Jeon 		map_locked = true;
10729c879596SNamjae Jeon 	}
10739c879596SNamjae Jeon 
10749c879596SNamjae Jeon 	switch (mode & FALLOC_FL_MODE_MASK) {
10759c879596SNamjae Jeon 	case FALLOC_FL_ALLOCATE_RANGE:
10769c879596SNamjae Jeon 	case FALLOC_FL_KEEP_SIZE:
10779c879596SNamjae Jeon 		err = ntfs_allocate_range(ni, mode, offset, len);
10789c879596SNamjae Jeon 		break;
10799c879596SNamjae Jeon 	case FALLOC_FL_PUNCH_HOLE:
10809c879596SNamjae Jeon 		err = ntfs_punch_hole(ni, mode, offset, len);
10819c879596SNamjae Jeon 		break;
10829c879596SNamjae Jeon 	case FALLOC_FL_COLLAPSE_RANGE:
10839c879596SNamjae Jeon 		err = ntfs_collapse_range(ni, offset, len);
10849c879596SNamjae Jeon 		break;
10859c879596SNamjae Jeon 	case FALLOC_FL_INSERT_RANGE:
10869c879596SNamjae Jeon 		err = ntfs_insert_range(ni, offset, len);
10879c879596SNamjae Jeon 		break;
10889c879596SNamjae Jeon 	default:
10899c879596SNamjae Jeon 		err = -EOPNOTSUPP;
10909c879596SNamjae Jeon 	}
10919c879596SNamjae Jeon 
10929c879596SNamjae Jeon 	if (err)
10939c879596SNamjae Jeon 		goto out;
10949c879596SNamjae Jeon 
10959c879596SNamjae Jeon 	err = file_modified(file);
10969c879596SNamjae Jeon out:
10979c879596SNamjae Jeon 	if (map_locked)
10989c879596SNamjae Jeon 		filemap_invalidate_unlock(vi->i_mapping);
10999c879596SNamjae Jeon 	if (!err) {
11009c879596SNamjae Jeon 		if (mode == 0 && NInoNonResident(ni) &&
11019c879596SNamjae Jeon 		    offset > old_size && old_size % PAGE_SIZE != 0) {
11029c879596SNamjae Jeon 			loff_t len = min_t(loff_t,
11039c879596SNamjae Jeon 					   round_up(old_size, PAGE_SIZE) - old_size,
11049c879596SNamjae Jeon 					   offset - old_size);
11059c879596SNamjae Jeon 			err = iomap_zero_range(vi, old_size, len, NULL,
11069c879596SNamjae Jeon 					       &ntfs_seek_iomap_ops,
11079c879596SNamjae Jeon 					       &ntfs_iomap_folio_ops, NULL);
11089c879596SNamjae Jeon 		}
11099c879596SNamjae Jeon 		NInoSetFileNameDirty(ni);
11109c879596SNamjae Jeon 		inode_set_mtime_to_ts(vi, inode_set_ctime_current(vi));
11119c879596SNamjae Jeon 		mark_inode_dirty(vi);
11129c879596SNamjae Jeon 	}
11139c879596SNamjae Jeon 
11149c879596SNamjae Jeon 	inode_unlock(vi);
11159c879596SNamjae Jeon 	return err;
11169c879596SNamjae Jeon }
11171e9ea7e0SNamjae Jeon 
11181e9ea7e0SNamjae Jeon const struct file_operations ntfs_file_ops = {
11199c879596SNamjae Jeon 	.llseek		= ntfs_file_llseek,
11209c879596SNamjae Jeon 	.read_iter	= ntfs_file_read_iter,
11211e9ea7e0SNamjae Jeon 	.write_iter	= ntfs_file_write_iter,
11221e9ea7e0SNamjae Jeon 	.fsync		= ntfs_file_fsync,
11239c879596SNamjae Jeon 	.mmap_prepare	= ntfs_file_mmap_prepare,
11241e9ea7e0SNamjae Jeon 	.open		= ntfs_file_open,
11259c879596SNamjae Jeon 	.release	= ntfs_file_release,
11269c879596SNamjae Jeon 	.splice_read	= ntfs_file_splice_read,
11279c879596SNamjae Jeon 	.splice_write	= iter_file_splice_write,
11289c879596SNamjae Jeon 	.unlocked_ioctl	= ntfs_ioctl,
11299c879596SNamjae Jeon #ifdef CONFIG_COMPAT
11309c879596SNamjae Jeon 	.compat_ioctl	= ntfs_compat_ioctl,
11319c879596SNamjae Jeon #endif
11329c879596SNamjae Jeon 	.fallocate	= ntfs_fallocate,
11339c879596SNamjae Jeon 	.setlease	= generic_setlease,
11341e9ea7e0SNamjae Jeon };
11351e9ea7e0SNamjae Jeon 
11361e9ea7e0SNamjae Jeon const struct inode_operations ntfs_file_inode_ops = {
11371e9ea7e0SNamjae Jeon 	.setattr	= ntfs_setattr,
11389c879596SNamjae Jeon 	.getattr	= ntfs_getattr,
11399c879596SNamjae Jeon 	.listxattr	= ntfs_listxattr,
11409c879596SNamjae Jeon 	.get_acl	= ntfs_get_acl,
11419c879596SNamjae Jeon 	.set_acl	= ntfs_set_acl,
11429c879596SNamjae Jeon 	.fiemap		= ntfs_fiemap,
11439c879596SNamjae Jeon };
11449c879596SNamjae Jeon 
11459c879596SNamjae Jeon const struct inode_operations ntfs_symlink_inode_operations = {
11469c879596SNamjae Jeon 	.get_link	= ntfs_get_link,
11479c879596SNamjae Jeon 	.setattr	= ntfs_setattr,
11489c879596SNamjae Jeon 	.listxattr	= ntfs_listxattr,
11499c879596SNamjae Jeon };
11509c879596SNamjae Jeon 
11519c879596SNamjae Jeon const struct inode_operations ntfs_special_inode_operations = {
11529c879596SNamjae Jeon 	.setattr	= ntfs_setattr,
11539c879596SNamjae Jeon 	.getattr	= ntfs_getattr,
11549c879596SNamjae Jeon 	.listxattr	= ntfs_listxattr,
11559c879596SNamjae Jeon 	.get_acl	= ntfs_get_acl,
11569c879596SNamjae Jeon 	.set_acl	= ntfs_set_acl,
11571e9ea7e0SNamjae Jeon };
11581e9ea7e0SNamjae Jeon 
11591e9ea7e0SNamjae Jeon const struct file_operations ntfs_empty_file_ops = {};
11601e9ea7e0SNamjae Jeon 
11611e9ea7e0SNamjae Jeon const struct inode_operations ntfs_empty_inode_ops = {};
1162