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 * 64342306fSKonstantin Komarov * regular file handling primitives for ntfs-based filesystems 74342306fSKonstantin Komarov */ 84342306fSKonstantin Komarov #include <linux/backing-dev.h> 94342306fSKonstantin Komarov #include <linux/buffer_head.h> 104342306fSKonstantin Komarov #include <linux/compat.h> 114342306fSKonstantin Komarov #include <linux/falloc.h> 124342306fSKonstantin Komarov #include <linux/fiemap.h> 134342306fSKonstantin Komarov #include <linux/msdos_fs.h> /* FAT_IOCTL_XXX */ 144342306fSKonstantin Komarov #include <linux/nls.h> 154342306fSKonstantin Komarov 164342306fSKonstantin Komarov #include "debug.h" 174342306fSKonstantin Komarov #include "ntfs.h" 184342306fSKonstantin Komarov #include "ntfs_fs.h" 194342306fSKonstantin Komarov 204342306fSKonstantin Komarov static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg) 214342306fSKonstantin Komarov { 224342306fSKonstantin Komarov struct fstrim_range __user *user_range; 234342306fSKonstantin Komarov struct fstrim_range range; 244342306fSKonstantin Komarov struct request_queue *q = bdev_get_queue(sbi->sb->s_bdev); 254342306fSKonstantin Komarov int err; 264342306fSKonstantin Komarov 274342306fSKonstantin Komarov if (!capable(CAP_SYS_ADMIN)) 284342306fSKonstantin Komarov return -EPERM; 294342306fSKonstantin Komarov 304342306fSKonstantin Komarov if (!blk_queue_discard(q)) 314342306fSKonstantin Komarov return -EOPNOTSUPP; 324342306fSKonstantin Komarov 334342306fSKonstantin Komarov user_range = (struct fstrim_range __user *)arg; 344342306fSKonstantin Komarov if (copy_from_user(&range, user_range, sizeof(range))) 354342306fSKonstantin Komarov return -EFAULT; 364342306fSKonstantin Komarov 374342306fSKonstantin Komarov range.minlen = max_t(u32, range.minlen, q->limits.discard_granularity); 384342306fSKonstantin Komarov 394342306fSKonstantin Komarov err = ntfs_trim_fs(sbi, &range); 404342306fSKonstantin Komarov if (err < 0) 414342306fSKonstantin Komarov return err; 424342306fSKonstantin Komarov 434342306fSKonstantin Komarov if (copy_to_user(user_range, &range, sizeof(range))) 444342306fSKonstantin Komarov return -EFAULT; 454342306fSKonstantin Komarov 464342306fSKonstantin Komarov return 0; 474342306fSKonstantin Komarov } 484342306fSKonstantin Komarov 494342306fSKonstantin Komarov static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg) 504342306fSKonstantin Komarov { 514342306fSKonstantin Komarov struct inode *inode = file_inode(filp); 524342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 534342306fSKonstantin Komarov u32 __user *user_attr = (u32 __user *)arg; 544342306fSKonstantin Komarov 554342306fSKonstantin Komarov switch (cmd) { 564342306fSKonstantin Komarov case FAT_IOCTL_GET_ATTRIBUTES: 574342306fSKonstantin Komarov return put_user(le32_to_cpu(ntfs_i(inode)->std_fa), user_attr); 584342306fSKonstantin Komarov 594342306fSKonstantin Komarov case FAT_IOCTL_GET_VOLUME_ID: 604342306fSKonstantin Komarov return put_user(sbi->volume.ser_num, user_attr); 614342306fSKonstantin Komarov 624342306fSKonstantin Komarov case FITRIM: 634342306fSKonstantin Komarov return ntfs_ioctl_fitrim(sbi, arg); 644342306fSKonstantin Komarov } 654342306fSKonstantin Komarov return -ENOTTY; /* Inappropriate ioctl for device */ 664342306fSKonstantin Komarov } 674342306fSKonstantin Komarov 684342306fSKonstantin Komarov #ifdef CONFIG_COMPAT 694342306fSKonstantin Komarov static long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg) 704342306fSKonstantin Komarov 714342306fSKonstantin Komarov { 724342306fSKonstantin Komarov return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); 734342306fSKonstantin Komarov } 744342306fSKonstantin Komarov #endif 754342306fSKonstantin Komarov 764342306fSKonstantin Komarov /* 774342306fSKonstantin Komarov * inode_operations::getattr 784342306fSKonstantin Komarov */ 794342306fSKonstantin Komarov int ntfs_getattr(struct user_namespace *mnt_userns, const struct path *path, 804342306fSKonstantin Komarov struct kstat *stat, u32 request_mask, u32 flags) 814342306fSKonstantin Komarov { 824342306fSKonstantin Komarov struct inode *inode = d_inode(path->dentry); 834342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 844342306fSKonstantin Komarov 854342306fSKonstantin Komarov if (is_compressed(ni)) 864342306fSKonstantin Komarov stat->attributes |= STATX_ATTR_COMPRESSED; 874342306fSKonstantin Komarov 884342306fSKonstantin Komarov if (is_encrypted(ni)) 894342306fSKonstantin Komarov stat->attributes |= STATX_ATTR_ENCRYPTED; 904342306fSKonstantin Komarov 914342306fSKonstantin Komarov stat->attributes_mask |= STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED; 924342306fSKonstantin Komarov 934342306fSKonstantin Komarov generic_fillattr(mnt_userns, inode, stat); 944342306fSKonstantin Komarov 954342306fSKonstantin Komarov stat->result_mask |= STATX_BTIME; 964342306fSKonstantin Komarov stat->btime = ni->i_crtime; 974342306fSKonstantin Komarov stat->blksize = ni->mi.sbi->cluster_size; /* 512, 1K, ..., 2M */ 984342306fSKonstantin Komarov 994342306fSKonstantin Komarov return 0; 1004342306fSKonstantin Komarov } 1014342306fSKonstantin Komarov 1024342306fSKonstantin Komarov static int ntfs_extend_initialized_size(struct file *file, 1034342306fSKonstantin Komarov struct ntfs_inode *ni, 1044342306fSKonstantin Komarov const loff_t valid, 1054342306fSKonstantin Komarov const loff_t new_valid) 1064342306fSKonstantin Komarov { 1074342306fSKonstantin Komarov struct inode *inode = &ni->vfs_inode; 1084342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 1094342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 1104342306fSKonstantin Komarov loff_t pos = valid; 1114342306fSKonstantin Komarov int err; 1124342306fSKonstantin Komarov 1134342306fSKonstantin Komarov if (is_resident(ni)) { 1144342306fSKonstantin Komarov ni->i_valid = new_valid; 1154342306fSKonstantin Komarov return 0; 1164342306fSKonstantin Komarov } 1174342306fSKonstantin Komarov 1184342306fSKonstantin Komarov WARN_ON(is_compressed(ni)); 1194342306fSKonstantin Komarov WARN_ON(valid >= new_valid); 1204342306fSKonstantin Komarov 1214342306fSKonstantin Komarov for (;;) { 1224342306fSKonstantin Komarov u32 zerofrom, len; 1234342306fSKonstantin Komarov struct page *page; 1244342306fSKonstantin Komarov void *fsdata; 1254342306fSKonstantin Komarov u8 bits; 1264342306fSKonstantin Komarov CLST vcn, lcn, clen; 1274342306fSKonstantin Komarov 1284342306fSKonstantin Komarov if (is_sparsed(ni)) { 1294342306fSKonstantin Komarov bits = sbi->cluster_bits; 1304342306fSKonstantin Komarov vcn = pos >> bits; 1314342306fSKonstantin Komarov 1324342306fSKonstantin Komarov err = attr_data_get_block(ni, vcn, 0, &lcn, &clen, 1334342306fSKonstantin Komarov NULL); 1344342306fSKonstantin Komarov if (err) 1354342306fSKonstantin Komarov goto out; 1364342306fSKonstantin Komarov 1374342306fSKonstantin Komarov if (lcn == SPARSE_LCN) { 1384342306fSKonstantin Komarov loff_t vbo = (loff_t)vcn << bits; 1394342306fSKonstantin Komarov loff_t to = vbo + ((loff_t)clen << bits); 1404342306fSKonstantin Komarov 1414342306fSKonstantin Komarov if (to <= new_valid) { 1424342306fSKonstantin Komarov ni->i_valid = to; 1434342306fSKonstantin Komarov pos = to; 1444342306fSKonstantin Komarov goto next; 1454342306fSKonstantin Komarov } 1464342306fSKonstantin Komarov 1474342306fSKonstantin Komarov if (vbo < pos) { 1484342306fSKonstantin Komarov pos = vbo; 1494342306fSKonstantin Komarov } else { 1504342306fSKonstantin Komarov to = (new_valid >> bits) << bits; 1514342306fSKonstantin Komarov if (pos < to) { 1524342306fSKonstantin Komarov ni->i_valid = to; 1534342306fSKonstantin Komarov pos = to; 1544342306fSKonstantin Komarov goto next; 1554342306fSKonstantin Komarov } 1564342306fSKonstantin Komarov } 1574342306fSKonstantin Komarov } 1584342306fSKonstantin Komarov } 1594342306fSKonstantin Komarov 1604342306fSKonstantin Komarov zerofrom = pos & (PAGE_SIZE - 1); 1614342306fSKonstantin Komarov len = PAGE_SIZE - zerofrom; 1624342306fSKonstantin Komarov 1634342306fSKonstantin Komarov if (pos + len > new_valid) 1644342306fSKonstantin Komarov len = new_valid - pos; 1654342306fSKonstantin Komarov 1664342306fSKonstantin Komarov err = pagecache_write_begin(file, mapping, pos, len, 0, &page, 1674342306fSKonstantin Komarov &fsdata); 1684342306fSKonstantin Komarov if (err) 1694342306fSKonstantin Komarov goto out; 1704342306fSKonstantin Komarov 1714342306fSKonstantin Komarov zero_user_segment(page, zerofrom, PAGE_SIZE); 1724342306fSKonstantin Komarov 1734342306fSKonstantin Komarov /* this function in any case puts page*/ 1744342306fSKonstantin Komarov err = pagecache_write_end(file, mapping, pos, len, len, page, 1754342306fSKonstantin Komarov fsdata); 1764342306fSKonstantin Komarov if (err < 0) 1774342306fSKonstantin Komarov goto out; 1784342306fSKonstantin Komarov pos += len; 1794342306fSKonstantin Komarov 1804342306fSKonstantin Komarov next: 1814342306fSKonstantin Komarov if (pos >= new_valid) 1824342306fSKonstantin Komarov break; 1834342306fSKonstantin Komarov 1844342306fSKonstantin Komarov balance_dirty_pages_ratelimited(mapping); 1854342306fSKonstantin Komarov cond_resched(); 1864342306fSKonstantin Komarov } 1874342306fSKonstantin Komarov 1884342306fSKonstantin Komarov return 0; 1894342306fSKonstantin Komarov 1904342306fSKonstantin Komarov out: 1914342306fSKonstantin Komarov ni->i_valid = valid; 1924342306fSKonstantin Komarov ntfs_inode_warn(inode, "failed to extend initialized size to %llx.", 1934342306fSKonstantin Komarov new_valid); 1944342306fSKonstantin Komarov return err; 1954342306fSKonstantin Komarov } 1964342306fSKonstantin Komarov 1974342306fSKonstantin Komarov /* 1984342306fSKonstantin Komarov * ntfs_zero_range 1994342306fSKonstantin Komarov * 2004342306fSKonstantin Komarov * Helper function for punch_hole. 2014342306fSKonstantin Komarov * It zeroes a range [vbo, vbo_to) 2024342306fSKonstantin Komarov */ 2034342306fSKonstantin Komarov static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to) 2044342306fSKonstantin Komarov { 2054342306fSKonstantin Komarov int err = 0; 2064342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 2074342306fSKonstantin Komarov u32 blocksize = 1 << inode->i_blkbits; 2084342306fSKonstantin Komarov pgoff_t idx = vbo >> PAGE_SHIFT; 2094342306fSKonstantin Komarov u32 z_start = vbo & (PAGE_SIZE - 1); 2104342306fSKonstantin Komarov pgoff_t idx_end = (vbo_to + PAGE_SIZE - 1) >> PAGE_SHIFT; 2114342306fSKonstantin Komarov loff_t page_off; 2124342306fSKonstantin Komarov struct buffer_head *head, *bh; 2134342306fSKonstantin Komarov u32 bh_next, bh_off, z_end; 2144342306fSKonstantin Komarov sector_t iblock; 2154342306fSKonstantin Komarov struct page *page; 2164342306fSKonstantin Komarov 2174342306fSKonstantin Komarov for (; idx < idx_end; idx += 1, z_start = 0) { 2184342306fSKonstantin Komarov page_off = (loff_t)idx << PAGE_SHIFT; 2194342306fSKonstantin Komarov z_end = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off) 2204342306fSKonstantin Komarov : PAGE_SIZE; 2214342306fSKonstantin Komarov iblock = page_off >> inode->i_blkbits; 2224342306fSKonstantin Komarov 2234342306fSKonstantin Komarov page = find_or_create_page(mapping, idx, 2244342306fSKonstantin Komarov mapping_gfp_constraint(mapping, 2254342306fSKonstantin Komarov ~__GFP_FS)); 2264342306fSKonstantin Komarov if (!page) 2274342306fSKonstantin Komarov return -ENOMEM; 2284342306fSKonstantin Komarov 2294342306fSKonstantin Komarov if (!page_has_buffers(page)) 2304342306fSKonstantin Komarov create_empty_buffers(page, blocksize, 0); 2314342306fSKonstantin Komarov 2324342306fSKonstantin Komarov bh = head = page_buffers(page); 2334342306fSKonstantin Komarov bh_off = 0; 2344342306fSKonstantin Komarov do { 2354342306fSKonstantin Komarov bh_next = bh_off + blocksize; 2364342306fSKonstantin Komarov 2374342306fSKonstantin Komarov if (bh_next <= z_start || bh_off >= z_end) 2384342306fSKonstantin Komarov continue; 2394342306fSKonstantin Komarov 2404342306fSKonstantin Komarov if (!buffer_mapped(bh)) { 2414342306fSKonstantin Komarov ntfs_get_block(inode, iblock, bh, 0); 2424342306fSKonstantin Komarov /* unmapped? It's a hole - nothing to do */ 2434342306fSKonstantin Komarov if (!buffer_mapped(bh)) 2444342306fSKonstantin Komarov continue; 2454342306fSKonstantin Komarov } 2464342306fSKonstantin Komarov 2474342306fSKonstantin Komarov /* Ok, it's mapped. Make sure it's up-to-date */ 2484342306fSKonstantin Komarov if (PageUptodate(page)) 2494342306fSKonstantin Komarov set_buffer_uptodate(bh); 2504342306fSKonstantin Komarov 2514342306fSKonstantin Komarov if (!buffer_uptodate(bh)) { 2524342306fSKonstantin Komarov lock_buffer(bh); 2534342306fSKonstantin Komarov bh->b_end_io = end_buffer_read_sync; 2544342306fSKonstantin Komarov get_bh(bh); 2554342306fSKonstantin Komarov submit_bh(REQ_OP_READ, 0, bh); 2564342306fSKonstantin Komarov 2574342306fSKonstantin Komarov wait_on_buffer(bh); 2584342306fSKonstantin Komarov if (!buffer_uptodate(bh)) { 2594342306fSKonstantin Komarov unlock_page(page); 2604342306fSKonstantin Komarov put_page(page); 2614342306fSKonstantin Komarov err = -EIO; 2624342306fSKonstantin Komarov goto out; 2634342306fSKonstantin Komarov } 2644342306fSKonstantin Komarov } 2654342306fSKonstantin Komarov 2664342306fSKonstantin Komarov mark_buffer_dirty(bh); 2674342306fSKonstantin Komarov 2684342306fSKonstantin Komarov } while (bh_off = bh_next, iblock += 1, 2694342306fSKonstantin Komarov head != (bh = bh->b_this_page)); 2704342306fSKonstantin Komarov 2714342306fSKonstantin Komarov zero_user_segment(page, z_start, z_end); 2724342306fSKonstantin Komarov 2734342306fSKonstantin Komarov unlock_page(page); 2744342306fSKonstantin Komarov put_page(page); 2754342306fSKonstantin Komarov cond_resched(); 2764342306fSKonstantin Komarov } 2774342306fSKonstantin Komarov out: 2784342306fSKonstantin Komarov mark_inode_dirty(inode); 2794342306fSKonstantin Komarov return err; 2804342306fSKonstantin Komarov } 2814342306fSKonstantin Komarov 2824342306fSKonstantin Komarov /* 2834342306fSKonstantin Komarov * ntfs_sparse_cluster 2844342306fSKonstantin Komarov * 2854342306fSKonstantin Komarov * Helper function to zero a new allocated clusters 2864342306fSKonstantin Komarov * NOTE: 512 <= cluster size <= 2M 2874342306fSKonstantin Komarov */ 2884342306fSKonstantin Komarov void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST vcn, 2894342306fSKonstantin Komarov CLST len) 2904342306fSKonstantin Komarov { 2914342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 2924342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 2934342306fSKonstantin Komarov u64 vbo = (u64)vcn << sbi->cluster_bits; 2944342306fSKonstantin Komarov u64 bytes = (u64)len << sbi->cluster_bits; 2954342306fSKonstantin Komarov u32 blocksize = 1 << inode->i_blkbits; 2964342306fSKonstantin Komarov pgoff_t idx0 = page0 ? page0->index : -1; 2974342306fSKonstantin Komarov loff_t vbo_clst = vbo & sbi->cluster_mask_inv; 2984342306fSKonstantin Komarov loff_t end = ntfs_up_cluster(sbi, vbo + bytes); 2994342306fSKonstantin Komarov pgoff_t idx = vbo_clst >> PAGE_SHIFT; 3004342306fSKonstantin Komarov u32 from = vbo_clst & (PAGE_SIZE - 1); 3014342306fSKonstantin Komarov pgoff_t idx_end = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; 3024342306fSKonstantin Komarov loff_t page_off; 3034342306fSKonstantin Komarov u32 to; 3044342306fSKonstantin Komarov bool partial; 3054342306fSKonstantin Komarov struct page *page; 3064342306fSKonstantin Komarov 3074342306fSKonstantin Komarov for (; idx < idx_end; idx += 1, from = 0) { 3084342306fSKonstantin Komarov page = idx == idx0 ? page0 : grab_cache_page(mapping, idx); 3094342306fSKonstantin Komarov 3104342306fSKonstantin Komarov if (!page) 3114342306fSKonstantin Komarov continue; 3124342306fSKonstantin Komarov 3134342306fSKonstantin Komarov page_off = (loff_t)idx << PAGE_SHIFT; 3144342306fSKonstantin Komarov to = (page_off + PAGE_SIZE) > end ? (end - page_off) 3154342306fSKonstantin Komarov : PAGE_SIZE; 3164342306fSKonstantin Komarov partial = false; 3174342306fSKonstantin Komarov 3184342306fSKonstantin Komarov if ((from || PAGE_SIZE != to) && 3194342306fSKonstantin Komarov likely(!page_has_buffers(page))) { 3204342306fSKonstantin Komarov create_empty_buffers(page, blocksize, 0); 3214342306fSKonstantin Komarov } 3224342306fSKonstantin Komarov 3234342306fSKonstantin Komarov if (page_has_buffers(page)) { 3244342306fSKonstantin Komarov struct buffer_head *head, *bh; 3254342306fSKonstantin Komarov u32 bh_off = 0; 3264342306fSKonstantin Komarov 3274342306fSKonstantin Komarov bh = head = page_buffers(page); 3284342306fSKonstantin Komarov do { 3294342306fSKonstantin Komarov u32 bh_next = bh_off + blocksize; 3304342306fSKonstantin Komarov 3314342306fSKonstantin Komarov if (from <= bh_off && bh_next <= to) { 3324342306fSKonstantin Komarov set_buffer_uptodate(bh); 3334342306fSKonstantin Komarov mark_buffer_dirty(bh); 3344342306fSKonstantin Komarov } else if (!buffer_uptodate(bh)) { 3354342306fSKonstantin Komarov partial = true; 3364342306fSKonstantin Komarov } 3374342306fSKonstantin Komarov bh_off = bh_next; 3384342306fSKonstantin Komarov } while (head != (bh = bh->b_this_page)); 3394342306fSKonstantin Komarov } 3404342306fSKonstantin Komarov 3414342306fSKonstantin Komarov zero_user_segment(page, from, to); 3424342306fSKonstantin Komarov 3434342306fSKonstantin Komarov if (!partial) { 3444342306fSKonstantin Komarov if (!PageUptodate(page)) 3454342306fSKonstantin Komarov SetPageUptodate(page); 3464342306fSKonstantin Komarov set_page_dirty(page); 3474342306fSKonstantin Komarov } 3484342306fSKonstantin Komarov 3494342306fSKonstantin Komarov if (idx != idx0) { 3504342306fSKonstantin Komarov unlock_page(page); 3514342306fSKonstantin Komarov put_page(page); 3524342306fSKonstantin Komarov } 3534342306fSKonstantin Komarov cond_resched(); 3544342306fSKonstantin Komarov } 3554342306fSKonstantin Komarov mark_inode_dirty(inode); 3564342306fSKonstantin Komarov } 3574342306fSKonstantin Komarov 3584342306fSKonstantin Komarov /* 3594342306fSKonstantin Komarov * file_operations::mmap 3604342306fSKonstantin Komarov */ 3614342306fSKonstantin Komarov static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma) 3624342306fSKonstantin Komarov { 3634342306fSKonstantin Komarov struct address_space *mapping = file->f_mapping; 3644342306fSKonstantin Komarov struct inode *inode = mapping->host; 3654342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 3664342306fSKonstantin Komarov u64 from = ((u64)vma->vm_pgoff << PAGE_SHIFT); 3674342306fSKonstantin Komarov bool rw = vma->vm_flags & VM_WRITE; 3684342306fSKonstantin Komarov int err; 3694342306fSKonstantin Komarov 3704342306fSKonstantin Komarov if (is_encrypted(ni)) { 3714342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap encrypted not supported"); 3724342306fSKonstantin Komarov return -EOPNOTSUPP; 3734342306fSKonstantin Komarov } 3744342306fSKonstantin Komarov 3754342306fSKonstantin Komarov if (is_dedup(ni)) { 3764342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap deduplicated not supported"); 3774342306fSKonstantin Komarov return -EOPNOTSUPP; 3784342306fSKonstantin Komarov } 3794342306fSKonstantin Komarov 3804342306fSKonstantin Komarov if (is_compressed(ni) && rw) { 3814342306fSKonstantin Komarov ntfs_inode_warn(inode, "mmap(write) compressed not supported"); 3824342306fSKonstantin Komarov return -EOPNOTSUPP; 3834342306fSKonstantin Komarov } 3844342306fSKonstantin Komarov 3854342306fSKonstantin Komarov if (rw) { 3864342306fSKonstantin Komarov u64 to = min_t(loff_t, i_size_read(inode), 3874342306fSKonstantin Komarov from + vma->vm_end - vma->vm_start); 3884342306fSKonstantin Komarov 3894342306fSKonstantin Komarov if (is_sparsed(ni)) { 3904342306fSKonstantin Komarov /* allocate clusters for rw map */ 3914342306fSKonstantin Komarov struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; 3924342306fSKonstantin Komarov CLST lcn, len; 3934342306fSKonstantin Komarov CLST vcn = from >> sbi->cluster_bits; 3944342306fSKonstantin Komarov CLST end = bytes_to_cluster(sbi, to); 3954342306fSKonstantin Komarov bool new; 3964342306fSKonstantin Komarov 3974342306fSKonstantin Komarov for (; vcn < end; vcn += len) { 3984342306fSKonstantin Komarov err = attr_data_get_block(ni, vcn, 1, &lcn, 3994342306fSKonstantin Komarov &len, &new); 4004342306fSKonstantin Komarov if (err) 4014342306fSKonstantin Komarov goto out; 4024342306fSKonstantin Komarov 4034342306fSKonstantin Komarov if (!new) 4044342306fSKonstantin Komarov continue; 4054342306fSKonstantin Komarov ntfs_sparse_cluster(inode, NULL, vcn, 1); 4064342306fSKonstantin Komarov } 4074342306fSKonstantin Komarov } 4084342306fSKonstantin Komarov 4094342306fSKonstantin Komarov if (ni->i_valid < to) { 4104342306fSKonstantin Komarov if (!inode_trylock(inode)) { 4114342306fSKonstantin Komarov err = -EAGAIN; 4124342306fSKonstantin Komarov goto out; 4134342306fSKonstantin Komarov } 4144342306fSKonstantin Komarov err = ntfs_extend_initialized_size(file, ni, 4154342306fSKonstantin Komarov ni->i_valid, to); 4164342306fSKonstantin Komarov inode_unlock(inode); 4174342306fSKonstantin Komarov if (err) 4184342306fSKonstantin Komarov goto out; 4194342306fSKonstantin Komarov } 4204342306fSKonstantin Komarov } 4214342306fSKonstantin Komarov 4224342306fSKonstantin Komarov err = generic_file_mmap(file, vma); 4234342306fSKonstantin Komarov out: 4244342306fSKonstantin Komarov return err; 4254342306fSKonstantin Komarov } 4264342306fSKonstantin Komarov 4274342306fSKonstantin Komarov static int ntfs_extend(struct inode *inode, loff_t pos, size_t count, 4284342306fSKonstantin Komarov struct file *file) 4294342306fSKonstantin Komarov { 4304342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 4314342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 4324342306fSKonstantin Komarov loff_t end = pos + count; 4334342306fSKonstantin Komarov bool extend_init = file && pos > ni->i_valid; 4344342306fSKonstantin Komarov int err; 4354342306fSKonstantin Komarov 4364342306fSKonstantin Komarov if (end <= inode->i_size && !extend_init) 4374342306fSKonstantin Komarov return 0; 4384342306fSKonstantin Komarov 4394342306fSKonstantin Komarov /*mark rw ntfs as dirty. it will be cleared at umount*/ 4404342306fSKonstantin Komarov ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY); 4414342306fSKonstantin Komarov 4424342306fSKonstantin Komarov if (end > inode->i_size) { 4434342306fSKonstantin Komarov err = ntfs_set_size(inode, end); 4444342306fSKonstantin Komarov if (err) 4454342306fSKonstantin Komarov goto out; 4464342306fSKonstantin Komarov inode->i_size = end; 4474342306fSKonstantin Komarov } 4484342306fSKonstantin Komarov 4494342306fSKonstantin Komarov if (extend_init && !is_compressed(ni)) { 4504342306fSKonstantin Komarov err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos); 4514342306fSKonstantin Komarov if (err) 4524342306fSKonstantin Komarov goto out; 4534342306fSKonstantin Komarov } else { 4544342306fSKonstantin Komarov err = 0; 4554342306fSKonstantin Komarov } 4564342306fSKonstantin Komarov 4574342306fSKonstantin Komarov inode->i_ctime = inode->i_mtime = current_time(inode); 4584342306fSKonstantin Komarov mark_inode_dirty(inode); 4594342306fSKonstantin Komarov 4604342306fSKonstantin Komarov if (IS_SYNC(inode)) { 4614342306fSKonstantin Komarov int err2; 4624342306fSKonstantin Komarov 4634342306fSKonstantin Komarov err = filemap_fdatawrite_range(mapping, pos, end - 1); 4644342306fSKonstantin Komarov err2 = sync_mapping_buffers(mapping); 4654342306fSKonstantin Komarov if (!err) 4664342306fSKonstantin Komarov err = err2; 4674342306fSKonstantin Komarov err2 = write_inode_now(inode, 1); 4684342306fSKonstantin Komarov if (!err) 4694342306fSKonstantin Komarov err = err2; 4704342306fSKonstantin Komarov if (!err) 4714342306fSKonstantin Komarov err = filemap_fdatawait_range(mapping, pos, end - 1); 4724342306fSKonstantin Komarov } 4734342306fSKonstantin Komarov 4744342306fSKonstantin Komarov out: 4754342306fSKonstantin Komarov return err; 4764342306fSKonstantin Komarov } 4774342306fSKonstantin Komarov 4784342306fSKonstantin Komarov static int ntfs_truncate(struct inode *inode, loff_t new_size) 4794342306fSKonstantin Komarov { 4804342306fSKonstantin Komarov struct super_block *sb = inode->i_sb; 4814342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 4824342306fSKonstantin Komarov int err, dirty = 0; 4834342306fSKonstantin Komarov u64 new_valid; 4844342306fSKonstantin Komarov 4854342306fSKonstantin Komarov if (!S_ISREG(inode->i_mode)) 4864342306fSKonstantin Komarov return 0; 4874342306fSKonstantin Komarov 4884342306fSKonstantin Komarov if (is_compressed(ni)) { 4894342306fSKonstantin Komarov if (ni->i_valid > new_size) 4904342306fSKonstantin Komarov ni->i_valid = new_size; 4914342306fSKonstantin Komarov } else { 4924342306fSKonstantin Komarov err = block_truncate_page(inode->i_mapping, new_size, 4934342306fSKonstantin Komarov ntfs_get_block); 4944342306fSKonstantin Komarov if (err) 4954342306fSKonstantin Komarov return err; 4964342306fSKonstantin Komarov } 4974342306fSKonstantin Komarov 4984342306fSKonstantin Komarov new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size)); 4994342306fSKonstantin Komarov 5004342306fSKonstantin Komarov ni_lock(ni); 5014342306fSKonstantin Komarov 5024342306fSKonstantin Komarov truncate_setsize(inode, new_size); 5034342306fSKonstantin Komarov 5044342306fSKonstantin Komarov down_write(&ni->file.run_lock); 5054342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, 5064342306fSKonstantin Komarov &new_valid, true, NULL); 5074342306fSKonstantin Komarov up_write(&ni->file.run_lock); 5084342306fSKonstantin Komarov 5094342306fSKonstantin Komarov if (new_valid < ni->i_valid) 5104342306fSKonstantin Komarov ni->i_valid = new_valid; 5114342306fSKonstantin Komarov 5124342306fSKonstantin Komarov ni_unlock(ni); 5134342306fSKonstantin Komarov 5144342306fSKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE; 5154342306fSKonstantin Komarov inode->i_ctime = inode->i_mtime = current_time(inode); 5164342306fSKonstantin Komarov if (!IS_DIRSYNC(inode)) { 5174342306fSKonstantin Komarov dirty = 1; 5184342306fSKonstantin Komarov } else { 5194342306fSKonstantin Komarov err = ntfs_sync_inode(inode); 5204342306fSKonstantin Komarov if (err) 5214342306fSKonstantin Komarov return err; 5224342306fSKonstantin Komarov } 5234342306fSKonstantin Komarov 5244342306fSKonstantin Komarov if (dirty) 5254342306fSKonstantin Komarov mark_inode_dirty(inode); 5264342306fSKonstantin Komarov 5274342306fSKonstantin Komarov /*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/ 5284342306fSKonstantin Komarov 5294342306fSKonstantin Komarov return 0; 5304342306fSKonstantin Komarov } 5314342306fSKonstantin Komarov 5324342306fSKonstantin Komarov /* 5334342306fSKonstantin Komarov * Preallocate space for a file. This implements ntfs's fallocate file 5344342306fSKonstantin Komarov * operation, which gets called from sys_fallocate system call. User 5354342306fSKonstantin Komarov * space requests 'len' bytes at 'vbo'. If FALLOC_FL_KEEP_SIZE is set 5364342306fSKonstantin Komarov * we just allocate clusters without zeroing them out. Otherwise we 5374342306fSKonstantin Komarov * allocate and zero out clusters via an expanding truncate. 5384342306fSKonstantin Komarov */ 5394342306fSKonstantin Komarov static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) 5404342306fSKonstantin Komarov { 5414342306fSKonstantin Komarov struct inode *inode = file->f_mapping->host; 5424342306fSKonstantin Komarov struct super_block *sb = inode->i_sb; 5434342306fSKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 5444342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 5454342306fSKonstantin Komarov loff_t end = vbo + len; 5464342306fSKonstantin Komarov loff_t vbo_down = round_down(vbo, PAGE_SIZE); 5474342306fSKonstantin Komarov loff_t i_size; 5484342306fSKonstantin Komarov int err; 5494342306fSKonstantin Komarov 5504342306fSKonstantin Komarov /* No support for dir */ 5514342306fSKonstantin Komarov if (!S_ISREG(inode->i_mode)) 5524342306fSKonstantin Komarov return -EOPNOTSUPP; 5534342306fSKonstantin Komarov 5544342306fSKonstantin Komarov /* Return error if mode is not supported */ 5554342306fSKonstantin Komarov if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | 5564342306fSKonstantin Komarov FALLOC_FL_COLLAPSE_RANGE)) { 5574342306fSKonstantin Komarov ntfs_inode_warn(inode, "fallocate(0x%x) is not supported", 5584342306fSKonstantin Komarov mode); 5594342306fSKonstantin Komarov return -EOPNOTSUPP; 5604342306fSKonstantin Komarov } 5614342306fSKonstantin Komarov 5624342306fSKonstantin Komarov ntfs_set_state(sbi, NTFS_DIRTY_DIRTY); 5634342306fSKonstantin Komarov 5644342306fSKonstantin Komarov inode_lock(inode); 5654342306fSKonstantin Komarov i_size = inode->i_size; 5664342306fSKonstantin Komarov 5674342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 5684342306fSKonstantin Komarov /* should never be here, see ntfs_file_open*/ 5694342306fSKonstantin Komarov err = -EOPNOTSUPP; 5704342306fSKonstantin Komarov goto out; 5714342306fSKonstantin Komarov } 5724342306fSKonstantin Komarov 5734342306fSKonstantin Komarov if (mode & FALLOC_FL_PUNCH_HOLE) { 5744342306fSKonstantin Komarov u32 frame_size; 5754342306fSKonstantin Komarov loff_t mask, vbo_a, end_a, tmp; 5764342306fSKonstantin Komarov 5774342306fSKonstantin Komarov if (!(mode & FALLOC_FL_KEEP_SIZE)) { 5784342306fSKonstantin Komarov err = -EINVAL; 5794342306fSKonstantin Komarov goto out; 5804342306fSKonstantin Komarov } 5814342306fSKonstantin Komarov 5824342306fSKonstantin Komarov err = filemap_write_and_wait_range(inode->i_mapping, vbo, 5834342306fSKonstantin Komarov end - 1); 5844342306fSKonstantin Komarov if (err) 5854342306fSKonstantin Komarov goto out; 5864342306fSKonstantin Komarov 5874342306fSKonstantin Komarov err = filemap_write_and_wait_range(inode->i_mapping, end, 5884342306fSKonstantin Komarov LLONG_MAX); 5894342306fSKonstantin Komarov if (err) 5904342306fSKonstantin Komarov goto out; 5914342306fSKonstantin Komarov 5924342306fSKonstantin Komarov inode_dio_wait(inode); 5934342306fSKonstantin Komarov 5944342306fSKonstantin Komarov truncate_pagecache(inode, vbo_down); 5954342306fSKonstantin Komarov 5964342306fSKonstantin Komarov if (!is_sparsed(ni) && !is_compressed(ni)) { 5974342306fSKonstantin Komarov /* normal file */ 5984342306fSKonstantin Komarov err = ntfs_zero_range(inode, vbo, end); 5994342306fSKonstantin Komarov goto out; 6004342306fSKonstantin Komarov } 6014342306fSKonstantin Komarov 6024342306fSKonstantin Komarov ni_lock(ni); 6034342306fSKonstantin Komarov err = attr_punch_hole(ni, vbo, len, &frame_size); 6044342306fSKonstantin Komarov ni_unlock(ni); 6054342306fSKonstantin Komarov if (err != E_NTFS_NOTALIGNED) 6064342306fSKonstantin Komarov goto out; 6074342306fSKonstantin Komarov 6084342306fSKonstantin Komarov /* process not aligned punch */ 6094342306fSKonstantin Komarov mask = frame_size - 1; 6104342306fSKonstantin Komarov vbo_a = (vbo + mask) & ~mask; 6114342306fSKonstantin Komarov end_a = end & ~mask; 6124342306fSKonstantin Komarov 6134342306fSKonstantin Komarov tmp = min(vbo_a, end); 6144342306fSKonstantin Komarov if (tmp > vbo) { 6154342306fSKonstantin Komarov err = ntfs_zero_range(inode, vbo, tmp); 6164342306fSKonstantin Komarov if (err) 6174342306fSKonstantin Komarov goto out; 6184342306fSKonstantin Komarov } 6194342306fSKonstantin Komarov 6204342306fSKonstantin Komarov if (vbo < end_a && end_a < end) { 6214342306fSKonstantin Komarov err = ntfs_zero_range(inode, end_a, end); 6224342306fSKonstantin Komarov if (err) 6234342306fSKonstantin Komarov goto out; 6244342306fSKonstantin Komarov } 6254342306fSKonstantin Komarov 6264342306fSKonstantin Komarov /* Aligned punch_hole */ 6274342306fSKonstantin Komarov if (end_a > vbo_a) { 6284342306fSKonstantin Komarov ni_lock(ni); 6294342306fSKonstantin Komarov err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL); 6304342306fSKonstantin Komarov ni_unlock(ni); 6314342306fSKonstantin Komarov } 6324342306fSKonstantin Komarov } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { 6334342306fSKonstantin Komarov if (mode & ~FALLOC_FL_COLLAPSE_RANGE) { 6344342306fSKonstantin Komarov err = -EINVAL; 6354342306fSKonstantin Komarov goto out; 6364342306fSKonstantin Komarov } 6374342306fSKonstantin Komarov 6384342306fSKonstantin Komarov /* 6394342306fSKonstantin Komarov * Write tail of the last page before removed range since 6404342306fSKonstantin Komarov * it will get removed from the page cache below. 6414342306fSKonstantin Komarov */ 6424342306fSKonstantin Komarov err = filemap_write_and_wait_range(inode->i_mapping, vbo_down, 6434342306fSKonstantin Komarov vbo); 6444342306fSKonstantin Komarov if (err) 6454342306fSKonstantin Komarov goto out; 6464342306fSKonstantin Komarov 6474342306fSKonstantin Komarov /* 6484342306fSKonstantin Komarov * Write data that will be shifted to preserve them 6494342306fSKonstantin Komarov * when discarding page cache below 6504342306fSKonstantin Komarov */ 6514342306fSKonstantin Komarov err = filemap_write_and_wait_range(inode->i_mapping, end, 6524342306fSKonstantin Komarov LLONG_MAX); 6534342306fSKonstantin Komarov if (err) 6544342306fSKonstantin Komarov goto out; 6554342306fSKonstantin Komarov 6564342306fSKonstantin Komarov /* Wait for existing dio to complete */ 6574342306fSKonstantin Komarov inode_dio_wait(inode); 6584342306fSKonstantin Komarov 6594342306fSKonstantin Komarov truncate_pagecache(inode, vbo_down); 6604342306fSKonstantin Komarov 6614342306fSKonstantin Komarov ni_lock(ni); 6624342306fSKonstantin Komarov err = attr_collapse_range(ni, vbo, len); 6634342306fSKonstantin Komarov ni_unlock(ni); 6644342306fSKonstantin Komarov } else { 6654342306fSKonstantin Komarov /* 6664342306fSKonstantin Komarov * normal file: allocate clusters, do not change 'valid' size 6674342306fSKonstantin Komarov */ 6684342306fSKonstantin Komarov err = ntfs_set_size(inode, max(end, i_size)); 6694342306fSKonstantin Komarov if (err) 6704342306fSKonstantin Komarov goto out; 6714342306fSKonstantin Komarov 6724342306fSKonstantin Komarov if (is_sparsed(ni) || is_compressed(ni)) { 6734342306fSKonstantin Komarov CLST vcn_v = ni->i_valid >> sbi->cluster_bits; 6744342306fSKonstantin Komarov CLST vcn = vbo >> sbi->cluster_bits; 6754342306fSKonstantin Komarov CLST cend = bytes_to_cluster(sbi, end); 6764342306fSKonstantin Komarov CLST lcn, clen; 6774342306fSKonstantin Komarov bool new; 6784342306fSKonstantin Komarov 6794342306fSKonstantin Komarov /* 6804342306fSKonstantin Komarov * allocate but not zero new clusters (see below comments) 6814342306fSKonstantin Komarov * this breaks security (one can read unused on-disk areas) 6824342306fSKonstantin Komarov * zeroing these clusters may be too long 6834342306fSKonstantin Komarov * may be we should check here for root rights? 6844342306fSKonstantin Komarov */ 6854342306fSKonstantin Komarov for (; vcn < cend; vcn += clen) { 6864342306fSKonstantin Komarov err = attr_data_get_block(ni, vcn, cend - vcn, 6874342306fSKonstantin Komarov &lcn, &clen, &new); 6884342306fSKonstantin Komarov if (err) 6894342306fSKonstantin Komarov goto out; 6904342306fSKonstantin Komarov if (!new || vcn >= vcn_v) 6914342306fSKonstantin Komarov continue; 6924342306fSKonstantin Komarov 6934342306fSKonstantin Komarov /* 6944342306fSKonstantin Komarov * Unwritten area 6954342306fSKonstantin Komarov * NTFS is not able to store several unwritten areas 6964342306fSKonstantin Komarov * Activate 'ntfs_sparse_cluster' to zero new allocated clusters 6974342306fSKonstantin Komarov * 6984342306fSKonstantin Komarov * Dangerous in case: 6994342306fSKonstantin Komarov * 1G of sparsed clusters + 1 cluster of data => 7004342306fSKonstantin Komarov * valid_size == 1G + 1 cluster 7014342306fSKonstantin Komarov * fallocate(1G) will zero 1G and this can be very long 7024342306fSKonstantin Komarov * xfstest 016/086 will fail without 'ntfs_sparse_cluster' 7034342306fSKonstantin Komarov */ 7044342306fSKonstantin Komarov ntfs_sparse_cluster(inode, NULL, vcn, 7054342306fSKonstantin Komarov min(vcn_v - vcn, clen)); 7064342306fSKonstantin Komarov } 7074342306fSKonstantin Komarov } 7084342306fSKonstantin Komarov 7094342306fSKonstantin Komarov if (mode & FALLOC_FL_KEEP_SIZE) { 7104342306fSKonstantin Komarov ni_lock(ni); 7114342306fSKonstantin Komarov /*true - keep preallocated*/ 7124342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, 7134342306fSKonstantin Komarov &ni->file.run, i_size, &ni->i_valid, 7144342306fSKonstantin Komarov true, NULL); 7154342306fSKonstantin Komarov ni_unlock(ni); 7164342306fSKonstantin Komarov } 7174342306fSKonstantin Komarov } 7184342306fSKonstantin Komarov 7194342306fSKonstantin Komarov out: 7204342306fSKonstantin Komarov if (err == -EFBIG) 7214342306fSKonstantin Komarov err = -ENOSPC; 7224342306fSKonstantin Komarov 7234342306fSKonstantin Komarov if (!err) { 7244342306fSKonstantin Komarov inode->i_ctime = inode->i_mtime = current_time(inode); 7254342306fSKonstantin Komarov mark_inode_dirty(inode); 7264342306fSKonstantin Komarov } 7274342306fSKonstantin Komarov 7284342306fSKonstantin Komarov inode_unlock(inode); 7294342306fSKonstantin Komarov return err; 7304342306fSKonstantin Komarov } 7314342306fSKonstantin Komarov 7324342306fSKonstantin Komarov /* 7334342306fSKonstantin Komarov * inode_operations::setattr 7344342306fSKonstantin Komarov */ 7354342306fSKonstantin Komarov int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, 7364342306fSKonstantin Komarov struct iattr *attr) 7374342306fSKonstantin Komarov { 7384342306fSKonstantin Komarov struct super_block *sb = dentry->d_sb; 7394342306fSKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 7404342306fSKonstantin Komarov struct inode *inode = d_inode(dentry); 7414342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 7424342306fSKonstantin Komarov u32 ia_valid = attr->ia_valid; 7434342306fSKonstantin Komarov umode_t mode = inode->i_mode; 7444342306fSKonstantin Komarov int err; 7454342306fSKonstantin Komarov 7464342306fSKonstantin Komarov if (sbi->options.no_acs_rules) { 7474342306fSKonstantin Komarov /* "no access rules" - force any changes of time etc. */ 7484342306fSKonstantin Komarov attr->ia_valid |= ATTR_FORCE; 7494342306fSKonstantin Komarov /* and disable for editing some attributes */ 7504342306fSKonstantin Komarov attr->ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); 7514342306fSKonstantin Komarov ia_valid = attr->ia_valid; 7524342306fSKonstantin Komarov } 7534342306fSKonstantin Komarov 7544342306fSKonstantin Komarov err = setattr_prepare(mnt_userns, dentry, attr); 7554342306fSKonstantin Komarov if (err) 7564342306fSKonstantin Komarov goto out; 7574342306fSKonstantin Komarov 7584342306fSKonstantin Komarov if (ia_valid & ATTR_SIZE) { 7594342306fSKonstantin Komarov loff_t oldsize = inode->i_size; 7604342306fSKonstantin Komarov 7614342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 7624342306fSKonstantin Komarov /* should never be here, see ntfs_file_open*/ 7634342306fSKonstantin Komarov err = -EOPNOTSUPP; 7644342306fSKonstantin Komarov goto out; 7654342306fSKonstantin Komarov } 7664342306fSKonstantin Komarov inode_dio_wait(inode); 7674342306fSKonstantin Komarov 7684342306fSKonstantin Komarov if (attr->ia_size < oldsize) 7694342306fSKonstantin Komarov err = ntfs_truncate(inode, attr->ia_size); 7704342306fSKonstantin Komarov else if (attr->ia_size > oldsize) 7714342306fSKonstantin Komarov err = ntfs_extend(inode, attr->ia_size, 0, NULL); 7724342306fSKonstantin Komarov 7734342306fSKonstantin Komarov if (err) 7744342306fSKonstantin Komarov goto out; 7754342306fSKonstantin Komarov 7764342306fSKonstantin Komarov ni->ni_flags |= NI_FLAG_UPDATE_PARENT; 7774342306fSKonstantin Komarov } 7784342306fSKonstantin Komarov 7794342306fSKonstantin Komarov setattr_copy(mnt_userns, inode, attr); 7804342306fSKonstantin Komarov 7814342306fSKonstantin Komarov if (mode != inode->i_mode) { 7824342306fSKonstantin Komarov err = ntfs_acl_chmod(mnt_userns, inode); 7834342306fSKonstantin Komarov if (err) 7844342306fSKonstantin Komarov goto out; 7854342306fSKonstantin Komarov 7864342306fSKonstantin Komarov /* linux 'w' -> windows 'ro' */ 7874342306fSKonstantin Komarov if (0222 & inode->i_mode) 7884342306fSKonstantin Komarov ni->std_fa &= ~FILE_ATTRIBUTE_READONLY; 7894342306fSKonstantin Komarov else 7904342306fSKonstantin Komarov ni->std_fa |= FILE_ATTRIBUTE_READONLY; 7914342306fSKonstantin Komarov } 7924342306fSKonstantin Komarov 7934342306fSKonstantin Komarov if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) 7944342306fSKonstantin Komarov ntfs_save_wsl_perm(inode); 7954342306fSKonstantin Komarov mark_inode_dirty(inode); 7964342306fSKonstantin Komarov out: 7974342306fSKonstantin Komarov return err; 7984342306fSKonstantin Komarov } 7994342306fSKonstantin Komarov 8004342306fSKonstantin Komarov static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 8014342306fSKonstantin Komarov { 8024342306fSKonstantin Komarov ssize_t err; 8034342306fSKonstantin Komarov size_t count = iov_iter_count(iter); 8044342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 8054342306fSKonstantin Komarov struct inode *inode = file->f_mapping->host; 8064342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 8074342306fSKonstantin Komarov 8084342306fSKonstantin Komarov if (is_encrypted(ni)) { 8094342306fSKonstantin Komarov ntfs_inode_warn(inode, "encrypted i/o not supported"); 8104342306fSKonstantin Komarov return -EOPNOTSUPP; 8114342306fSKonstantin Komarov } 8124342306fSKonstantin Komarov 8134342306fSKonstantin Komarov if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 8144342306fSKonstantin Komarov ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 8154342306fSKonstantin Komarov return -EOPNOTSUPP; 8164342306fSKonstantin Komarov } 8174342306fSKonstantin Komarov 8184342306fSKonstantin Komarov #ifndef CONFIG_NTFS3_LZX_XPRESS 8194342306fSKonstantin Komarov if (ni->ni_flags & NI_FLAG_COMPRESSED_MASK) { 8204342306fSKonstantin Komarov ntfs_inode_warn( 8214342306fSKonstantin Komarov inode, 8224342306fSKonstantin Komarov "activate CONFIG_NTFS3_LZX_XPRESS to read external compressed files"); 8234342306fSKonstantin Komarov return -EOPNOTSUPP; 8244342306fSKonstantin Komarov } 8254342306fSKonstantin Komarov #endif 8264342306fSKonstantin Komarov 8274342306fSKonstantin Komarov if (is_dedup(ni)) { 8284342306fSKonstantin Komarov ntfs_inode_warn(inode, "read deduplicated not supported"); 8294342306fSKonstantin Komarov return -EOPNOTSUPP; 8304342306fSKonstantin Komarov } 8314342306fSKonstantin Komarov 8324342306fSKonstantin Komarov err = count ? generic_file_read_iter(iocb, iter) : 0; 8334342306fSKonstantin Komarov 8344342306fSKonstantin Komarov return err; 8354342306fSKonstantin Komarov } 8364342306fSKonstantin Komarov 8374342306fSKonstantin Komarov /* returns array of locked pages */ 8384342306fSKonstantin Komarov static int ntfs_get_frame_pages(struct address_space *mapping, pgoff_t index, 8394342306fSKonstantin Komarov struct page **pages, u32 pages_per_frame, 8404342306fSKonstantin Komarov bool *frame_uptodate) 8414342306fSKonstantin Komarov { 8424342306fSKonstantin Komarov gfp_t gfp_mask = mapping_gfp_mask(mapping); 8434342306fSKonstantin Komarov u32 npages; 8444342306fSKonstantin Komarov 8454342306fSKonstantin Komarov *frame_uptodate = true; 8464342306fSKonstantin Komarov 8474342306fSKonstantin Komarov for (npages = 0; npages < pages_per_frame; npages++, index++) { 8484342306fSKonstantin Komarov struct page *page; 8494342306fSKonstantin Komarov 8504342306fSKonstantin Komarov page = find_or_create_page(mapping, index, gfp_mask); 8514342306fSKonstantin Komarov if (!page) { 8524342306fSKonstantin Komarov while (npages--) { 8534342306fSKonstantin Komarov page = pages[npages]; 8544342306fSKonstantin Komarov unlock_page(page); 8554342306fSKonstantin Komarov put_page(page); 8564342306fSKonstantin Komarov } 8574342306fSKonstantin Komarov 8584342306fSKonstantin Komarov return -ENOMEM; 8594342306fSKonstantin Komarov } 8604342306fSKonstantin Komarov 8614342306fSKonstantin Komarov if (!PageUptodate(page)) 8624342306fSKonstantin Komarov *frame_uptodate = false; 8634342306fSKonstantin Komarov 8644342306fSKonstantin Komarov pages[npages] = page; 8654342306fSKonstantin Komarov } 8664342306fSKonstantin Komarov 8674342306fSKonstantin Komarov return 0; 8684342306fSKonstantin Komarov } 8694342306fSKonstantin Komarov 8704342306fSKonstantin Komarov /*helper for ntfs_file_write_iter (compressed files)*/ 8714342306fSKonstantin Komarov static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) 8724342306fSKonstantin Komarov { 8734342306fSKonstantin Komarov int err; 8744342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 8754342306fSKonstantin Komarov size_t count = iov_iter_count(from); 8764342306fSKonstantin Komarov loff_t pos = iocb->ki_pos; 8774342306fSKonstantin Komarov struct inode *inode = file_inode(file); 8784342306fSKonstantin Komarov loff_t i_size = inode->i_size; 8794342306fSKonstantin Komarov struct address_space *mapping = inode->i_mapping; 8804342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 8814342306fSKonstantin Komarov u64 valid = ni->i_valid; 8824342306fSKonstantin Komarov struct ntfs_sb_info *sbi = ni->mi.sbi; 8834342306fSKonstantin Komarov struct page *page, **pages = NULL; 8844342306fSKonstantin Komarov size_t written = 0; 8854342306fSKonstantin Komarov u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits; 8864342306fSKonstantin Komarov u32 frame_size = 1u << frame_bits; 8874342306fSKonstantin Komarov u32 pages_per_frame = frame_size >> PAGE_SHIFT; 8884342306fSKonstantin Komarov u32 ip, off; 8894342306fSKonstantin Komarov CLST frame; 8904342306fSKonstantin Komarov u64 frame_vbo; 8914342306fSKonstantin Komarov pgoff_t index; 8924342306fSKonstantin Komarov bool frame_uptodate; 8934342306fSKonstantin Komarov 8944342306fSKonstantin Komarov if (frame_size < PAGE_SIZE) { 8954342306fSKonstantin Komarov /* 8964342306fSKonstantin Komarov * frame_size == 8K if cluster 512 8974342306fSKonstantin Komarov * frame_size == 64K if cluster 4096 8984342306fSKonstantin Komarov */ 8994342306fSKonstantin Komarov ntfs_inode_warn(inode, "page size is bigger than frame size"); 9004342306fSKonstantin Komarov return -EOPNOTSUPP; 9014342306fSKonstantin Komarov } 9024342306fSKonstantin Komarov 903*195c52bdSKari Argillander pages = kmalloc(pages_per_frame * sizeof(struct page *), GFP_NOFS); 9044342306fSKonstantin Komarov if (!pages) 9054342306fSKonstantin Komarov return -ENOMEM; 9064342306fSKonstantin Komarov 9074342306fSKonstantin Komarov current->backing_dev_info = inode_to_bdi(inode); 9084342306fSKonstantin Komarov err = file_remove_privs(file); 9094342306fSKonstantin Komarov if (err) 9104342306fSKonstantin Komarov goto out; 9114342306fSKonstantin Komarov 9124342306fSKonstantin Komarov err = file_update_time(file); 9134342306fSKonstantin Komarov if (err) 9144342306fSKonstantin Komarov goto out; 9154342306fSKonstantin Komarov 9164342306fSKonstantin Komarov /* zero range [valid : pos) */ 9174342306fSKonstantin Komarov while (valid < pos) { 9184342306fSKonstantin Komarov CLST lcn, clen; 9194342306fSKonstantin Komarov 9204342306fSKonstantin Komarov frame = valid >> frame_bits; 9214342306fSKonstantin Komarov frame_vbo = valid & ~(frame_size - 1); 9224342306fSKonstantin Komarov off = valid & (frame_size - 1); 9234342306fSKonstantin Komarov 9244342306fSKonstantin Komarov err = attr_data_get_block(ni, frame << NTFS_LZNT_CUNIT, 0, &lcn, 9254342306fSKonstantin Komarov &clen, NULL); 9264342306fSKonstantin Komarov if (err) 9274342306fSKonstantin Komarov goto out; 9284342306fSKonstantin Komarov 9294342306fSKonstantin Komarov if (lcn == SPARSE_LCN) { 9304342306fSKonstantin Komarov ni->i_valid = valid = 9314342306fSKonstantin Komarov frame_vbo + ((u64)clen << sbi->cluster_bits); 9324342306fSKonstantin Komarov continue; 9334342306fSKonstantin Komarov } 9344342306fSKonstantin Komarov 9354342306fSKonstantin Komarov /* Load full frame */ 9364342306fSKonstantin Komarov err = ntfs_get_frame_pages(mapping, frame_vbo >> PAGE_SHIFT, 9374342306fSKonstantin Komarov pages, pages_per_frame, 9384342306fSKonstantin Komarov &frame_uptodate); 9394342306fSKonstantin Komarov if (err) 9404342306fSKonstantin Komarov goto out; 9414342306fSKonstantin Komarov 9424342306fSKonstantin Komarov if (!frame_uptodate && off) { 9434342306fSKonstantin Komarov err = ni_read_frame(ni, frame_vbo, pages, 9444342306fSKonstantin Komarov pages_per_frame); 9454342306fSKonstantin Komarov if (err) { 9464342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 9474342306fSKonstantin Komarov page = pages[ip]; 9484342306fSKonstantin Komarov unlock_page(page); 9494342306fSKonstantin Komarov put_page(page); 9504342306fSKonstantin Komarov } 9514342306fSKonstantin Komarov goto out; 9524342306fSKonstantin Komarov } 9534342306fSKonstantin Komarov } 9544342306fSKonstantin Komarov 9554342306fSKonstantin Komarov ip = off >> PAGE_SHIFT; 9564342306fSKonstantin Komarov off = offset_in_page(valid); 9574342306fSKonstantin Komarov for (; ip < pages_per_frame; ip++, off = 0) { 9584342306fSKonstantin Komarov page = pages[ip]; 9594342306fSKonstantin Komarov zero_user_segment(page, off, PAGE_SIZE); 9604342306fSKonstantin Komarov flush_dcache_page(page); 9614342306fSKonstantin Komarov SetPageUptodate(page); 9624342306fSKonstantin Komarov } 9634342306fSKonstantin Komarov 9644342306fSKonstantin Komarov ni_lock(ni); 9654342306fSKonstantin Komarov err = ni_write_frame(ni, pages, pages_per_frame); 9664342306fSKonstantin Komarov ni_unlock(ni); 9674342306fSKonstantin Komarov 9684342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 9694342306fSKonstantin Komarov page = pages[ip]; 9704342306fSKonstantin Komarov SetPageUptodate(page); 9714342306fSKonstantin Komarov unlock_page(page); 9724342306fSKonstantin Komarov put_page(page); 9734342306fSKonstantin Komarov } 9744342306fSKonstantin Komarov 9754342306fSKonstantin Komarov if (err) 9764342306fSKonstantin Komarov goto out; 9774342306fSKonstantin Komarov 9784342306fSKonstantin Komarov ni->i_valid = valid = frame_vbo + frame_size; 9794342306fSKonstantin Komarov } 9804342306fSKonstantin Komarov 9814342306fSKonstantin Komarov /* copy user data [pos : pos + count) */ 9824342306fSKonstantin Komarov while (count) { 9834342306fSKonstantin Komarov size_t copied, bytes; 9844342306fSKonstantin Komarov 9854342306fSKonstantin Komarov off = pos & (frame_size - 1); 9864342306fSKonstantin Komarov bytes = frame_size - off; 9874342306fSKonstantin Komarov if (bytes > count) 9884342306fSKonstantin Komarov bytes = count; 9894342306fSKonstantin Komarov 9904342306fSKonstantin Komarov frame = pos >> frame_bits; 9914342306fSKonstantin Komarov frame_vbo = pos & ~(frame_size - 1); 9924342306fSKonstantin Komarov index = frame_vbo >> PAGE_SHIFT; 9934342306fSKonstantin Komarov 9944342306fSKonstantin Komarov if (unlikely(iov_iter_fault_in_readable(from, bytes))) { 9954342306fSKonstantin Komarov err = -EFAULT; 9964342306fSKonstantin Komarov goto out; 9974342306fSKonstantin Komarov } 9984342306fSKonstantin Komarov 9994342306fSKonstantin Komarov /* Load full frame */ 10004342306fSKonstantin Komarov err = ntfs_get_frame_pages(mapping, index, pages, 10014342306fSKonstantin Komarov pages_per_frame, &frame_uptodate); 10024342306fSKonstantin Komarov if (err) 10034342306fSKonstantin Komarov goto out; 10044342306fSKonstantin Komarov 10054342306fSKonstantin Komarov if (!frame_uptodate) { 10064342306fSKonstantin Komarov loff_t to = pos + bytes; 10074342306fSKonstantin Komarov 10084342306fSKonstantin Komarov if (off || (to < i_size && (to & (frame_size - 1)))) { 10094342306fSKonstantin Komarov err = ni_read_frame(ni, frame_vbo, pages, 10104342306fSKonstantin Komarov pages_per_frame); 10114342306fSKonstantin Komarov if (err) { 10124342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; 10134342306fSKonstantin Komarov ip++) { 10144342306fSKonstantin Komarov page = pages[ip]; 10154342306fSKonstantin Komarov unlock_page(page); 10164342306fSKonstantin Komarov put_page(page); 10174342306fSKonstantin Komarov } 10184342306fSKonstantin Komarov goto out; 10194342306fSKonstantin Komarov } 10204342306fSKonstantin Komarov } 10214342306fSKonstantin Komarov } 10224342306fSKonstantin Komarov 10234342306fSKonstantin Komarov WARN_ON(!bytes); 10244342306fSKonstantin Komarov copied = 0; 10254342306fSKonstantin Komarov ip = off >> PAGE_SHIFT; 10264342306fSKonstantin Komarov off = offset_in_page(pos); 10274342306fSKonstantin Komarov 10284342306fSKonstantin Komarov /* copy user data to pages */ 10294342306fSKonstantin Komarov for (;;) { 10304342306fSKonstantin Komarov size_t cp, tail = PAGE_SIZE - off; 10314342306fSKonstantin Komarov 10324342306fSKonstantin Komarov page = pages[ip]; 10334342306fSKonstantin Komarov cp = copy_page_from_iter_atomic(page, off, 10344342306fSKonstantin Komarov min(tail, bytes), from); 10354342306fSKonstantin Komarov flush_dcache_page(page); 10364342306fSKonstantin Komarov 10374342306fSKonstantin Komarov copied += cp; 10384342306fSKonstantin Komarov bytes -= cp; 10394342306fSKonstantin Komarov if (!bytes || !cp) 10404342306fSKonstantin Komarov break; 10414342306fSKonstantin Komarov 10424342306fSKonstantin Komarov if (cp < tail) { 10434342306fSKonstantin Komarov off += cp; 10444342306fSKonstantin Komarov } else { 10454342306fSKonstantin Komarov ip++; 10464342306fSKonstantin Komarov off = 0; 10474342306fSKonstantin Komarov } 10484342306fSKonstantin Komarov } 10494342306fSKonstantin Komarov 10504342306fSKonstantin Komarov ni_lock(ni); 10514342306fSKonstantin Komarov err = ni_write_frame(ni, pages, pages_per_frame); 10524342306fSKonstantin Komarov ni_unlock(ni); 10534342306fSKonstantin Komarov 10544342306fSKonstantin Komarov for (ip = 0; ip < pages_per_frame; ip++) { 10554342306fSKonstantin Komarov page = pages[ip]; 10564342306fSKonstantin Komarov ClearPageDirty(page); 10574342306fSKonstantin Komarov SetPageUptodate(page); 10584342306fSKonstantin Komarov unlock_page(page); 10594342306fSKonstantin Komarov put_page(page); 10604342306fSKonstantin Komarov } 10614342306fSKonstantin Komarov 10624342306fSKonstantin Komarov if (err) 10634342306fSKonstantin Komarov goto out; 10644342306fSKonstantin Komarov 10654342306fSKonstantin Komarov /* 10664342306fSKonstantin Komarov * We can loop for a long time in here. Be nice and allow 10674342306fSKonstantin Komarov * us to schedule out to avoid softlocking if preempt 10684342306fSKonstantin Komarov * is disabled. 10694342306fSKonstantin Komarov */ 10704342306fSKonstantin Komarov cond_resched(); 10714342306fSKonstantin Komarov 10724342306fSKonstantin Komarov pos += copied; 10734342306fSKonstantin Komarov written += copied; 10744342306fSKonstantin Komarov 10754342306fSKonstantin Komarov count = iov_iter_count(from); 10764342306fSKonstantin Komarov } 10774342306fSKonstantin Komarov 10784342306fSKonstantin Komarov out: 1079*195c52bdSKari Argillander kfree(pages); 10804342306fSKonstantin Komarov 10814342306fSKonstantin Komarov current->backing_dev_info = NULL; 10824342306fSKonstantin Komarov 10834342306fSKonstantin Komarov if (err < 0) 10844342306fSKonstantin Komarov return err; 10854342306fSKonstantin Komarov 10864342306fSKonstantin Komarov iocb->ki_pos += written; 10874342306fSKonstantin Komarov if (iocb->ki_pos > ni->i_valid) 10884342306fSKonstantin Komarov ni->i_valid = iocb->ki_pos; 10894342306fSKonstantin Komarov 10904342306fSKonstantin Komarov return written; 10914342306fSKonstantin Komarov } 10924342306fSKonstantin Komarov 10934342306fSKonstantin Komarov /* 10944342306fSKonstantin Komarov * file_operations::write_iter 10954342306fSKonstantin Komarov */ 10964342306fSKonstantin Komarov static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 10974342306fSKonstantin Komarov { 10984342306fSKonstantin Komarov struct file *file = iocb->ki_filp; 10994342306fSKonstantin Komarov struct address_space *mapping = file->f_mapping; 11004342306fSKonstantin Komarov struct inode *inode = mapping->host; 11014342306fSKonstantin Komarov ssize_t ret; 11024342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11034342306fSKonstantin Komarov 11044342306fSKonstantin Komarov if (is_encrypted(ni)) { 11054342306fSKonstantin Komarov ntfs_inode_warn(inode, "encrypted i/o not supported"); 11064342306fSKonstantin Komarov return -EOPNOTSUPP; 11074342306fSKonstantin Komarov } 11084342306fSKonstantin Komarov 11094342306fSKonstantin Komarov if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) { 11104342306fSKonstantin Komarov ntfs_inode_warn(inode, "direct i/o + compressed not supported"); 11114342306fSKonstantin Komarov return -EOPNOTSUPP; 11124342306fSKonstantin Komarov } 11134342306fSKonstantin Komarov 11144342306fSKonstantin Komarov if (is_dedup(ni)) { 11154342306fSKonstantin Komarov ntfs_inode_warn(inode, "write into deduplicated not supported"); 11164342306fSKonstantin Komarov return -EOPNOTSUPP; 11174342306fSKonstantin Komarov } 11184342306fSKonstantin Komarov 11194342306fSKonstantin Komarov if (!inode_trylock(inode)) { 11204342306fSKonstantin Komarov if (iocb->ki_flags & IOCB_NOWAIT) 11214342306fSKonstantin Komarov return -EAGAIN; 11224342306fSKonstantin Komarov inode_lock(inode); 11234342306fSKonstantin Komarov } 11244342306fSKonstantin Komarov 11254342306fSKonstantin Komarov ret = generic_write_checks(iocb, from); 11264342306fSKonstantin Komarov if (ret <= 0) 11274342306fSKonstantin Komarov goto out; 11284342306fSKonstantin Komarov 11294342306fSKonstantin Komarov if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) { 11304342306fSKonstantin Komarov /* should never be here, see ntfs_file_open*/ 11314342306fSKonstantin Komarov ret = -EOPNOTSUPP; 11324342306fSKonstantin Komarov goto out; 11334342306fSKonstantin Komarov } 11344342306fSKonstantin Komarov 11354342306fSKonstantin Komarov ret = ntfs_extend(inode, iocb->ki_pos, ret, file); 11364342306fSKonstantin Komarov if (ret) 11374342306fSKonstantin Komarov goto out; 11384342306fSKonstantin Komarov 11394342306fSKonstantin Komarov ret = is_compressed(ni) ? ntfs_compress_write(iocb, from) 11404342306fSKonstantin Komarov : __generic_file_write_iter(iocb, from); 11414342306fSKonstantin Komarov 11424342306fSKonstantin Komarov out: 11434342306fSKonstantin Komarov inode_unlock(inode); 11444342306fSKonstantin Komarov 11454342306fSKonstantin Komarov if (ret > 0) 11464342306fSKonstantin Komarov ret = generic_write_sync(iocb, ret); 11474342306fSKonstantin Komarov 11484342306fSKonstantin Komarov return ret; 11494342306fSKonstantin Komarov } 11504342306fSKonstantin Komarov 11514342306fSKonstantin Komarov /* 11524342306fSKonstantin Komarov * file_operations::open 11534342306fSKonstantin Komarov */ 11544342306fSKonstantin Komarov int ntfs_file_open(struct inode *inode, struct file *file) 11554342306fSKonstantin Komarov { 11564342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11574342306fSKonstantin Komarov 11584342306fSKonstantin Komarov if (unlikely((is_compressed(ni) || is_encrypted(ni)) && 11594342306fSKonstantin Komarov (file->f_flags & O_DIRECT))) { 11604342306fSKonstantin Komarov return -EOPNOTSUPP; 11614342306fSKonstantin Komarov } 11624342306fSKonstantin Komarov 11634342306fSKonstantin Komarov /* Decompress "external compressed" file if opened for rw */ 11644342306fSKonstantin Komarov if ((ni->ni_flags & NI_FLAG_COMPRESSED_MASK) && 11654342306fSKonstantin Komarov (file->f_flags & (O_WRONLY | O_RDWR | O_TRUNC))) { 11664342306fSKonstantin Komarov #ifdef CONFIG_NTFS3_LZX_XPRESS 11674342306fSKonstantin Komarov int err = ni_decompress_file(ni); 11684342306fSKonstantin Komarov 11694342306fSKonstantin Komarov if (err) 11704342306fSKonstantin Komarov return err; 11714342306fSKonstantin Komarov #else 11724342306fSKonstantin Komarov ntfs_inode_warn( 11734342306fSKonstantin Komarov inode, 11744342306fSKonstantin Komarov "activate CONFIG_NTFS3_LZX_XPRESS to write external compressed files"); 11754342306fSKonstantin Komarov return -EOPNOTSUPP; 11764342306fSKonstantin Komarov #endif 11774342306fSKonstantin Komarov } 11784342306fSKonstantin Komarov 11794342306fSKonstantin Komarov return generic_file_open(inode, file); 11804342306fSKonstantin Komarov } 11814342306fSKonstantin Komarov 11824342306fSKonstantin Komarov /* 11834342306fSKonstantin Komarov * file_operations::release 11844342306fSKonstantin Komarov */ 11854342306fSKonstantin Komarov static int ntfs_file_release(struct inode *inode, struct file *file) 11864342306fSKonstantin Komarov { 11874342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 11884342306fSKonstantin Komarov struct ntfs_sb_info *sbi = ni->mi.sbi; 11894342306fSKonstantin Komarov int err = 0; 11904342306fSKonstantin Komarov 11914342306fSKonstantin Komarov /* if we are the last writer on the inode, drop the block reservation */ 11924342306fSKonstantin Komarov if (sbi->options.prealloc && ((file->f_mode & FMODE_WRITE) && 11934342306fSKonstantin Komarov atomic_read(&inode->i_writecount) == 1)) { 11944342306fSKonstantin Komarov ni_lock(ni); 11954342306fSKonstantin Komarov down_write(&ni->file.run_lock); 11964342306fSKonstantin Komarov 11974342306fSKonstantin Komarov err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, 11984342306fSKonstantin Komarov inode->i_size, &ni->i_valid, false, NULL); 11994342306fSKonstantin Komarov 12004342306fSKonstantin Komarov up_write(&ni->file.run_lock); 12014342306fSKonstantin Komarov ni_unlock(ni); 12024342306fSKonstantin Komarov } 12034342306fSKonstantin Komarov return err; 12044342306fSKonstantin Komarov } 12054342306fSKonstantin Komarov 12064342306fSKonstantin Komarov /* file_operations::fiemap */ 12074342306fSKonstantin Komarov int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 12084342306fSKonstantin Komarov __u64 start, __u64 len) 12094342306fSKonstantin Komarov { 12104342306fSKonstantin Komarov int err; 12114342306fSKonstantin Komarov struct ntfs_inode *ni = ntfs_i(inode); 12124342306fSKonstantin Komarov 12134342306fSKonstantin Komarov if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) 12144342306fSKonstantin Komarov return -EOPNOTSUPP; 12154342306fSKonstantin Komarov 12164342306fSKonstantin Komarov ni_lock(ni); 12174342306fSKonstantin Komarov 12184342306fSKonstantin Komarov err = ni_fiemap(ni, fieinfo, start, len); 12194342306fSKonstantin Komarov 12204342306fSKonstantin Komarov ni_unlock(ni); 12214342306fSKonstantin Komarov 12224342306fSKonstantin Komarov return err; 12234342306fSKonstantin Komarov } 12244342306fSKonstantin Komarov 12254342306fSKonstantin Komarov // clang-format off 12264342306fSKonstantin Komarov const struct inode_operations ntfs_file_inode_operations = { 12274342306fSKonstantin Komarov .getattr = ntfs_getattr, 12284342306fSKonstantin Komarov .setattr = ntfs3_setattr, 12294342306fSKonstantin Komarov .listxattr = ntfs_listxattr, 12304342306fSKonstantin Komarov .permission = ntfs_permission, 12314342306fSKonstantin Komarov .get_acl = ntfs_get_acl, 12324342306fSKonstantin Komarov .set_acl = ntfs_set_acl, 12334342306fSKonstantin Komarov .fiemap = ntfs_fiemap, 12344342306fSKonstantin Komarov }; 12354342306fSKonstantin Komarov 12364342306fSKonstantin Komarov const struct file_operations ntfs_file_operations = { 12374342306fSKonstantin Komarov .llseek = generic_file_llseek, 12384342306fSKonstantin Komarov .read_iter = ntfs_file_read_iter, 12394342306fSKonstantin Komarov .write_iter = ntfs_file_write_iter, 12404342306fSKonstantin Komarov .unlocked_ioctl = ntfs_ioctl, 12414342306fSKonstantin Komarov #ifdef CONFIG_COMPAT 12424342306fSKonstantin Komarov .compat_ioctl = ntfs_compat_ioctl, 12434342306fSKonstantin Komarov #endif 12444342306fSKonstantin Komarov .splice_read = generic_file_splice_read, 12454342306fSKonstantin Komarov .mmap = ntfs_file_mmap, 12464342306fSKonstantin Komarov .open = ntfs_file_open, 12474342306fSKonstantin Komarov .fsync = generic_file_fsync, 12484342306fSKonstantin Komarov .splice_write = iter_file_splice_write, 12494342306fSKonstantin Komarov .fallocate = ntfs_fallocate, 12504342306fSKonstantin Komarov .release = ntfs_file_release, 12514342306fSKonstantin Komarov }; 12524342306fSKonstantin Komarov // clang-format on 1253