14342306fSKonstantin Komarov // SPDX-License-Identifier: GPL-2.0 24342306fSKonstantin Komarov /* 34342306fSKonstantin Komarov * 44342306fSKonstantin Komarov * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 54342306fSKonstantin Komarov * 6e8b8e97fSKari Argillander * Regular file handling primitives for NTFS-based filesystems. 7e8b8e97fSKari Argillander * 84342306fSKonstantin Komarov */ 9e8b8e97fSKari Argillander 104342306fSKonstantin Komarov #include <linux/backing-dev.h> 11ccdf7741SChristoph Hellwig #include <linux/blkdev.h> 124342306fSKonstantin Komarov #include <linux/buffer_head.h> 134342306fSKonstantin Komarov #include <linux/compat.h> 144342306fSKonstantin Komarov #include <linux/falloc.h> 154342306fSKonstantin Komarov #include <linux/fiemap.h> 164342306fSKonstantin Komarov 174342306fSKonstantin Komarov #include "debug.h" 184342306fSKonstantin Komarov #include "ntfs.h" 194342306fSKonstantin Komarov #include "ntfs_fs.h" 204342306fSKonstantin Komarov 214342306fSKonstantin Komarov static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg) 224342306fSKonstantin Komarov { 234342306fSKonstantin Komarov struct fstrim_range __user *user_range; 244342306fSKonstantin Komarov struct fstrim_range range; 2596de65a9SKonstantin Komarov struct block_device *dev; 264342306fSKonstantin Komarov int err; 274342306fSKonstantin Komarov 284342306fSKonstantin Komarov if (!capable(CAP_SYS_ADMIN)) 294342306fSKonstantin Komarov return -EPERM; 304342306fSKonstantin Komarov 3196de65a9SKonstantin Komarov dev = sbi->sb->s_bdev; 3296de65a9SKonstantin Komarov if (!bdev_max_discard_sectors(dev)) 334342306fSKonstantin Komarov return -EOPNOTSUPP; 344342306fSKonstantin Komarov 354342306fSKonstantin Komarov user_range = (struct fstrim_range __user *)arg; 364342306fSKonstantin Komarov if (copy_from_user(&range, user_range, sizeof(range))) 374342306fSKonstantin Komarov return -EFAULT; 384342306fSKonstantin Komarov 3996de65a9SKonstantin Komarov range.minlen = max_t(u32, range.minlen, bdev_discard_granularity(dev)); 404342306fSKonstantin Komarov 414342306fSKonstantin Komarov err = ntfs_trim_fs(sbi, &range); 424342306fSKonstantin Komarov if (err < 0) 434342306fSKonstantin Komarov return err; 444342306fSKonstantin Komarov 454342306fSKonstantin Komarov if (copy_to_user(user_range, &range, sizeof(range))) 464342306fSKonstantin Komarov return -EFAULT; 474342306fSKonstantin Komarov 484342306fSKonstantin Komarov return 0; 494342306fSKonstantin Komarov } 504342306fSKonstantin Komarov 514342306fSKonstantin Komarov static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg) 524342306fSKonstantin Komarov { 534342306fSKonstantin Komarov struct inode *inode = file_inode(filp); 544342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 554342306fSKonstantin Komarov 564342306fSKonstantin Komarov switch (cmd) { 574342306fSKonstantin Komarov case FITRIM: 584342306fSKonstantin Komarov return ntfs_ioctl_fitrim(sbi, arg); 594342306fSKonstantin Komarov } 60e8b8e97fSKari Argillander return -ENOTTY; /* Inappropriate ioctl for device. */ 614342306fSKonstantin Komarov } 624342306fSKonstantin Komarov 634342306fSKonstantin Komarov #ifdef CONFIG_COMPAT 644342306fSKonstantin Komarov static long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg) 654342306fSKonstantin Komarov 664342306fSKonstantin Komarov { 674342306fSKonstantin Komarov return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); 684342306fSKonstantin Komarov } 694342306fSKonstantin Komarov #endif 704342306fSKonstantin Komarov 714342306fSKonstantin Komarov /* 72e8b8e97fSKari Argillander * ntfs_getattr - inode_operations::getattr 734342306fSKonstantin Komarov */ 74b74d24f7SChristian Brauner int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path, 754342306fSKonstantin Komarov struct kstat *stat, u32 request_mask, u32 flags) 764342306fSKonstantin Komarov { 774342306fSKonstantin Komarov struct inode *inode = d_inode(path->dentry); 784342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 794342306fSKonstantin Komarov 804342306fSKonstantin Komarov if (is_compressed(ni)) 814342306fSKonstantin Komarov stat->attributes |= STATX_ATTR_COMPRESSED; 824342306fSKonstantin Komarov 834342306fSKonstantin Komarov if (is_encrypted(ni)) 844342306fSKonstantin Komarov stat->attributes |= STATX_ATTR_ENCRYPTED; 854342306fSKonstantin Komarov 864342306fSKonstantin Komarov stat->attributes_mask |= STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED; 874342306fSKonstantin Komarov 880d72b928SJeff Layton generic_fillattr(idmap, request_mask, inode, stat); 894342306fSKonstantin Komarov 904342306fSKonstantin Komarov stat->result_mask |= STATX_BTIME; 914342306fSKonstantin Komarov stat->btime = ni->i_crtime; 924342306fSKonstantin Komarov stat->blksize = ni->mi.sbi->cluster_size; /* 512, 1K, ..., 2M */ 934342306fSKonstantin Komarov 944342306fSKonstantin Komarov return 0; 954342306fSKonstantin Komarov } 964342306fSKonstantin Komarov 974342306fSKonstantin Komarov static int ntfs_extend_initialized_size(struct file *file, 984342306fSKonstantin Komarov struct ntfs_inode *ni, 994342306fSKonstantin Komarov const loff_t valid, 1004342306fSKonstantin Komarov const loff_t new_valid) 1014342306fSKonstantin Komarov { 1024342306fSKonstantin Komarov struct inode *inode = &ni->vfs_inode; 1034342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 1044342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 1054342306fSKonstantin Komarov loff_t pos = valid; 1064342306fSKonstantin Komarov int err; 1074342306fSKonstantin Komarov 1084342306fSKonstantin Komarov if (is_resident(ni)) { 1094342306fSKonstantin Komarov ni->i_valid = new_valid; 1104342306fSKonstantin Komarov return 0; 1114342306fSKonstantin Komarov } 1124342306fSKonstantin Komarov 1134342306fSKonstantin Komarov WARN_ON(is_compressed(ni)); 1144342306fSKonstantin Komarov WARN_ON(valid >= new_valid); 1154342306fSKonstantin Komarov 1164342306fSKonstantin Komarov for (;;) { 1174342306fSKonstantin Komarov u32 zerofrom, len; 1184342306fSKonstantin Komarov struct page *page; 1194342306fSKonstantin Komarov u8 bits; 1204342306fSKonstantin Komarov CLST vcn, lcn, clen; 1214342306fSKonstantin Komarov 1224342306fSKonstantin Komarov if (is_sparsed(ni)) { 1234342306fSKonstantin Komarov bits = sbi->cluster_bits; 1244342306fSKonstantin Komarov vcn = pos >> bits; 1254342306fSKonstantin Komarov 126c380b52fSKonstantin Komarov err = attr_data_get_block(ni, vcn, 1, &lcn, &clen, NULL, 127c380b52fSKonstantin Komarov false); 1284342306fSKonstantin Komarov if (err) 1294342306fSKonstantin Komarov goto out; 1304342306fSKonstantin Komarov 1314342306fSKonstantin Komarov if (lcn == SPARSE_LCN) { 1322f56a3f8SKonstantin Komarov pos = ((loff_t)clen + vcn) << bits; 1332f56a3f8SKonstantin Komarov ni->i_valid = pos; 1344342306fSKonstantin Komarov goto next; 1354342306fSKonstantin Komarov } 1364342306fSKonstantin Komarov } 1374342306fSKonstantin Komarov 1384342306fSKonstantin Komarov zerofrom = pos & (PAGE_SIZE - 1); 1394342306fSKonstantin Komarov len = PAGE_SIZE - zerofrom; 1404342306fSKonstantin Komarov 1414342306fSKonstantin Komarov if (pos + len > new_valid) 1424342306fSKonstantin Komarov len = new_valid - pos; 1434342306fSKonstantin Komarov 144652118b8SMatthew Wilcox (Oracle) err = ntfs_write_begin(file, mapping, pos, len, &page, NULL); 1454342306fSKonstantin Komarov if (err) 1464342306fSKonstantin Komarov goto out; 1474342306fSKonstantin Komarov 1484342306fSKonstantin Komarov zero_user_segment(page, zerofrom, PAGE_SIZE); 1494342306fSKonstantin Komarov 150e8b8e97fSKari Argillander /* This function in any case puts page. */ 151652118b8SMatthew Wilcox (Oracle) err = ntfs_write_end(file, mapping, pos, len, len, page, NULL); 1524342306fSKonstantin Komarov if (err < 0) 1534342306fSKonstantin Komarov goto out; 1544342306fSKonstantin Komarov pos += len; 1554342306fSKonstantin Komarov 1564342306fSKonstantin Komarov next: 1574342306fSKonstantin Komarov if (pos >= new_valid) 1584342306fSKonstantin Komarov break; 1594342306fSKonstantin Komarov 1604342306fSKonstantin Komarov balance_dirty_pages_ratelimited(mapping); 1614342306fSKonstantin Komarov cond_resched(); 1624342306fSKonstantin Komarov } 1634342306fSKonstantin Komarov 1644342306fSKonstantin Komarov return 0; 1654342306fSKonstantin Komarov 1664342306fSKonstantin Komarov out: 1674342306fSKonstantin Komarov ni->i_valid = valid; 1684342306fSKonstantin Komarov ntfs_inode_warn(inode, "failed to extend initialized size to %llx.", 1694342306fSKonstantin Komarov new_valid); 1704342306fSKonstantin Komarov return err; 1714342306fSKonstantin Komarov } 1724342306fSKonstantin Komarov 1734342306fSKonstantin Komarov /* 174e8b8e97fSKari Argillander * ntfs_zero_range - Helper function for punch_hole. 175d3624466SKonstantin Komarov * 176d3624466SKonstantin Komarov * It zeroes a range [vbo, vbo_to). 1774342306fSKonstantin Komarov */ 1784342306fSKonstantin Komarov static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to) 1794342306fSKonstantin Komarov { 1804342306fSKonstantin Komarov int err = 0; 1814342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 182f39244e2SYangtao Li u32 blocksize = i_blocksize(inode); 1834342306fSKonstantin Komarov pgoff_t idx = vbo >> PAGE_SHIFT; 184c380b52fSKonstantin Komarov u32 from = vbo & (PAGE_SIZE - 1); 1854342306fSKonstantin Komarov pgoff_t idx_end = (vbo_to + PAGE_SIZE - 1) >> PAGE_SHIFT; 1864342306fSKonstantin Komarov loff_t page_off; 1874342306fSKonstantin Komarov struct buffer_head *head, *bh; 188c380b52fSKonstantin Komarov u32 bh_next, bh_off, to; 1894342306fSKonstantin Komarov sector_t iblock; 1904342306fSKonstantin Komarov struct page *page; 1914342306fSKonstantin Komarov 192c380b52fSKonstantin Komarov for (; idx < idx_end; idx += 1, from = 0) { 1934342306fSKonstantin Komarov page_off = (loff_t)idx << PAGE_SHIFT; 19496de65a9SKonstantin Komarov to = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off) : 19596de65a9SKonstantin Komarov PAGE_SIZE; 1964342306fSKonstantin Komarov iblock = page_off >> inode->i_blkbits; 1974342306fSKonstantin Komarov 1984342306fSKonstantin Komarov page = find_or_create_page(mapping, idx, 1994342306fSKonstantin Komarov mapping_gfp_constraint(mapping, 2004342306fSKonstantin Komarov ~__GFP_FS)); 2014342306fSKonstantin Komarov if (!page) 2024342306fSKonstantin Komarov return -ENOMEM; 2034342306fSKonstantin Komarov 2044342306fSKonstantin Komarov if (!page_has_buffers(page)) 2054342306fSKonstantin Komarov create_empty_buffers(page, blocksize, 0); 2064342306fSKonstantin Komarov 2074342306fSKonstantin Komarov bh = head = page_buffers(page); 2084342306fSKonstantin Komarov bh_off = 0; 2094342306fSKonstantin Komarov do { 2104342306fSKonstantin Komarov bh_next = bh_off + blocksize; 2114342306fSKonstantin Komarov 212c380b52fSKonstantin Komarov if (bh_next <= from || bh_off >= to) 2134342306fSKonstantin Komarov continue; 2144342306fSKonstantin Komarov 2154342306fSKonstantin Komarov if (!buffer_mapped(bh)) { 2164342306fSKonstantin Komarov ntfs_get_block(inode, iblock, bh, 0); 217d3624466SKonstantin Komarov /* Unmapped? It's a hole - nothing to do. */ 2184342306fSKonstantin Komarov if (!buffer_mapped(bh)) 2194342306fSKonstantin Komarov continue; 2204342306fSKonstantin Komarov } 2214342306fSKonstantin Komarov 222d3624466SKonstantin Komarov /* Ok, it's mapped. Make sure it's up-to-date. */ 2234342306fSKonstantin Komarov if (PageUptodate(page)) 2244342306fSKonstantin Komarov set_buffer_uptodate(bh); 2254342306fSKonstantin Komarov 2264342306fSKonstantin Komarov if (!buffer_uptodate(bh)) { 227c20bc9c6SKonstantin Komarov err = bh_read(bh, 0); 228c20bc9c6SKonstantin Komarov if (err < 0) { 2294342306fSKonstantin Komarov unlock_page(page); 2304342306fSKonstantin Komarov put_page(page); 2314342306fSKonstantin Komarov goto out; 2324342306fSKonstantin Komarov } 2334342306fSKonstantin Komarov } 2344342306fSKonstantin Komarov 2354342306fSKonstantin Komarov mark_buffer_dirty(bh); 2364342306fSKonstantin Komarov 2374342306fSKonstantin Komarov } while (bh_off = bh_next, iblock += 1, 2384342306fSKonstantin Komarov head != (bh = bh->b_this_page)); 2394342306fSKonstantin Komarov 240c380b52fSKonstantin Komarov zero_user_segment(page, from, to); 2414342306fSKonstantin Komarov 2424342306fSKonstantin Komarov unlock_page(page); 2434342306fSKonstantin Komarov put_page(page); 2444342306fSKonstantin Komarov cond_resched(); 2454342306fSKonstantin Komarov } 2464342306fSKonstantin Komarov out: 2474342306fSKonstantin Komarov mark_inode_dirty(inode); 2484342306fSKonstantin Komarov return err; 2494342306fSKonstantin Komarov } 2504342306fSKonstantin Komarov 2514342306fSKonstantin Komarov /* 252e8b8e97fSKari Argillander * ntfs_file_mmap - file_operations::mmap 2534342306fSKonstantin Komarov */ 2544342306fSKonstantin Komarov static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma) 2554342306fSKonstantin Komarov { 2564342306fSKonstantin Komarov struct address_space *mapping = file->f_mapping; 2574342306fSKonstantin Komarov struct inode *inode = mapping->host; 2584342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 2594342306fSKonstantin Komarov u64 from = ((u64)vma->vm_pgoff << PAGE_SHIFT); 2604342306fSKonstantin Komarov bool rw = vma->vm_flags & VM_WRITE; 2614342306fSKonstantin Komarov int err; 2624342306fSKonstantin Komarov 263f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 264f73f9397SKonstantin Komarov return -EIO; 265f73f9397SKonstantin Komarov 2664342306fSKonstantin Komarov if (is_encrypted(ni)) { 2674342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap encrypted not supported"); 2684342306fSKonstantin Komarov return -EOPNOTSUPP; 2694342306fSKonstantin Komarov } 2704342306fSKonstantin Komarov 2714342306fSKonstantin Komarov if (is_dedup(ni)) { 2724342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap deduplicated not supported"); 2734342306fSKonstantin Komarov return -EOPNOTSUPP; 2744342306fSKonstantin Komarov } 2754342306fSKonstantin Komarov 2764342306fSKonstantin Komarov if (is_compressed(ni) && rw) { 2774342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap(write) compressed not supported"); 2784342306fSKonstantin Komarov return -EOPNOTSUPP; 2794342306fSKonstantin Komarov } 2804342306fSKonstantin Komarov 2814342306fSKonstantin Komarov if (rw) { 2824342306fSKonstantin Komarov u64 to = min_t(loff_t, i_size_read(inode), 2834342306fSKonstantin Komarov from + vma->vm_end - vma->vm_start); 2844342306fSKonstantin Komarov 2854342306fSKonstantin Komarov if (is_sparsed(ni)) { 286e8b8e97fSKari Argillander /* Allocate clusters for rw map. */ 2874342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 2884342306fSKonstantin Komarov CLST lcn, len; 2894342306fSKonstantin Komarov CLST vcn = from >> sbi->cluster_bits; 2904342306fSKonstantin Komarov CLST end = bytes_to_cluster(sbi, to); 2914342306fSKonstantin Komarov bool new; 2924342306fSKonstantin Komarov 2934342306fSKonstantin Komarov for (; vcn < end; vcn += len) { 2944342306fSKonstantin Komarov err = attr_data_get_block(ni, vcn, 1, &lcn, 295c380b52fSKonstantin Komarov &len, &new, true); 2964342306fSKonstantin Komarov if (err) 2974342306fSKonstantin Komarov goto out; 2984342306fSKonstantin Komarov } 2994342306fSKonstantin Komarov } 3004342306fSKonstantin Komarov 3014342306fSKonstantin Komarov if (ni->i_valid < to) { 3024342306fSKonstantin Komarov if (!inode_trylock(inode)) { 3034342306fSKonstantin Komarov err = -EAGAIN; 3044342306fSKonstantin Komarov goto out; 3054342306fSKonstantin Komarov } 3064342306fSKonstantin Komarov err = ntfs_extend_initialized_size(file, ni, 3074342306fSKonstantin Komarov ni->i_valid, to); 3084342306fSKonstantin Komarov inode_unlock(inode); 3094342306fSKonstantin Komarov if (err) 3104342306fSKonstantin Komarov goto out; 3114342306fSKonstantin Komarov } 3124342306fSKonstantin Komarov } 3134342306fSKonstantin Komarov 3144342306fSKonstantin Komarov err = generic_file_mmap(file, vma); 3154342306fSKonstantin Komarov out: 3164342306fSKonstantin Komarov return err; 3174342306fSKonstantin Komarov } 3184342306fSKonstantin Komarov 3194342306fSKonstantin Komarov static int ntfs_extend(struct inode *inode, loff_t pos, size_t count, 3204342306fSKonstantin Komarov struct file *file) 3214342306fSKonstantin Komarov { 3224342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 3234342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 3244342306fSKonstantin Komarov loff_t end = pos + count; 3254342306fSKonstantin Komarov bool extend_init = file && pos > ni->i_valid; 3264342306fSKonstantin Komarov int err; 3274342306fSKonstantin Komarov 3284342306fSKonstantin Komarov if (end <= inode->i_size && !extend_init) 3294342306fSKonstantin Komarov return 0; 3304342306fSKonstantin Komarov 331e8b8e97fSKari Argillander /* Mark rw ntfs as dirty. It will be cleared at umount. */ 3324342306fSKonstantin Komarov ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY); 3334342306fSKonstantin Komarov 3344342306fSKonstantin Komarov if (end > inode->i_size) { 3354342306fSKonstantin Komarov err = ntfs_set_size(inode, end); 3364342306fSKonstantin Komarov if (err) 3374342306fSKonstantin Komarov goto out; 3384342306fSKonstantin Komarov } 3394342306fSKonstantin Komarov 3404342306fSKonstantin Komarov if (extend_init && !is_compressed(ni)) { 3414342306fSKonstantin Komarov err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos); 3424342306fSKonstantin Komarov if (err) 3434342306fSKonstantin Komarov goto out; 3444342306fSKonstantin Komarov } else { 3454342306fSKonstantin Komarov err = 0; 3464342306fSKonstantin Komarov } 3474342306fSKonstantin Komarov 3483d65c46fSJeff Layton inode->i_mtime = inode_set_ctime_current(inode); 3494342306fSKonstantin Komarov mark_inode_dirty(inode); 3504342306fSKonstantin Komarov 3514342306fSKonstantin Komarov if (IS_SYNC(inode)) { 3524342306fSKonstantin Komarov int err2; 3534342306fSKonstantin Komarov 3544342306fSKonstantin Komarov err = filemap_fdatawrite_range(mapping, pos, end - 1); 3554342306fSKonstantin Komarov err2 = sync_mapping_buffers(mapping); 3564342306fSKonstantin Komarov if (!err) 3574342306fSKonstantin Komarov err = err2; 3584342306fSKonstantin Komarov err2 = write_inode_now(inode, 1); 3594342306fSKonstantin Komarov if (!err) 3604342306fSKonstantin Komarov err = err2; 3614342306fSKonstantin Komarov if (!err) 3624342306fSKonstantin Komarov err = filemap_fdatawait_range(mapping, pos, end - 1); 3634342306fSKonstantin Komarov } 3644342306fSKonstantin Komarov 3654342306fSKonstantin Komarov out: 3664342306fSKonstantin Komarov return err; 3674342306fSKonstantin Komarov } 3684342306fSKonstantin Komarov 3694342306fSKonstantin Komarov static int ntfs_truncate(struct inode *inode, loff_t new_size) 3704342306fSKonstantin Komarov { 3714342306fSKonstantin Komarov struct super_block *sb = inode->i_sb; 3724342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 3734342306fSKonstantin Komarov int err, dirty = 0; 3744342306fSKonstantin Komarov u64 new_valid; 3754342306fSKonstantin Komarov 3764342306fSKonstantin Komarov if (!S_ISREG(inode->i_mode)) 3774342306fSKonstantin Komarov return 0; 3784342306fSKonstantin Komarov 3794342306fSKonstantin Komarov if (is_compressed(ni)) { 3804342306fSKonstantin Komarov if (ni->i_valid > new_size) 3814342306fSKonstantin Komarov ni->i_valid = new_size; 3824342306fSKonstantin Komarov } else { 3834342306fSKonstantin Komarov err = block_truncate_page(inode->i_mapping, new_size, 3844342306fSKonstantin Komarov ntfs_get_block); 3854342306fSKonstantin Komarov if (err) 3864342306fSKonstantin Komarov return err; 3874342306fSKonstantin Komarov } 3884342306fSKonstantin Komarov 3894342306fSKonstantin Komarov new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size)); 3904342306fSKonstantin Komarov 3914342306fSKonstantin Komarov truncate_setsize(inode, new_size); 3924342306fSKonstantin Komarov 3930226635cSTetsuo Handa ni_lock(ni); 3940226635cSTetsuo Handa 3954342306fSKonstantin Komarov down_write(&ni->file.run_lock); 3964342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, 397e95113edSKonstantin Komarov &new_valid, ni->mi.sbi->options->prealloc, NULL); 3984342306fSKonstantin Komarov up_write(&ni->file.run_lock); 3994342306fSKonstantin Komarov 4004342306fSKonstantin Komarov if (new_valid < ni->i_valid) 4014342306fSKonstantin Komarov ni->i_valid = new_valid; 4024342306fSKonstantin Komarov 4034342306fSKonstantin Komarov ni_unlock(ni); 4044342306fSKonstantin Komarov 4054342306fSKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE; 4063d65c46fSJeff Layton inode->i_mtime = inode_set_ctime_current(inode); 4074342306fSKonstantin Komarov if (!IS_DIRSYNC(inode)) { 4084342306fSKonstantin Komarov dirty = 1; 4094342306fSKonstantin Komarov } else { 4104342306fSKonstantin Komarov err = ntfs_sync_inode(inode); 4114342306fSKonstantin Komarov if (err) 4124342306fSKonstantin Komarov return err; 4134342306fSKonstantin Komarov } 4144342306fSKonstantin Komarov 4154342306fSKonstantin Komarov if (dirty) 4164342306fSKonstantin Komarov mark_inode_dirty(inode); 4174342306fSKonstantin Komarov 4184342306fSKonstantin Komarov /*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/ 4194342306fSKonstantin Komarov 4204342306fSKonstantin Komarov return 0; 4214342306fSKonstantin Komarov } 4224342306fSKonstantin Komarov 4234342306fSKonstantin Komarov /* 424e8b8e97fSKari Argillander * ntfs_fallocate 425e8b8e97fSKari Argillander * 4264342306fSKonstantin Komarov * Preallocate space for a file. This implements ntfs's fallocate file 4274342306fSKonstantin Komarov * operation, which gets called from sys_fallocate system call. User 4284342306fSKonstantin Komarov * space requests 'len' bytes at 'vbo'. If FALLOC_FL_KEEP_SIZE is set 4294342306fSKonstantin Komarov * we just allocate clusters without zeroing them out. Otherwise we 4304342306fSKonstantin Komarov * allocate and zero out clusters via an expanding truncate. 4314342306fSKonstantin Komarov */ 4324342306fSKonstantin Komarov static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) 4334342306fSKonstantin Komarov { 4344342306fSKonstantin Komarov struct inode *inode = file->f_mapping->host; 435e4d2f4fdSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 4364342306fSKonstantin Komarov struct super_block *sb = inode->i_sb; 4374342306fSKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 4384342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 4394342306fSKonstantin Komarov loff_t end = vbo + len; 440c380b52fSKonstantin Komarov loff_t vbo_down = round_down(vbo, max_t(unsigned long, 441c380b52fSKonstantin Komarov sbi->cluster_size, PAGE_SIZE)); 442e4d2f4fdSKonstantin Komarov bool is_supported_holes = is_sparsed(ni) || is_compressed(ni); 443e4d2f4fdSKonstantin Komarov loff_t i_size, new_size; 444e4d2f4fdSKonstantin Komarov bool map_locked; 4454342306fSKonstantin Komarov int err; 4464342306fSKonstantin Komarov 447e8b8e97fSKari Argillander /* No support for dir. */ 4484342306fSKonstantin Komarov if (!S_ISREG(inode->i_mode)) 4494342306fSKonstantin Komarov return -EOPNOTSUPP; 4504342306fSKonstantin Komarov 451e4d2f4fdSKonstantin Komarov /* 452e4d2f4fdSKonstantin Komarov * vfs_fallocate checks all possible combinations of mode. 453e4d2f4fdSKonstantin Komarov * Do additional checks here before ntfs_set_state(dirty). 454e4d2f4fdSKonstantin Komarov */ 455e4d2f4fdSKonstantin Komarov if (mode & FALLOC_FL_PUNCH_HOLE) { 456e4d2f4fdSKonstantin Komarov if (!is_supported_holes) 457e4d2f4fdSKonstantin Komarov return -EOPNOTSUPP; 458e4d2f4fdSKonstantin Komarov } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { 459e4d2f4fdSKonstantin Komarov } else if (mode & FALLOC_FL_INSERT_RANGE) { 460e4d2f4fdSKonstantin Komarov if (!is_supported_holes) 461e4d2f4fdSKonstantin Komarov return -EOPNOTSUPP; 462e4d2f4fdSKonstantin Komarov } else if (mode & 463e4d2f4fdSKonstantin Komarov ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | 464e4d2f4fdSKonstantin Komarov FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE)) { 4654342306fSKonstantin Komarov ntfs_inode_warn(inode, "fallocate(0x%x) is not supported", 4664342306fSKonstantin Komarov mode); 4674342306fSKonstantin Komarov return -EOPNOTSUPP; 4684342306fSKonstantin Komarov } 4694342306fSKonstantin Komarov 4704342306fSKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 4714342306fSKonstantin Komarov 4724342306fSKonstantin Komarov inode_lock(inode); 4734342306fSKonstantin Komarov i_size = inode->i_size; 474e4d2f4fdSKonstantin Komarov new_size = max(end, i_size); 475e4d2f4fdSKonstantin Komarov map_locked = false; 4764342306fSKonstantin Komarov 4774342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 478e8b8e97fSKari Argillander /* Should never be here, see ntfs_file_open. */ 4794342306fSKonstantin Komarov err = -EOPNOTSUPP; 4804342306fSKonstantin Komarov goto out; 4814342306fSKonstantin Komarov } 4824342306fSKonstantin Komarov 483e4d2f4fdSKonstantin Komarov if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | 484e4d2f4fdSKonstantin Komarov FALLOC_FL_INSERT_RANGE)) { 485e4d2f4fdSKonstantin Komarov inode_dio_wait(inode); 486e4d2f4fdSKonstantin Komarov filemap_invalidate_lock(mapping); 487e4d2f4fdSKonstantin Komarov map_locked = true; 488e4d2f4fdSKonstantin Komarov } 489e4d2f4fdSKonstantin Komarov 4904342306fSKonstantin Komarov if (mode & FALLOC_FL_PUNCH_HOLE) { 4914342306fSKonstantin Komarov u32 frame_size; 4924342306fSKonstantin Komarov loff_t mask, vbo_a, end_a, tmp; 4934342306fSKonstantin Komarov 494c380b52fSKonstantin Komarov err = filemap_write_and_wait_range(mapping, vbo_down, 495c380b52fSKonstantin Komarov LLONG_MAX); 4964342306fSKonstantin Komarov if (err) 4974342306fSKonstantin Komarov goto out; 4984342306fSKonstantin Komarov 4994342306fSKonstantin Komarov truncate_pagecache(inode, vbo_down); 5004342306fSKonstantin Komarov 5014342306fSKonstantin Komarov ni_lock(ni); 5024342306fSKonstantin Komarov err = attr_punch_hole(ni, vbo, len, &frame_size); 5034342306fSKonstantin Komarov ni_unlock(ni); 5047e0aff0aSKonstantin Komarov if (!err) 5057e0aff0aSKonstantin Komarov goto ok; 5067e0aff0aSKonstantin Komarov 5074342306fSKonstantin Komarov if (err != E_NTFS_NOTALIGNED) 5084342306fSKonstantin Komarov goto out; 5094342306fSKonstantin Komarov 510d3624466SKonstantin Komarov /* Process not aligned punch. */ 5117e0aff0aSKonstantin Komarov err = 0; 5124342306fSKonstantin Komarov mask = frame_size - 1; 5134342306fSKonstantin Komarov vbo_a = (vbo + mask) & ~mask; 5144342306fSKonstantin Komarov end_a = end & ~mask; 5154342306fSKonstantin Komarov 5164342306fSKonstantin Komarov tmp = min(vbo_a, end); 5174342306fSKonstantin Komarov if (tmp > vbo) { 5184342306fSKonstantin Komarov err = ntfs_zero_range(inode, vbo, tmp); 5194342306fSKonstantin Komarov if (err) 5204342306fSKonstantin Komarov goto out; 5214342306fSKonstantin Komarov } 5224342306fSKonstantin Komarov 5234342306fSKonstantin Komarov if (vbo < end_a && end_a < end) { 5244342306fSKonstantin Komarov err = ntfs_zero_range(inode, end_a, end); 5254342306fSKonstantin Komarov if (err) 5264342306fSKonstantin Komarov goto out; 5274342306fSKonstantin Komarov } 5284342306fSKonstantin Komarov 5294342306fSKonstantin Komarov /* Aligned punch_hole */ 5304342306fSKonstantin Komarov if (end_a > vbo_a) { 5314342306fSKonstantin Komarov ni_lock(ni); 5324342306fSKonstantin Komarov err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL); 5334342306fSKonstantin Komarov ni_unlock(ni); 5347e0aff0aSKonstantin Komarov if (err) 5357e0aff0aSKonstantin Komarov goto out; 5364342306fSKonstantin Komarov } 5374342306fSKonstantin Komarov } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { 5384342306fSKonstantin Komarov /* 5394342306fSKonstantin Komarov * Write tail of the last page before removed range since 5404342306fSKonstantin Komarov * it will get removed from the page cache below. 5414342306fSKonstantin Komarov */ 542e4d2f4fdSKonstantin Komarov err = filemap_write_and_wait_range(mapping, vbo_down, vbo); 5434342306fSKonstantin Komarov if (err) 5444342306fSKonstantin Komarov goto out; 5454342306fSKonstantin Komarov 5464342306fSKonstantin Komarov /* 5474342306fSKonstantin Komarov * Write data that will be shifted to preserve them 548e8b8e97fSKari Argillander * when discarding page cache below. 5494342306fSKonstantin Komarov */ 550e4d2f4fdSKonstantin Komarov err = filemap_write_and_wait_range(mapping, end, LLONG_MAX); 5514342306fSKonstantin Komarov if (err) 5524342306fSKonstantin Komarov goto out; 5534342306fSKonstantin Komarov 5544342306fSKonstantin Komarov truncate_pagecache(inode, vbo_down); 5554342306fSKonstantin Komarov 5564342306fSKonstantin Komarov ni_lock(ni); 5574342306fSKonstantin Komarov err = attr_collapse_range(ni, vbo, len); 5584342306fSKonstantin Komarov ni_unlock(ni); 559e4d2f4fdSKonstantin Komarov } else if (mode & FALLOC_FL_INSERT_RANGE) { 560e4d2f4fdSKonstantin Komarov /* Check new size. */ 56111434697SKonstantin Komarov err = inode_newsize_ok(inode, new_size); 56211434697SKonstantin Komarov if (err) 56311434697SKonstantin Komarov goto out; 56411434697SKonstantin Komarov 565e4d2f4fdSKonstantin Komarov /* Write out all dirty pages. */ 566e4d2f4fdSKonstantin Komarov err = filemap_write_and_wait_range(mapping, vbo_down, 567e4d2f4fdSKonstantin Komarov LLONG_MAX); 568e4d2f4fdSKonstantin Komarov if (err) 569e4d2f4fdSKonstantin Komarov goto out; 570e4d2f4fdSKonstantin Komarov truncate_pagecache(inode, vbo_down); 571e4d2f4fdSKonstantin Komarov 572e4d2f4fdSKonstantin Komarov ni_lock(ni); 573e4d2f4fdSKonstantin Komarov err = attr_insert_range(ni, vbo, len); 574e4d2f4fdSKonstantin Komarov ni_unlock(ni); 5757e0aff0aSKonstantin Komarov if (err) 5767e0aff0aSKonstantin Komarov goto out; 5774342306fSKonstantin Komarov } else { 578e4d2f4fdSKonstantin Komarov /* Check new size. */ 57996de65a9SKonstantin Komarov u8 cluster_bits = sbi->cluster_bits; 580b3e04872SKonstantin Komarov 581b3e04872SKonstantin Komarov /* generic/213: expected -ENOSPC instead of -EFBIG. */ 582b3e04872SKonstantin Komarov if (!is_supported_holes) { 583b3e04872SKonstantin Komarov loff_t to_alloc = new_size - inode_get_bytes(inode); 584b3e04872SKonstantin Komarov 585b3e04872SKonstantin Komarov if (to_alloc > 0 && 58696de65a9SKonstantin Komarov (to_alloc >> cluster_bits) > 587b3e04872SKonstantin Komarov wnd_zeroes(&sbi->used.bitmap)) { 588b3e04872SKonstantin Komarov err = -ENOSPC; 589b3e04872SKonstantin Komarov goto out; 590b3e04872SKonstantin Komarov } 591b3e04872SKonstantin Komarov } 59211434697SKonstantin Komarov 59311434697SKonstantin Komarov err = inode_newsize_ok(inode, new_size); 59411434697SKonstantin Komarov if (err) 59511434697SKonstantin Komarov goto out; 59611434697SKonstantin Komarov 597ad26a9c8SKonstantin Komarov if (new_size > i_size) { 598e4d2f4fdSKonstantin Komarov /* 599e4d2f4fdSKonstantin Komarov * Allocate clusters, do not change 'valid' size. 600e4d2f4fdSKonstantin Komarov */ 60111434697SKonstantin Komarov err = ntfs_set_size(inode, new_size); 6024342306fSKonstantin Komarov if (err) 6034342306fSKonstantin Komarov goto out; 604ad26a9c8SKonstantin Komarov } 6054342306fSKonstantin Komarov 606e4d2f4fdSKonstantin Komarov if (is_supported_holes) { 60796de65a9SKonstantin Komarov CLST vcn = vbo >> cluster_bits; 6084342306fSKonstantin Komarov CLST cend = bytes_to_cluster(sbi, end); 609c380b52fSKonstantin Komarov CLST cend_v = bytes_to_cluster(sbi, ni->i_valid); 6104342306fSKonstantin Komarov CLST lcn, clen; 6114342306fSKonstantin Komarov bool new; 6124342306fSKonstantin Komarov 613c380b52fSKonstantin Komarov if (cend_v > cend) 614c380b52fSKonstantin Komarov cend_v = cend; 615c380b52fSKonstantin Komarov 6164342306fSKonstantin Komarov /* 617c380b52fSKonstantin Komarov * Allocate and zero new clusters. 618e8b8e97fSKari Argillander * Zeroing these clusters may be too long. 619c380b52fSKonstantin Komarov */ 620c380b52fSKonstantin Komarov for (; vcn < cend_v; vcn += clen) { 621c380b52fSKonstantin Komarov err = attr_data_get_block(ni, vcn, cend_v - vcn, 622c380b52fSKonstantin Komarov &lcn, &clen, &new, 623c380b52fSKonstantin Komarov true); 624c380b52fSKonstantin Komarov if (err) 625c380b52fSKonstantin Komarov goto out; 626c380b52fSKonstantin Komarov } 627c380b52fSKonstantin Komarov /* 628c380b52fSKonstantin Komarov * Allocate but not zero new clusters. 6294342306fSKonstantin Komarov */ 6304342306fSKonstantin Komarov for (; vcn < cend; vcn += clen) { 6314342306fSKonstantin Komarov err = attr_data_get_block(ni, vcn, cend - vcn, 632c380b52fSKonstantin Komarov &lcn, &clen, &new, 633c380b52fSKonstantin Komarov false); 6344342306fSKonstantin Komarov if (err) 6354342306fSKonstantin Komarov goto out; 6364342306fSKonstantin Komarov } 6374342306fSKonstantin Komarov } 6384342306fSKonstantin Komarov 6394342306fSKonstantin Komarov if (mode & FALLOC_FL_KEEP_SIZE) { 6404342306fSKonstantin Komarov ni_lock(ni); 641e8b8e97fSKari Argillander /* True - Keep preallocated. */ 6424342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, 6434342306fSKonstantin Komarov &ni->file.run, i_size, &ni->i_valid, 6444342306fSKonstantin Komarov true, NULL); 6454342306fSKonstantin Komarov ni_unlock(ni); 646c28efa87SKonstantin Komarov if (err) 647c28efa87SKonstantin Komarov goto out; 648ad26a9c8SKonstantin Komarov } else if (new_size > i_size) { 649f4cf29c6SKonstantin Komarov i_size_write(inode, new_size); 6504342306fSKonstantin Komarov } 6514342306fSKonstantin Komarov } 6524342306fSKonstantin Komarov 6537e0aff0aSKonstantin Komarov ok: 654c28efa87SKonstantin Komarov err = file_modified(file); 655c28efa87SKonstantin Komarov if (err) 656c28efa87SKonstantin Komarov goto out; 657c28efa87SKonstantin Komarov 6584342306fSKonstantin Komarov out: 659e4d2f4fdSKonstantin Komarov if (map_locked) 660e4d2f4fdSKonstantin Komarov filemap_invalidate_unlock(mapping); 6614342306fSKonstantin Komarov 6624342306fSKonstantin Komarov if (!err) { 6633d65c46fSJeff Layton inode->i_mtime = inode_set_ctime_current(inode); 6644342306fSKonstantin Komarov mark_inode_dirty(inode); 6654342306fSKonstantin Komarov } 6664342306fSKonstantin Komarov 6674342306fSKonstantin Komarov inode_unlock(inode); 6684342306fSKonstantin Komarov return err; 6694342306fSKonstantin Komarov } 6704342306fSKonstantin Komarov 6714342306fSKonstantin Komarov /* 672e8b8e97fSKari Argillander * ntfs3_setattr - inode_operations::setattr 6734342306fSKonstantin Komarov */ 674c1632a0fSChristian Brauner int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 6754342306fSKonstantin Komarov struct iattr *attr) 6764342306fSKonstantin Komarov { 6774342306fSKonstantin Komarov struct inode *inode = d_inode(dentry); 6784342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 6794342306fSKonstantin Komarov u32 ia_valid = attr->ia_valid; 6804342306fSKonstantin Komarov umode_t mode = inode->i_mode; 6814342306fSKonstantin Komarov int err; 6824342306fSKonstantin Komarov 683f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 684f73f9397SKonstantin Komarov return -EIO; 685f73f9397SKonstantin Komarov 686c1632a0fSChristian Brauner err = setattr_prepare(idmap, dentry, attr); 6874342306fSKonstantin Komarov if (err) 6884342306fSKonstantin Komarov goto out; 6894342306fSKonstantin Komarov 6904342306fSKonstantin Komarov if (ia_valid & ATTR_SIZE) { 691ad26a9c8SKonstantin Komarov loff_t newsize, oldsize; 6924342306fSKonstantin Komarov 6934342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 694e8b8e97fSKari Argillander /* Should never be here, see ntfs_file_open(). */ 6954342306fSKonstantin Komarov err = -EOPNOTSUPP; 6964342306fSKonstantin Komarov goto out; 6974342306fSKonstantin Komarov } 6984342306fSKonstantin Komarov inode_dio_wait(inode); 699f4cf29c6SKonstantin Komarov oldsize = i_size_read(inode); 700ad26a9c8SKonstantin Komarov newsize = attr->ia_size; 7014342306fSKonstantin Komarov 702ad26a9c8SKonstantin Komarov if (newsize <= oldsize) 703ad26a9c8SKonstantin Komarov err = ntfs_truncate(inode, newsize); 704ad26a9c8SKonstantin Komarov else 705ad26a9c8SKonstantin Komarov err = ntfs_extend(inode, newsize, 0, NULL); 7064342306fSKonstantin Komarov 7074342306fSKonstantin Komarov if (err) 7084342306fSKonstantin Komarov goto out; 7094342306fSKonstantin Komarov 7104342306fSKonstantin Komarov ni->ni_flags |= NI_FLAG_UPDATE_PARENT; 711f4cf29c6SKonstantin Komarov i_size_write(inode, newsize); 7124342306fSKonstantin Komarov } 7134342306fSKonstantin Komarov 714c1632a0fSChristian Brauner setattr_copy(idmap, inode, attr); 7154342306fSKonstantin Komarov 7164342306fSKonstantin Komarov if (mode != inode->i_mode) { 71713e83a49SChristian Brauner err = ntfs_acl_chmod(idmap, dentry); 7184342306fSKonstantin Komarov if (err) 7194342306fSKonstantin Komarov goto out; 7204342306fSKonstantin Komarov 721e8b8e97fSKari Argillander /* Linux 'w' -> Windows 'ro'. */ 7224342306fSKonstantin Komarov if (0222 & inode->i_mode) 7234342306fSKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_READONLY; 7244342306fSKonstantin Komarov else 7254342306fSKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_READONLY; 7264342306fSKonstantin Komarov } 7274342306fSKonstantin Komarov 7284342306fSKonstantin Komarov if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) 7291842fbc8SKonstantin Komarov ntfs_save_wsl_perm(inode, NULL); 7304342306fSKonstantin Komarov mark_inode_dirty(inode); 7314342306fSKonstantin Komarov out: 7324342306fSKonstantin Komarov return err; 7334342306fSKonstantin Komarov } 7344342306fSKonstantin Komarov 7354342306fSKonstantin Komarov static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 7364342306fSKonstantin Komarov { 7374342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 7384342306fSKonstantin Komarov struct inode *inode = file->f_mapping->host; 7394342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 7404342306fSKonstantin Komarov 741f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 742f73f9397SKonstantin Komarov return -EIO; 743f73f9397SKonstantin Komarov 7444342306fSKonstantin Komarov if (is_encrypted(ni)) { 7454342306fSKonstantin Komarov ntfs_inode_warn(inode, "encrypted i/o not supported"); 7464342306fSKonstantin Komarov return -EOPNOTSUPP; 7474342306fSKonstantin Komarov } 7484342306fSKonstantin Komarov 7494342306fSKonstantin Komarov if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 7504342306fSKonstantin Komarov ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 7514342306fSKonstantin Komarov return -EOPNOTSUPP; 7524342306fSKonstantin Komarov } 7534342306fSKonstantin Komarov 7544342306fSKonstantin Komarov #ifndef CONFIG_NTFS3_LZX_XPRESS 7554342306fSKonstantin Komarov if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 7564342306fSKonstantin Komarov ntfs_inode_warn( 7574342306fSKonstantin Komarov inode, 7584342306fSKonstantin Komarov "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 7594342306fSKonstantin Komarov return -EOPNOTSUPP; 7604342306fSKonstantin Komarov } 7614342306fSKonstantin Komarov #endif 7624342306fSKonstantin Komarov 7634342306fSKonstantin Komarov if (is_dedup(ni)) { 7644342306fSKonstantin Komarov ntfs_inode_warn(inode, "read deduplicated not supported"); 7654342306fSKonstantin Komarov return -EOPNOTSUPP; 7664342306fSKonstantin Komarov } 7674342306fSKonstantin Komarov 768dd854e4bSKari Argillander return generic_file_read_iter(iocb, iter); 7694342306fSKonstantin Komarov } 7704342306fSKonstantin Komarov 77151494398SDavid Howells static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos, 772f684073cSKonstantin Komarov struct pipe_inode_info *pipe, size_t len, 773f684073cSKonstantin Komarov unsigned int flags) 77451494398SDavid Howells { 77551494398SDavid Howells struct inode *inode = in->f_mapping->host; 77651494398SDavid Howells struct ntfs_inode *ni = ntfs_i(inode); 77751494398SDavid Howells 778f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 779f73f9397SKonstantin Komarov return -EIO; 780f73f9397SKonstantin Komarov 78151494398SDavid Howells if (is_encrypted(ni)) { 78251494398SDavid Howells ntfs_inode_warn(inode, "encrypted i/o not supported"); 78351494398SDavid Howells return -EOPNOTSUPP; 78451494398SDavid Howells } 78551494398SDavid Howells 78651494398SDavid Howells #ifndef CONFIG_NTFS3_LZX_XPRESS 78751494398SDavid Howells if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 78851494398SDavid Howells ntfs_inode_warn( 78951494398SDavid Howells inode, 79051494398SDavid Howells "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 79151494398SDavid Howells return -EOPNOTSUPP; 79251494398SDavid Howells } 79351494398SDavid Howells #endif 79451494398SDavid Howells 79551494398SDavid Howells if (is_dedup(ni)) { 79651494398SDavid Howells ntfs_inode_warn(inode, "read deduplicated not supported"); 79751494398SDavid Howells return -EOPNOTSUPP; 79851494398SDavid Howells } 79951494398SDavid Howells 8002cb1e089SDavid Howells return filemap_splice_read(in, ppos, pipe, len, flags); 80151494398SDavid Howells } 80251494398SDavid Howells 803e8b8e97fSKari Argillander /* 804e8b8e97fSKari Argillander * ntfs_get_frame_pages 805e8b8e97fSKari Argillander * 806e8b8e97fSKari Argillander * Return: Array of locked pages. 807e8b8e97fSKari Argillander */ 8084342306fSKonstantin Komarov static int ntfs_get_frame_pages(struct address_space *mapping, pgoff_t index, 8094342306fSKonstantin Komarov struct page **pages, u32 pages_per_frame, 8104342306fSKonstantin Komarov bool *frame_uptodate) 8114342306fSKonstantin Komarov { 8124342306fSKonstantin Komarov gfp_t gfp_mask = mapping_gfp_mask(mapping); 8134342306fSKonstantin Komarov u32 npages; 8144342306fSKonstantin Komarov 8154342306fSKonstantin Komarov *frame_uptodate = true; 8164342306fSKonstantin Komarov 8174342306fSKonstantin Komarov for (npages = 0; npages < pages_per_frame; npages++, index++) { 8184342306fSKonstantin Komarov struct page *page; 8194342306fSKonstantin Komarov 8204342306fSKonstantin Komarov page = find_or_create_page(mapping, index, gfp_mask); 8214342306fSKonstantin Komarov if (!page) { 8224342306fSKonstantin Komarov while (npages--) { 8234342306fSKonstantin Komarov page = pages[npages]; 8244342306fSKonstantin Komarov unlock_page(page); 8254342306fSKonstantin Komarov put_page(page); 8264342306fSKonstantin Komarov } 8274342306fSKonstantin Komarov 8284342306fSKonstantin Komarov return -ENOMEM; 8294342306fSKonstantin Komarov } 8304342306fSKonstantin Komarov 8314342306fSKonstantin Komarov if (!PageUptodate(page)) 8324342306fSKonstantin Komarov *frame_uptodate = false; 8334342306fSKonstantin Komarov 8344342306fSKonstantin Komarov pages[npages] = page; 8354342306fSKonstantin Komarov } 8364342306fSKonstantin Komarov 8374342306fSKonstantin Komarov return 0; 8384342306fSKonstantin Komarov } 8394342306fSKonstantin Komarov 840e8b8e97fSKari Argillander /* 841e8b8e97fSKari Argillander * ntfs_compress_write - Helper for ntfs_file_write_iter() (compressed files). 842e8b8e97fSKari Argillander */ 8434342306fSKonstantin Komarov static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) 8444342306fSKonstantin Komarov { 8454342306fSKonstantin Komarov int err; 8464342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 8474342306fSKonstantin Komarov size_t count = iov_iter_count(from); 8484342306fSKonstantin Komarov loff_t pos = iocb->ki_pos; 8494342306fSKonstantin Komarov struct inode *inode = file_inode(file); 850f4cf29c6SKonstantin Komarov loff_t i_size = i_size_read(inode); 8514342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 8524342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 8534342306fSKonstantin Komarov u64 valid = ni->i_valid; 8544342306fSKonstantin Komarov struct ntfs_sb_info *sbi = ni->mi.sbi; 8554342306fSKonstantin Komarov struct page *page, **pages = NULL; 8564342306fSKonstantin Komarov size_t written = 0; 8574342306fSKonstantin Komarov u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits; 8584342306fSKonstantin Komarov u32 frame_size = 1u << frame_bits; 8594342306fSKonstantin Komarov u32 pages_per_frame = frame_size >> PAGE_SHIFT; 8604342306fSKonstantin Komarov u32 ip, off; 8614342306fSKonstantin Komarov CLST frame; 8624342306fSKonstantin Komarov u64 frame_vbo; 8634342306fSKonstantin Komarov pgoff_t index; 8644342306fSKonstantin Komarov bool frame_uptodate; 8654342306fSKonstantin Komarov 8664342306fSKonstantin Komarov if (frame_size < PAGE_SIZE) { 8674342306fSKonstantin Komarov /* 8684342306fSKonstantin Komarov * frame_size == 8K if cluster 512 8694342306fSKonstantin Komarov * frame_size == 64K if cluster 4096 8704342306fSKonstantin Komarov */ 8714342306fSKonstantin Komarov ntfs_inode_warn(inode, "page size is bigger than frame size"); 8724342306fSKonstantin Komarov return -EOPNOTSUPP; 8734342306fSKonstantin Komarov } 8744342306fSKonstantin Komarov 875345482bcSKari Argillander pages = kmalloc_array(pages_per_frame, sizeof(struct page *), GFP_NOFS); 8764342306fSKonstantin Komarov if (!pages) 8774342306fSKonstantin Komarov return -ENOMEM; 8784342306fSKonstantin Komarov 8794342306fSKonstantin Komarov err = file_remove_privs(file); 8804342306fSKonstantin Komarov if (err) 8814342306fSKonstantin Komarov goto out; 8824342306fSKonstantin Komarov 8834342306fSKonstantin Komarov err = file_update_time(file); 8844342306fSKonstantin Komarov if (err) 8854342306fSKonstantin Komarov goto out; 8864342306fSKonstantin Komarov 887e8b8e97fSKari Argillander /* Zero range [valid : pos). */ 8884342306fSKonstantin Komarov while (valid < pos) { 8894342306fSKonstantin Komarov CLST lcn, clen; 8904342306fSKonstantin Komarov 8914342306fSKonstantin Komarov frame = valid >> frame_bits; 8924342306fSKonstantin Komarov frame_vbo = valid & ~(frame_size - 1); 8934342306fSKonstantin Komarov off = valid & (frame_size - 1); 8944342306fSKonstantin Komarov 895c380b52fSKonstantin Komarov err = attr_data_get_block(ni, frame << NTFS_LZNT_CUNIT, 1, &lcn, 896c380b52fSKonstantin Komarov &clen, NULL, false); 8974342306fSKonstantin Komarov if (err) 8984342306fSKonstantin Komarov goto out; 8994342306fSKonstantin Komarov 9004342306fSKonstantin Komarov if (lcn == SPARSE_LCN) { 9014342306fSKonstantin Komarov ni->i_valid = valid = 9024342306fSKonstantin Komarov frame_vbo + ((u64)clen << sbi->cluster_bits); 9034342306fSKonstantin Komarov continue; 9044342306fSKonstantin Komarov } 9054342306fSKonstantin Komarov 906e8b8e97fSKari Argillander /* Load full frame. */ 9074342306fSKonstantin Komarov err = ntfs_get_frame_pages(mapping, frame_vbo >> PAGE_SHIFT, 9084342306fSKonstantin Komarov pages, pages_per_frame, 9094342306fSKonstantin Komarov &frame_uptodate); 9104342306fSKonstantin Komarov if (err) 9114342306fSKonstantin Komarov goto out; 9124342306fSKonstantin Komarov 9134342306fSKonstantin Komarov if (!frame_uptodate && off) { 9144342306fSKonstantin Komarov err = ni_read_frame(ni, frame_vbo, pages, 9154342306fSKonstantin Komarov pages_per_frame); 9164342306fSKonstantin Komarov if (err) { 9174342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 9184342306fSKonstantin Komarov page = pages[ip]; 9194342306fSKonstantin Komarov unlock_page(page); 9204342306fSKonstantin Komarov put_page(page); 9214342306fSKonstantin Komarov } 9224342306fSKonstantin Komarov goto out; 9234342306fSKonstantin Komarov } 9244342306fSKonstantin Komarov } 9254342306fSKonstantin Komarov 9264342306fSKonstantin Komarov ip = off >> PAGE_SHIFT; 9274342306fSKonstantin Komarov off = offset_in_page(valid); 9284342306fSKonstantin Komarov for (; ip < pages_per_frame; ip++, off = 0) { 9294342306fSKonstantin Komarov page = pages[ip]; 9304342306fSKonstantin Komarov zero_user_segment(page, off, PAGE_SIZE); 9314342306fSKonstantin Komarov flush_dcache_page(page); 9324342306fSKonstantin Komarov SetPageUptodate(page); 9334342306fSKonstantin Komarov } 9344342306fSKonstantin Komarov 9354342306fSKonstantin Komarov ni_lock(ni); 9364342306fSKonstantin Komarov err = ni_write_frame(ni, pages, pages_per_frame); 9374342306fSKonstantin Komarov ni_unlock(ni); 9384342306fSKonstantin Komarov 9394342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 9404342306fSKonstantin Komarov page = pages[ip]; 9414342306fSKonstantin Komarov SetPageUptodate(page); 9424342306fSKonstantin Komarov unlock_page(page); 9434342306fSKonstantin Komarov put_page(page); 9444342306fSKonstantin Komarov } 9454342306fSKonstantin Komarov 9464342306fSKonstantin Komarov if (err) 9474342306fSKonstantin Komarov goto out; 9484342306fSKonstantin Komarov 9494342306fSKonstantin Komarov ni->i_valid = valid = frame_vbo + frame_size; 9504342306fSKonstantin Komarov } 9514342306fSKonstantin Komarov 952e8b8e97fSKari Argillander /* Copy user data [pos : pos + count). */ 9534342306fSKonstantin Komarov while (count) { 9544342306fSKonstantin Komarov size_t copied, bytes; 9554342306fSKonstantin Komarov 9564342306fSKonstantin Komarov off = pos & (frame_size - 1); 9574342306fSKonstantin Komarov bytes = frame_size - off; 9584342306fSKonstantin Komarov if (bytes > count) 9594342306fSKonstantin Komarov bytes = count; 9604342306fSKonstantin Komarov 9614342306fSKonstantin Komarov frame_vbo = pos & ~(frame_size - 1); 9624342306fSKonstantin Komarov index = frame_vbo >> PAGE_SHIFT; 9634342306fSKonstantin Komarov 964a6294593SAndreas Gruenbacher if (unlikely(fault_in_iov_iter_readable(from, bytes))) { 9654342306fSKonstantin Komarov err = -EFAULT; 9664342306fSKonstantin Komarov goto out; 9674342306fSKonstantin Komarov } 9684342306fSKonstantin Komarov 969e8b8e97fSKari Argillander /* Load full frame. */ 9704342306fSKonstantin Komarov err = ntfs_get_frame_pages(mapping, index, pages, 9714342306fSKonstantin Komarov pages_per_frame, &frame_uptodate); 9724342306fSKonstantin Komarov if (err) 9734342306fSKonstantin Komarov goto out; 9744342306fSKonstantin Komarov 9754342306fSKonstantin Komarov if (!frame_uptodate) { 9764342306fSKonstantin Komarov loff_t to = pos + bytes; 9774342306fSKonstantin Komarov 9784342306fSKonstantin Komarov if (off || (to < i_size && (to & (frame_size - 1)))) { 9794342306fSKonstantin Komarov err = ni_read_frame(ni, frame_vbo, pages, 9804342306fSKonstantin Komarov pages_per_frame); 9814342306fSKonstantin Komarov if (err) { 9824342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; 9834342306fSKonstantin Komarov ip++) { 9844342306fSKonstantin Komarov page = pages[ip]; 9854342306fSKonstantin Komarov unlock_page(page); 9864342306fSKonstantin Komarov put_page(page); 9874342306fSKonstantin Komarov } 9884342306fSKonstantin Komarov goto out; 9894342306fSKonstantin Komarov } 9904342306fSKonstantin Komarov } 9914342306fSKonstantin Komarov } 9924342306fSKonstantin Komarov 9934342306fSKonstantin Komarov WARN_ON(!bytes); 9944342306fSKonstantin Komarov copied = 0; 9954342306fSKonstantin Komarov ip = off >> PAGE_SHIFT; 9964342306fSKonstantin Komarov off = offset_in_page(pos); 9974342306fSKonstantin Komarov 998e8b8e97fSKari Argillander /* Copy user data to pages. */ 9994342306fSKonstantin Komarov for (;;) { 10004342306fSKonstantin Komarov size_t cp, tail = PAGE_SIZE - off; 10014342306fSKonstantin Komarov 10024342306fSKonstantin Komarov page = pages[ip]; 10034342306fSKonstantin Komarov cp = copy_page_from_iter_atomic(page, off, 10044342306fSKonstantin Komarov min(tail, bytes), from); 10054342306fSKonstantin Komarov flush_dcache_page(page); 10064342306fSKonstantin Komarov 10074342306fSKonstantin Komarov copied += cp; 10084342306fSKonstantin Komarov bytes -= cp; 10094342306fSKonstantin Komarov if (!bytes || !cp) 10104342306fSKonstantin Komarov break; 10114342306fSKonstantin Komarov 10124342306fSKonstantin Komarov if (cp < tail) { 10134342306fSKonstantin Komarov off += cp; 10144342306fSKonstantin Komarov } else { 10154342306fSKonstantin Komarov ip++; 10164342306fSKonstantin Komarov off = 0; 10174342306fSKonstantin Komarov } 10184342306fSKonstantin Komarov } 10194342306fSKonstantin Komarov 10204342306fSKonstantin Komarov ni_lock(ni); 10214342306fSKonstantin Komarov err = ni_write_frame(ni, pages, pages_per_frame); 10224342306fSKonstantin Komarov ni_unlock(ni); 10234342306fSKonstantin Komarov 10244342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 10254342306fSKonstantin Komarov page = pages[ip]; 10264342306fSKonstantin Komarov ClearPageDirty(page); 10274342306fSKonstantin Komarov SetPageUptodate(page); 10284342306fSKonstantin Komarov unlock_page(page); 10294342306fSKonstantin Komarov put_page(page); 10304342306fSKonstantin Komarov } 10314342306fSKonstantin Komarov 10324342306fSKonstantin Komarov if (err) 10334342306fSKonstantin Komarov goto out; 10344342306fSKonstantin Komarov 10354342306fSKonstantin Komarov /* 10364342306fSKonstantin Komarov * We can loop for a long time in here. Be nice and allow 10374342306fSKonstantin Komarov * us to schedule out to avoid softlocking if preempt 10384342306fSKonstantin Komarov * is disabled. 10394342306fSKonstantin Komarov */ 10404342306fSKonstantin Komarov cond_resched(); 10414342306fSKonstantin Komarov 10424342306fSKonstantin Komarov pos += copied; 10434342306fSKonstantin Komarov written += copied; 10444342306fSKonstantin Komarov 10454342306fSKonstantin Komarov count = iov_iter_count(from); 10464342306fSKonstantin Komarov } 10474342306fSKonstantin Komarov 10484342306fSKonstantin Komarov out: 1049195c52bdSKari Argillander kfree(pages); 10504342306fSKonstantin Komarov 10514342306fSKonstantin Komarov if (err < 0) 10524342306fSKonstantin Komarov return err; 10534342306fSKonstantin Komarov 10544342306fSKonstantin Komarov iocb->ki_pos += written; 10554342306fSKonstantin Komarov if (iocb->ki_pos > ni->i_valid) 10564342306fSKonstantin Komarov ni->i_valid = iocb->ki_pos; 1057*ded8bf5bSKonstantin Komarov if (iocb->ki_pos > i_size) 1058*ded8bf5bSKonstantin Komarov i_size_write(inode, iocb->ki_pos); 10594342306fSKonstantin Komarov 10604342306fSKonstantin Komarov return written; 10614342306fSKonstantin Komarov } 10624342306fSKonstantin Komarov 10634342306fSKonstantin Komarov /* 1064e8b8e97fSKari Argillander * ntfs_file_write_iter - file_operations::write_iter 10654342306fSKonstantin Komarov */ 10664342306fSKonstantin Komarov static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 10674342306fSKonstantin Komarov { 10684342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 10694342306fSKonstantin Komarov struct address_space *mapping = file->f_mapping; 10704342306fSKonstantin Komarov struct inode *inode = mapping->host; 10714342306fSKonstantin Komarov ssize_t ret; 1072c28efa87SKonstantin Komarov int err; 10734342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 10744342306fSKonstantin Komarov 1075f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 1076f73f9397SKonstantin Komarov return -EIO; 1077f73f9397SKonstantin Komarov 10784342306fSKonstantin Komarov if (is_encrypted(ni)) { 10794342306fSKonstantin Komarov ntfs_inode_warn(inode, "encrypted i/o not supported"); 10804342306fSKonstantin Komarov return -EOPNOTSUPP; 10814342306fSKonstantin Komarov } 10824342306fSKonstantin Komarov 10834342306fSKonstantin Komarov if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 10844342306fSKonstantin Komarov ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 10854342306fSKonstantin Komarov return -EOPNOTSUPP; 10864342306fSKonstantin Komarov } 10874342306fSKonstantin Komarov 10884342306fSKonstantin Komarov if (is_dedup(ni)) { 10894342306fSKonstantin Komarov ntfs_inode_warn(inode, "write into deduplicated not supported"); 10904342306fSKonstantin Komarov return -EOPNOTSUPP; 10914342306fSKonstantin Komarov } 10924342306fSKonstantin Komarov 10934342306fSKonstantin Komarov if (!inode_trylock(inode)) { 10944342306fSKonstantin Komarov if (iocb->ki_flags & IOCB_NOWAIT) 10954342306fSKonstantin Komarov return -EAGAIN; 10964342306fSKonstantin Komarov inode_lock(inode); 10974342306fSKonstantin Komarov } 10984342306fSKonstantin Komarov 10994342306fSKonstantin Komarov ret = generic_write_checks(iocb, from); 11004342306fSKonstantin Komarov if (ret <= 0) 11014342306fSKonstantin Komarov goto out; 11024342306fSKonstantin Komarov 1103c28efa87SKonstantin Komarov err = file_modified(iocb->ki_filp); 1104c28efa87SKonstantin Komarov if (err) { 1105c28efa87SKonstantin Komarov ret = err; 1106c28efa87SKonstantin Komarov goto out; 1107c28efa87SKonstantin Komarov } 1108c28efa87SKonstantin Komarov 11094342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 1110d3624466SKonstantin Komarov /* Should never be here, see ntfs_file_open(). */ 11114342306fSKonstantin Komarov ret = -EOPNOTSUPP; 11124342306fSKonstantin Komarov goto out; 11134342306fSKonstantin Komarov } 11144342306fSKonstantin Komarov 11154342306fSKonstantin Komarov ret = ntfs_extend(inode, iocb->ki_pos, ret, file); 11164342306fSKonstantin Komarov if (ret) 11174342306fSKonstantin Komarov goto out; 11184342306fSKonstantin Komarov 111996de65a9SKonstantin Komarov ret = is_compressed(ni) ? ntfs_compress_write(iocb, from) : 112096de65a9SKonstantin Komarov __generic_file_write_iter(iocb, from); 11214342306fSKonstantin Komarov 11224342306fSKonstantin Komarov out: 11234342306fSKonstantin Komarov inode_unlock(inode); 11244342306fSKonstantin Komarov 11254342306fSKonstantin Komarov if (ret > 0) 11264342306fSKonstantin Komarov ret = generic_write_sync(iocb, ret); 11274342306fSKonstantin Komarov 11284342306fSKonstantin Komarov return ret; 11294342306fSKonstantin Komarov } 11304342306fSKonstantin Komarov 11314342306fSKonstantin Komarov /* 1132e8b8e97fSKari Argillander * ntfs_file_open - file_operations::open 11334342306fSKonstantin Komarov */ 11344342306fSKonstantin Komarov int ntfs_file_open(struct inode *inode, struct file *file) 11354342306fSKonstantin Komarov { 11364342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11374342306fSKonstantin Komarov 1138f73f9397SKonstantin Komarov if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) 1139f73f9397SKonstantin Komarov return -EIO; 1140f73f9397SKonstantin Komarov 11414342306fSKonstantin Komarov if (unlikely((is_compressed(ni) || is_encrypted(ni)) && 11424342306fSKonstantin Komarov (file->f_flags & O_DIRECT))) { 11434342306fSKonstantin Komarov return -EOPNOTSUPP; 11444342306fSKonstantin Komarov } 11454342306fSKonstantin Komarov 1146e8b8e97fSKari Argillander /* Decompress "external compressed" file if opened for rw. */ 11474342306fSKonstantin Komarov if ((ni->ni_flags & NI_FLAG_COMPRESSED_MASK) && 11484342306fSKonstantin Komarov (file->f_flags & (O_WRONLY | O_RDWR | O_TRUNC))) { 11494342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS 11504342306fSKonstantin Komarov int err = ni_decompress_file(ni); 11514342306fSKonstantin Komarov 11524342306fSKonstantin Komarov if (err) 11534342306fSKonstantin Komarov return err; 11544342306fSKonstantin Komarov #else 11554342306fSKonstantin Komarov ntfs_inode_warn( 11564342306fSKonstantin Komarov inode, 11574342306fSKonstantin Komarov "activate CONFIG_NTFS3_LZX_XPRESS to write external compressed files"); 11584342306fSKonstantin Komarov return -EOPNOTSUPP; 11594342306fSKonstantin Komarov #endif 11604342306fSKonstantin Komarov } 11614342306fSKonstantin Komarov 11624342306fSKonstantin Komarov return generic_file_open(inode, file); 11634342306fSKonstantin Komarov } 11644342306fSKonstantin Komarov 11654342306fSKonstantin Komarov /* 1166e8b8e97fSKari Argillander * ntfs_file_release - file_operations::release 11674342306fSKonstantin Komarov */ 11684342306fSKonstantin Komarov static int ntfs_file_release(struct inode *inode, struct file *file) 11694342306fSKonstantin Komarov { 11704342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11714342306fSKonstantin Komarov struct ntfs_sb_info *sbi = ni->mi.sbi; 11724342306fSKonstantin Komarov int err = 0; 11734342306fSKonstantin Komarov 1174e8b8e97fSKari Argillander /* If we are last writer on the inode, drop the block reservation. */ 117596de65a9SKonstantin Komarov if (sbi->options->prealloc && 117696de65a9SKonstantin Komarov ((file->f_mode & FMODE_WRITE) && 11774342306fSKonstantin Komarov atomic_read(&inode->i_writecount) == 1)) { 11784342306fSKonstantin Komarov ni_lock(ni); 11794342306fSKonstantin Komarov down_write(&ni->file.run_lock); 11804342306fSKonstantin Komarov 11814342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, 1182f4cf29c6SKonstantin Komarov i_size_read(inode), &ni->i_valid, false, 1183f4cf29c6SKonstantin Komarov NULL); 11844342306fSKonstantin Komarov 11854342306fSKonstantin Komarov up_write(&ni->file.run_lock); 11864342306fSKonstantin Komarov ni_unlock(ni); 11874342306fSKonstantin Komarov } 11884342306fSKonstantin Komarov return err; 11894342306fSKonstantin Komarov } 11904342306fSKonstantin Komarov 1191e8b8e97fSKari Argillander /* 1192e8b8e97fSKari Argillander * ntfs_fiemap - file_operations::fiemap 1193e8b8e97fSKari Argillander */ 11944342306fSKonstantin Komarov int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 11954342306fSKonstantin Komarov __u64 start, __u64 len) 11964342306fSKonstantin Komarov { 11974342306fSKonstantin Komarov int err; 11984342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11994342306fSKonstantin Komarov 1200d4e8e135SKari Argillander err = fiemap_prep(inode, fieinfo, start, &len, ~FIEMAP_FLAG_XATTR); 1201d4e8e135SKari Argillander if (err) 1202d4e8e135SKari Argillander return err; 12034342306fSKonstantin Komarov 12044342306fSKonstantin Komarov ni_lock(ni); 12054342306fSKonstantin Komarov 12064342306fSKonstantin Komarov err = ni_fiemap(ni, fieinfo, start, len); 12074342306fSKonstantin Komarov 12084342306fSKonstantin Komarov ni_unlock(ni); 12094342306fSKonstantin Komarov 12104342306fSKonstantin Komarov return err; 12114342306fSKonstantin Komarov } 12124342306fSKonstantin Komarov 12134342306fSKonstantin Komarov // clang-format off 12144342306fSKonstantin Komarov const struct inode_operations ntfs_file_inode_operations = { 12154342306fSKonstantin Komarov .getattr = ntfs_getattr, 12164342306fSKonstantin Komarov .setattr = ntfs3_setattr, 12174342306fSKonstantin Komarov .listxattr = ntfs_listxattr, 121875c5e0c9SKonstantin Komarov .get_acl = ntfs_get_acl, 12194342306fSKonstantin Komarov .set_acl = ntfs_set_acl, 12204342306fSKonstantin Komarov .fiemap = ntfs_fiemap, 12214342306fSKonstantin Komarov }; 12224342306fSKonstantin Komarov 12234342306fSKonstantin Komarov const struct file_operations ntfs_file_operations = { 12244342306fSKonstantin Komarov .llseek = generic_file_llseek, 12254342306fSKonstantin Komarov .read_iter = ntfs_file_read_iter, 12264342306fSKonstantin Komarov .write_iter = ntfs_file_write_iter, 12274342306fSKonstantin Komarov .unlocked_ioctl = ntfs_ioctl, 12284342306fSKonstantin Komarov #ifdef CONFIG_COMPAT 12294342306fSKonstantin Komarov .compat_ioctl = ntfs_compat_ioctl, 12304342306fSKonstantin Komarov #endif 123151494398SDavid Howells .splice_read = ntfs_file_splice_read, 12324342306fSKonstantin Komarov .mmap = ntfs_file_mmap, 12334342306fSKonstantin Komarov .open = ntfs_file_open, 12344342306fSKonstantin Komarov .fsync = generic_file_fsync, 12354342306fSKonstantin Komarov .splice_write = iter_file_splice_write, 12364342306fSKonstantin Komarov .fallocate = ntfs_fallocate, 12374342306fSKonstantin Komarov .release = ntfs_file_release, 12384342306fSKonstantin Komarov }; 12394342306fSKonstantin Komarov // clang-format on 1240