18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * file.c - NTFS kernel file operations. Part of the Linux-NTFS project. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2001-2015 Anton Altaparmakov and Tuxera Inc. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 98c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 108c2ecf20Sopenharmony_ci#include <linux/gfp.h> 118c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 128c2ecf20Sopenharmony_ci#include <linux/pagevec.h> 138c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 148c2ecf20Sopenharmony_ci#include <linux/swap.h> 158c2ecf20Sopenharmony_ci#include <linux/uio.h> 168c2ecf20Sopenharmony_ci#include <linux/writeback.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/page.h> 198c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "attrib.h" 228c2ecf20Sopenharmony_ci#include "bitmap.h" 238c2ecf20Sopenharmony_ci#include "inode.h" 248c2ecf20Sopenharmony_ci#include "debug.h" 258c2ecf20Sopenharmony_ci#include "lcnalloc.h" 268c2ecf20Sopenharmony_ci#include "malloc.h" 278c2ecf20Sopenharmony_ci#include "mft.h" 288c2ecf20Sopenharmony_ci#include "ntfs.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/** 318c2ecf20Sopenharmony_ci * ntfs_file_open - called when an inode is about to be opened 328c2ecf20Sopenharmony_ci * @vi: inode to be opened 338c2ecf20Sopenharmony_ci * @filp: file structure describing the inode 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * Limit file size to the page cache limit on architectures where unsigned long 368c2ecf20Sopenharmony_ci * is 32-bits. This is the most we can do for now without overflowing the page 378c2ecf20Sopenharmony_ci * cache page index. Doing it this way means we don't run into problems because 388c2ecf20Sopenharmony_ci * of existing too large files. It would be better to allow the user to read 398c2ecf20Sopenharmony_ci * the beginning of the file but I doubt very much anyone is going to hit this 408c2ecf20Sopenharmony_ci * check on a 32-bit architecture, so there is no point in adding the extra 418c2ecf20Sopenharmony_ci * complexity required to support this. 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * On 64-bit architectures, the check is hopefully optimized away by the 448c2ecf20Sopenharmony_ci * compiler. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * After the check passes, just call generic_file_open() to do its work. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_cistatic int ntfs_file_open(struct inode *vi, struct file *filp) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci if (sizeof(unsigned long) < 8) { 518c2ecf20Sopenharmony_ci if (i_size_read(vi) > MAX_LFS_FILESIZE) 528c2ecf20Sopenharmony_ci return -EOVERFLOW; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci return generic_file_open(vi, filp); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#ifdef NTFS_RW 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/** 608c2ecf20Sopenharmony_ci * ntfs_attr_extend_initialized - extend the initialized size of an attribute 618c2ecf20Sopenharmony_ci * @ni: ntfs inode of the attribute to extend 628c2ecf20Sopenharmony_ci * @new_init_size: requested new initialized size in bytes 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * Extend the initialized size of an attribute described by the ntfs inode @ni 658c2ecf20Sopenharmony_ci * to @new_init_size bytes. This involves zeroing any non-sparse space between 668c2ecf20Sopenharmony_ci * the old initialized size and @new_init_size both in the page cache and on 678c2ecf20Sopenharmony_ci * disk (if relevant complete pages are already uptodate in the page cache then 688c2ecf20Sopenharmony_ci * these are simply marked dirty). 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * As a side-effect, the file size (vfs inode->i_size) may be incremented as, 718c2ecf20Sopenharmony_ci * in the resident attribute case, it is tied to the initialized size and, in 728c2ecf20Sopenharmony_ci * the non-resident attribute case, it may not fall below the initialized size. 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * Note that if the attribute is resident, we do not need to touch the page 758c2ecf20Sopenharmony_ci * cache at all. This is because if the page cache page is not uptodate we 768c2ecf20Sopenharmony_ci * bring it uptodate later, when doing the write to the mft record since we 778c2ecf20Sopenharmony_ci * then already have the page mapped. And if the page is uptodate, the 788c2ecf20Sopenharmony_ci * non-initialized region will already have been zeroed when the page was 798c2ecf20Sopenharmony_ci * brought uptodate and the region may in fact already have been overwritten 808c2ecf20Sopenharmony_ci * with new data via mmap() based writes, so we cannot just zero it. And since 818c2ecf20Sopenharmony_ci * POSIX specifies that the behaviour of resizing a file whilst it is mmap()ped 828c2ecf20Sopenharmony_ci * is unspecified, we choose not to do zeroing and thus we do not need to touch 838c2ecf20Sopenharmony_ci * the page at all. For a more detailed explanation see ntfs_truncate() in 848c2ecf20Sopenharmony_ci * fs/ntfs/inode.c. 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error. In the case that an error is 878c2ecf20Sopenharmony_ci * encountered it is possible that the initialized size will already have been 888c2ecf20Sopenharmony_ci * incremented some way towards @new_init_size but it is guaranteed that if 898c2ecf20Sopenharmony_ci * this is the case, the necessary zeroing will also have happened and that all 908c2ecf20Sopenharmony_ci * metadata is self-consistent. 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * Locking: i_mutex on the vfs inode corrseponsind to the ntfs inode @ni must be 938c2ecf20Sopenharmony_ci * held by the caller. 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_cistatic int ntfs_attr_extend_initialized(ntfs_inode *ni, const s64 new_init_size) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci s64 old_init_size; 988c2ecf20Sopenharmony_ci loff_t old_i_size; 998c2ecf20Sopenharmony_ci pgoff_t index, end_index; 1008c2ecf20Sopenharmony_ci unsigned long flags; 1018c2ecf20Sopenharmony_ci struct inode *vi = VFS_I(ni); 1028c2ecf20Sopenharmony_ci ntfs_inode *base_ni; 1038c2ecf20Sopenharmony_ci MFT_RECORD *m = NULL; 1048c2ecf20Sopenharmony_ci ATTR_RECORD *a; 1058c2ecf20Sopenharmony_ci ntfs_attr_search_ctx *ctx = NULL; 1068c2ecf20Sopenharmony_ci struct address_space *mapping; 1078c2ecf20Sopenharmony_ci struct page *page = NULL; 1088c2ecf20Sopenharmony_ci u8 *kattr; 1098c2ecf20Sopenharmony_ci int err; 1108c2ecf20Sopenharmony_ci u32 attr_len; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 1138c2ecf20Sopenharmony_ci old_init_size = ni->initialized_size; 1148c2ecf20Sopenharmony_ci old_i_size = i_size_read(vi); 1158c2ecf20Sopenharmony_ci BUG_ON(new_init_size > ni->allocated_size); 1168c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 1178c2ecf20Sopenharmony_ci ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, " 1188c2ecf20Sopenharmony_ci "old_initialized_size 0x%llx, " 1198c2ecf20Sopenharmony_ci "new_initialized_size 0x%llx, i_size 0x%llx.", 1208c2ecf20Sopenharmony_ci vi->i_ino, (unsigned)le32_to_cpu(ni->type), 1218c2ecf20Sopenharmony_ci (unsigned long long)old_init_size, 1228c2ecf20Sopenharmony_ci (unsigned long long)new_init_size, old_i_size); 1238c2ecf20Sopenharmony_ci if (!NInoAttr(ni)) 1248c2ecf20Sopenharmony_ci base_ni = ni; 1258c2ecf20Sopenharmony_ci else 1268c2ecf20Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 1278c2ecf20Sopenharmony_ci /* Use goto to reduce indentation and we need the label below anyway. */ 1288c2ecf20Sopenharmony_ci if (NInoNonResident(ni)) 1298c2ecf20Sopenharmony_ci goto do_non_resident_extend; 1308c2ecf20Sopenharmony_ci BUG_ON(old_init_size != old_i_size); 1318c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 1328c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 1338c2ecf20Sopenharmony_ci err = PTR_ERR(m); 1348c2ecf20Sopenharmony_ci m = NULL; 1358c2ecf20Sopenharmony_ci goto err_out; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 1388c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 1398c2ecf20Sopenharmony_ci err = -ENOMEM; 1408c2ecf20Sopenharmony_ci goto err_out; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 1438c2ecf20Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 1448c2ecf20Sopenharmony_ci if (unlikely(err)) { 1458c2ecf20Sopenharmony_ci if (err == -ENOENT) 1468c2ecf20Sopenharmony_ci err = -EIO; 1478c2ecf20Sopenharmony_ci goto err_out; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci m = ctx->mrec; 1508c2ecf20Sopenharmony_ci a = ctx->attr; 1518c2ecf20Sopenharmony_ci BUG_ON(a->non_resident); 1528c2ecf20Sopenharmony_ci /* The total length of the attribute value. */ 1538c2ecf20Sopenharmony_ci attr_len = le32_to_cpu(a->data.resident.value_length); 1548c2ecf20Sopenharmony_ci BUG_ON(old_i_size != (loff_t)attr_len); 1558c2ecf20Sopenharmony_ci /* 1568c2ecf20Sopenharmony_ci * Do the zeroing in the mft record and update the attribute size in 1578c2ecf20Sopenharmony_ci * the mft record. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset); 1608c2ecf20Sopenharmony_ci memset(kattr + attr_len, 0, new_init_size - attr_len); 1618c2ecf20Sopenharmony_ci a->data.resident.value_length = cpu_to_le32((u32)new_init_size); 1628c2ecf20Sopenharmony_ci /* Finally, update the sizes in the vfs and ntfs inodes. */ 1638c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 1648c2ecf20Sopenharmony_ci i_size_write(vi, new_init_size); 1658c2ecf20Sopenharmony_ci ni->initialized_size = new_init_size; 1668c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 1678c2ecf20Sopenharmony_ci goto done; 1688c2ecf20Sopenharmony_cido_non_resident_extend: 1698c2ecf20Sopenharmony_ci /* 1708c2ecf20Sopenharmony_ci * If the new initialized size @new_init_size exceeds the current file 1718c2ecf20Sopenharmony_ci * size (vfs inode->i_size), we need to extend the file size to the 1728c2ecf20Sopenharmony_ci * new initialized size. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ci if (new_init_size > old_i_size) { 1758c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 1768c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 1778c2ecf20Sopenharmony_ci err = PTR_ERR(m); 1788c2ecf20Sopenharmony_ci m = NULL; 1798c2ecf20Sopenharmony_ci goto err_out; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 1828c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 1838c2ecf20Sopenharmony_ci err = -ENOMEM; 1848c2ecf20Sopenharmony_ci goto err_out; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 1878c2ecf20Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 1888c2ecf20Sopenharmony_ci if (unlikely(err)) { 1898c2ecf20Sopenharmony_ci if (err == -ENOENT) 1908c2ecf20Sopenharmony_ci err = -EIO; 1918c2ecf20Sopenharmony_ci goto err_out; 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci m = ctx->mrec; 1948c2ecf20Sopenharmony_ci a = ctx->attr; 1958c2ecf20Sopenharmony_ci BUG_ON(!a->non_resident); 1968c2ecf20Sopenharmony_ci BUG_ON(old_i_size != (loff_t) 1978c2ecf20Sopenharmony_ci sle64_to_cpu(a->data.non_resident.data_size)); 1988c2ecf20Sopenharmony_ci a->data.non_resident.data_size = cpu_to_sle64(new_init_size); 1998c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 2008c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 2018c2ecf20Sopenharmony_ci /* Update the file size in the vfs inode. */ 2028c2ecf20Sopenharmony_ci i_size_write(vi, new_init_size); 2038c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 2048c2ecf20Sopenharmony_ci ctx = NULL; 2058c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 2068c2ecf20Sopenharmony_ci m = NULL; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci mapping = vi->i_mapping; 2098c2ecf20Sopenharmony_ci index = old_init_size >> PAGE_SHIFT; 2108c2ecf20Sopenharmony_ci end_index = (new_init_size + PAGE_SIZE - 1) >> PAGE_SHIFT; 2118c2ecf20Sopenharmony_ci do { 2128c2ecf20Sopenharmony_ci /* 2138c2ecf20Sopenharmony_ci * Read the page. If the page is not present, this will zero 2148c2ecf20Sopenharmony_ci * the uninitialized regions for us. 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_ci page = read_mapping_page(mapping, index, NULL); 2178c2ecf20Sopenharmony_ci if (IS_ERR(page)) { 2188c2ecf20Sopenharmony_ci err = PTR_ERR(page); 2198c2ecf20Sopenharmony_ci goto init_err_out; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci if (unlikely(PageError(page))) { 2228c2ecf20Sopenharmony_ci put_page(page); 2238c2ecf20Sopenharmony_ci err = -EIO; 2248c2ecf20Sopenharmony_ci goto init_err_out; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci /* 2278c2ecf20Sopenharmony_ci * Update the initialized size in the ntfs inode. This is 2288c2ecf20Sopenharmony_ci * enough to make ntfs_writepage() work. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 2318c2ecf20Sopenharmony_ci ni->initialized_size = (s64)(index + 1) << PAGE_SHIFT; 2328c2ecf20Sopenharmony_ci if (ni->initialized_size > new_init_size) 2338c2ecf20Sopenharmony_ci ni->initialized_size = new_init_size; 2348c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 2358c2ecf20Sopenharmony_ci /* Set the page dirty so it gets written out. */ 2368c2ecf20Sopenharmony_ci set_page_dirty(page); 2378c2ecf20Sopenharmony_ci put_page(page); 2388c2ecf20Sopenharmony_ci /* 2398c2ecf20Sopenharmony_ci * Play nice with the vm and the rest of the system. This is 2408c2ecf20Sopenharmony_ci * very much needed as we can potentially be modifying the 2418c2ecf20Sopenharmony_ci * initialised size from a very small value to a really huge 2428c2ecf20Sopenharmony_ci * value, e.g. 2438c2ecf20Sopenharmony_ci * f = open(somefile, O_TRUNC); 2448c2ecf20Sopenharmony_ci * truncate(f, 10GiB); 2458c2ecf20Sopenharmony_ci * seek(f, 10GiB); 2468c2ecf20Sopenharmony_ci * write(f, 1); 2478c2ecf20Sopenharmony_ci * And this would mean we would be marking dirty hundreds of 2488c2ecf20Sopenharmony_ci * thousands of pages or as in the above example more than 2498c2ecf20Sopenharmony_ci * two and a half million pages! 2508c2ecf20Sopenharmony_ci * 2518c2ecf20Sopenharmony_ci * TODO: For sparse pages could optimize this workload by using 2528c2ecf20Sopenharmony_ci * the FsMisc / MiscFs page bit as a "PageIsSparse" bit. This 2538c2ecf20Sopenharmony_ci * would be set in readpage for sparse pages and here we would 2548c2ecf20Sopenharmony_ci * not need to mark dirty any pages which have this bit set. 2558c2ecf20Sopenharmony_ci * The only caveat is that we have to clear the bit everywhere 2568c2ecf20Sopenharmony_ci * where we allocate any clusters that lie in the page or that 2578c2ecf20Sopenharmony_ci * contain the page. 2588c2ecf20Sopenharmony_ci * 2598c2ecf20Sopenharmony_ci * TODO: An even greater optimization would be for us to only 2608c2ecf20Sopenharmony_ci * call readpage() on pages which are not in sparse regions as 2618c2ecf20Sopenharmony_ci * determined from the runlist. This would greatly reduce the 2628c2ecf20Sopenharmony_ci * number of pages we read and make dirty in the case of sparse 2638c2ecf20Sopenharmony_ci * files. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ci balance_dirty_pages_ratelimited(mapping); 2668c2ecf20Sopenharmony_ci cond_resched(); 2678c2ecf20Sopenharmony_ci } while (++index < end_index); 2688c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 2698c2ecf20Sopenharmony_ci BUG_ON(ni->initialized_size != new_init_size); 2708c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 2718c2ecf20Sopenharmony_ci /* Now bring in sync the initialized_size in the mft record. */ 2728c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 2738c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 2748c2ecf20Sopenharmony_ci err = PTR_ERR(m); 2758c2ecf20Sopenharmony_ci m = NULL; 2768c2ecf20Sopenharmony_ci goto init_err_out; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 2798c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 2808c2ecf20Sopenharmony_ci err = -ENOMEM; 2818c2ecf20Sopenharmony_ci goto init_err_out; 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 2848c2ecf20Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 2858c2ecf20Sopenharmony_ci if (unlikely(err)) { 2868c2ecf20Sopenharmony_ci if (err == -ENOENT) 2878c2ecf20Sopenharmony_ci err = -EIO; 2888c2ecf20Sopenharmony_ci goto init_err_out; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci m = ctx->mrec; 2918c2ecf20Sopenharmony_ci a = ctx->attr; 2928c2ecf20Sopenharmony_ci BUG_ON(!a->non_resident); 2938c2ecf20Sopenharmony_ci a->data.non_resident.initialized_size = cpu_to_sle64(new_init_size); 2948c2ecf20Sopenharmony_cidone: 2958c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 2968c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 2978c2ecf20Sopenharmony_ci if (ctx) 2988c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 2998c2ecf20Sopenharmony_ci if (m) 3008c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 3018c2ecf20Sopenharmony_ci ntfs_debug("Done, initialized_size 0x%llx, i_size 0x%llx.", 3028c2ecf20Sopenharmony_ci (unsigned long long)new_init_size, i_size_read(vi)); 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ciinit_err_out: 3058c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 3068c2ecf20Sopenharmony_ci ni->initialized_size = old_init_size; 3078c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 3088c2ecf20Sopenharmony_cierr_out: 3098c2ecf20Sopenharmony_ci if (ctx) 3108c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 3118c2ecf20Sopenharmony_ci if (m) 3128c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 3138c2ecf20Sopenharmony_ci ntfs_debug("Failed. Returning error code %i.", err); 3148c2ecf20Sopenharmony_ci return err; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic ssize_t ntfs_prepare_file_for_write(struct kiocb *iocb, 3188c2ecf20Sopenharmony_ci struct iov_iter *from) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci loff_t pos; 3218c2ecf20Sopenharmony_ci s64 end, ll; 3228c2ecf20Sopenharmony_ci ssize_t err; 3238c2ecf20Sopenharmony_ci unsigned long flags; 3248c2ecf20Sopenharmony_ci struct file *file = iocb->ki_filp; 3258c2ecf20Sopenharmony_ci struct inode *vi = file_inode(file); 3268c2ecf20Sopenharmony_ci ntfs_inode *base_ni, *ni = NTFS_I(vi); 3278c2ecf20Sopenharmony_ci ntfs_volume *vol = ni->vol; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos " 3308c2ecf20Sopenharmony_ci "0x%llx, count 0x%zx.", vi->i_ino, 3318c2ecf20Sopenharmony_ci (unsigned)le32_to_cpu(ni->type), 3328c2ecf20Sopenharmony_ci (unsigned long long)iocb->ki_pos, 3338c2ecf20Sopenharmony_ci iov_iter_count(from)); 3348c2ecf20Sopenharmony_ci err = generic_write_checks(iocb, from); 3358c2ecf20Sopenharmony_ci if (unlikely(err <= 0)) 3368c2ecf20Sopenharmony_ci goto out; 3378c2ecf20Sopenharmony_ci /* 3388c2ecf20Sopenharmony_ci * All checks have passed. Before we start doing any writing we want 3398c2ecf20Sopenharmony_ci * to abort any totally illegal writes. 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci BUG_ON(NInoMstProtected(ni)); 3428c2ecf20Sopenharmony_ci BUG_ON(ni->type != AT_DATA); 3438c2ecf20Sopenharmony_ci /* If file is encrypted, deny access, just like NT4. */ 3448c2ecf20Sopenharmony_ci if (NInoEncrypted(ni)) { 3458c2ecf20Sopenharmony_ci /* Only $DATA attributes can be encrypted. */ 3468c2ecf20Sopenharmony_ci /* 3478c2ecf20Sopenharmony_ci * Reminder for later: Encrypted files are _always_ 3488c2ecf20Sopenharmony_ci * non-resident so that the content can always be encrypted. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci ntfs_debug("Denying write access to encrypted file."); 3518c2ecf20Sopenharmony_ci err = -EACCES; 3528c2ecf20Sopenharmony_ci goto out; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci if (NInoCompressed(ni)) { 3558c2ecf20Sopenharmony_ci /* Only unnamed $DATA attribute can be compressed. */ 3568c2ecf20Sopenharmony_ci BUG_ON(ni->name_len); 3578c2ecf20Sopenharmony_ci /* 3588c2ecf20Sopenharmony_ci * Reminder for later: If resident, the data is not actually 3598c2ecf20Sopenharmony_ci * compressed. Only on the switch to non-resident does 3608c2ecf20Sopenharmony_ci * compression kick in. This is in contrast to encrypted files 3618c2ecf20Sopenharmony_ci * (see above). 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Writing to compressed files is not " 3648c2ecf20Sopenharmony_ci "implemented yet. Sorry."); 3658c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 3668c2ecf20Sopenharmony_ci goto out; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci base_ni = ni; 3698c2ecf20Sopenharmony_ci if (NInoAttr(ni)) 3708c2ecf20Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 3718c2ecf20Sopenharmony_ci err = file_remove_privs(file); 3728c2ecf20Sopenharmony_ci if (unlikely(err)) 3738c2ecf20Sopenharmony_ci goto out; 3748c2ecf20Sopenharmony_ci /* 3758c2ecf20Sopenharmony_ci * Our ->update_time method always succeeds thus file_update_time() 3768c2ecf20Sopenharmony_ci * cannot fail either so there is no need to check the return code. 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_ci file_update_time(file); 3798c2ecf20Sopenharmony_ci pos = iocb->ki_pos; 3808c2ecf20Sopenharmony_ci /* The first byte after the last cluster being written to. */ 3818c2ecf20Sopenharmony_ci end = (pos + iov_iter_count(from) + vol->cluster_size_mask) & 3828c2ecf20Sopenharmony_ci ~(u64)vol->cluster_size_mask; 3838c2ecf20Sopenharmony_ci /* 3848c2ecf20Sopenharmony_ci * If the write goes beyond the allocated size, extend the allocation 3858c2ecf20Sopenharmony_ci * to cover the whole of the write, rounded up to the nearest cluster. 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 3888c2ecf20Sopenharmony_ci ll = ni->allocated_size; 3898c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 3908c2ecf20Sopenharmony_ci if (end > ll) { 3918c2ecf20Sopenharmony_ci /* 3928c2ecf20Sopenharmony_ci * Extend the allocation without changing the data size. 3938c2ecf20Sopenharmony_ci * 3948c2ecf20Sopenharmony_ci * Note we ensure the allocation is big enough to at least 3958c2ecf20Sopenharmony_ci * write some data but we do not require the allocation to be 3968c2ecf20Sopenharmony_ci * complete, i.e. it may be partial. 3978c2ecf20Sopenharmony_ci */ 3988c2ecf20Sopenharmony_ci ll = ntfs_attr_extend_allocation(ni, end, -1, pos); 3998c2ecf20Sopenharmony_ci if (likely(ll >= 0)) { 4008c2ecf20Sopenharmony_ci BUG_ON(pos >= ll); 4018c2ecf20Sopenharmony_ci /* If the extension was partial truncate the write. */ 4028c2ecf20Sopenharmony_ci if (end > ll) { 4038c2ecf20Sopenharmony_ci ntfs_debug("Truncating write to inode 0x%lx, " 4048c2ecf20Sopenharmony_ci "attribute type 0x%x, because " 4058c2ecf20Sopenharmony_ci "the allocation was only " 4068c2ecf20Sopenharmony_ci "partially extended.", 4078c2ecf20Sopenharmony_ci vi->i_ino, (unsigned) 4088c2ecf20Sopenharmony_ci le32_to_cpu(ni->type)); 4098c2ecf20Sopenharmony_ci iov_iter_truncate(from, ll - pos); 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } else { 4128c2ecf20Sopenharmony_ci err = ll; 4138c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 4148c2ecf20Sopenharmony_ci ll = ni->allocated_size; 4158c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 4168c2ecf20Sopenharmony_ci /* Perform a partial write if possible or fail. */ 4178c2ecf20Sopenharmony_ci if (pos < ll) { 4188c2ecf20Sopenharmony_ci ntfs_debug("Truncating write to inode 0x%lx " 4198c2ecf20Sopenharmony_ci "attribute type 0x%x, because " 4208c2ecf20Sopenharmony_ci "extending the allocation " 4218c2ecf20Sopenharmony_ci "failed (error %d).", 4228c2ecf20Sopenharmony_ci vi->i_ino, (unsigned) 4238c2ecf20Sopenharmony_ci le32_to_cpu(ni->type), 4248c2ecf20Sopenharmony_ci (int)-err); 4258c2ecf20Sopenharmony_ci iov_iter_truncate(from, ll - pos); 4268c2ecf20Sopenharmony_ci } else { 4278c2ecf20Sopenharmony_ci if (err != -ENOSPC) 4288c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Cannot perform " 4298c2ecf20Sopenharmony_ci "write to inode " 4308c2ecf20Sopenharmony_ci "0x%lx, attribute " 4318c2ecf20Sopenharmony_ci "type 0x%x, because " 4328c2ecf20Sopenharmony_ci "extending the " 4338c2ecf20Sopenharmony_ci "allocation failed " 4348c2ecf20Sopenharmony_ci "(error %ld).", 4358c2ecf20Sopenharmony_ci vi->i_ino, (unsigned) 4368c2ecf20Sopenharmony_ci le32_to_cpu(ni->type), 4378c2ecf20Sopenharmony_ci (long)-err); 4388c2ecf20Sopenharmony_ci else 4398c2ecf20Sopenharmony_ci ntfs_debug("Cannot perform write to " 4408c2ecf20Sopenharmony_ci "inode 0x%lx, " 4418c2ecf20Sopenharmony_ci "attribute type 0x%x, " 4428c2ecf20Sopenharmony_ci "because there is not " 4438c2ecf20Sopenharmony_ci "space left.", 4448c2ecf20Sopenharmony_ci vi->i_ino, (unsigned) 4458c2ecf20Sopenharmony_ci le32_to_cpu(ni->type)); 4468c2ecf20Sopenharmony_ci goto out; 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci /* 4518c2ecf20Sopenharmony_ci * If the write starts beyond the initialized size, extend it up to the 4528c2ecf20Sopenharmony_ci * beginning of the write and initialize all non-sparse space between 4538c2ecf20Sopenharmony_ci * the old initialized size and the new one. This automatically also 4548c2ecf20Sopenharmony_ci * increments the vfs inode->i_size to keep it above or equal to the 4558c2ecf20Sopenharmony_ci * initialized_size. 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 4588c2ecf20Sopenharmony_ci ll = ni->initialized_size; 4598c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 4608c2ecf20Sopenharmony_ci if (pos > ll) { 4618c2ecf20Sopenharmony_ci /* 4628c2ecf20Sopenharmony_ci * Wait for ongoing direct i/o to complete before proceeding. 4638c2ecf20Sopenharmony_ci * New direct i/o cannot start as we hold i_mutex. 4648c2ecf20Sopenharmony_ci */ 4658c2ecf20Sopenharmony_ci inode_dio_wait(vi); 4668c2ecf20Sopenharmony_ci err = ntfs_attr_extend_initialized(ni, pos); 4678c2ecf20Sopenharmony_ci if (unlikely(err < 0)) 4688c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Cannot perform write to inode " 4698c2ecf20Sopenharmony_ci "0x%lx, attribute type 0x%x, because " 4708c2ecf20Sopenharmony_ci "extending the initialized size " 4718c2ecf20Sopenharmony_ci "failed (error %d).", vi->i_ino, 4728c2ecf20Sopenharmony_ci (unsigned)le32_to_cpu(ni->type), 4738c2ecf20Sopenharmony_ci (int)-err); 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ciout: 4768c2ecf20Sopenharmony_ci return err; 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci/** 4808c2ecf20Sopenharmony_ci * __ntfs_grab_cache_pages - obtain a number of locked pages 4818c2ecf20Sopenharmony_ci * @mapping: address space mapping from which to obtain page cache pages 4828c2ecf20Sopenharmony_ci * @index: starting index in @mapping at which to begin obtaining pages 4838c2ecf20Sopenharmony_ci * @nr_pages: number of page cache pages to obtain 4848c2ecf20Sopenharmony_ci * @pages: array of pages in which to return the obtained page cache pages 4858c2ecf20Sopenharmony_ci * @cached_page: allocated but as yet unused page 4868c2ecf20Sopenharmony_ci * 4878c2ecf20Sopenharmony_ci * Obtain @nr_pages locked page cache pages from the mapping @mapping and 4888c2ecf20Sopenharmony_ci * starting at index @index. 4898c2ecf20Sopenharmony_ci * 4908c2ecf20Sopenharmony_ci * If a page is newly created, add it to lru list 4918c2ecf20Sopenharmony_ci * 4928c2ecf20Sopenharmony_ci * Note, the page locks are obtained in ascending page index order. 4938c2ecf20Sopenharmony_ci */ 4948c2ecf20Sopenharmony_cistatic inline int __ntfs_grab_cache_pages(struct address_space *mapping, 4958c2ecf20Sopenharmony_ci pgoff_t index, const unsigned nr_pages, struct page **pages, 4968c2ecf20Sopenharmony_ci struct page **cached_page) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci int err, nr; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci BUG_ON(!nr_pages); 5018c2ecf20Sopenharmony_ci err = nr = 0; 5028c2ecf20Sopenharmony_ci do { 5038c2ecf20Sopenharmony_ci pages[nr] = find_get_page_flags(mapping, index, FGP_LOCK | 5048c2ecf20Sopenharmony_ci FGP_ACCESSED); 5058c2ecf20Sopenharmony_ci if (!pages[nr]) { 5068c2ecf20Sopenharmony_ci if (!*cached_page) { 5078c2ecf20Sopenharmony_ci *cached_page = page_cache_alloc(mapping); 5088c2ecf20Sopenharmony_ci if (unlikely(!*cached_page)) { 5098c2ecf20Sopenharmony_ci err = -ENOMEM; 5108c2ecf20Sopenharmony_ci goto err_out; 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci err = add_to_page_cache_lru(*cached_page, mapping, 5148c2ecf20Sopenharmony_ci index, 5158c2ecf20Sopenharmony_ci mapping_gfp_constraint(mapping, GFP_KERNEL)); 5168c2ecf20Sopenharmony_ci if (unlikely(err)) { 5178c2ecf20Sopenharmony_ci if (err == -EEXIST) 5188c2ecf20Sopenharmony_ci continue; 5198c2ecf20Sopenharmony_ci goto err_out; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci pages[nr] = *cached_page; 5228c2ecf20Sopenharmony_ci *cached_page = NULL; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci index++; 5258c2ecf20Sopenharmony_ci nr++; 5268c2ecf20Sopenharmony_ci } while (nr < nr_pages); 5278c2ecf20Sopenharmony_ciout: 5288c2ecf20Sopenharmony_ci return err; 5298c2ecf20Sopenharmony_cierr_out: 5308c2ecf20Sopenharmony_ci while (nr > 0) { 5318c2ecf20Sopenharmony_ci unlock_page(pages[--nr]); 5328c2ecf20Sopenharmony_ci put_page(pages[nr]); 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci goto out; 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_cistatic inline int ntfs_submit_bh_for_read(struct buffer_head *bh) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci lock_buffer(bh); 5408c2ecf20Sopenharmony_ci get_bh(bh); 5418c2ecf20Sopenharmony_ci bh->b_end_io = end_buffer_read_sync; 5428c2ecf20Sopenharmony_ci return submit_bh(REQ_OP_READ, 0, bh); 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci/** 5468c2ecf20Sopenharmony_ci * ntfs_prepare_pages_for_non_resident_write - prepare pages for receiving data 5478c2ecf20Sopenharmony_ci * @pages: array of destination pages 5488c2ecf20Sopenharmony_ci * @nr_pages: number of pages in @pages 5498c2ecf20Sopenharmony_ci * @pos: byte position in file at which the write begins 5508c2ecf20Sopenharmony_ci * @bytes: number of bytes to be written 5518c2ecf20Sopenharmony_ci * 5528c2ecf20Sopenharmony_ci * This is called for non-resident attributes from ntfs_file_buffered_write() 5538c2ecf20Sopenharmony_ci * with i_mutex held on the inode (@pages[0]->mapping->host). There are 5548c2ecf20Sopenharmony_ci * @nr_pages pages in @pages which are locked but not kmap()ped. The source 5558c2ecf20Sopenharmony_ci * data has not yet been copied into the @pages. 5568c2ecf20Sopenharmony_ci * 5578c2ecf20Sopenharmony_ci * Need to fill any holes with actual clusters, allocate buffers if necessary, 5588c2ecf20Sopenharmony_ci * ensure all the buffers are mapped, and bring uptodate any buffers that are 5598c2ecf20Sopenharmony_ci * only partially being written to. 5608c2ecf20Sopenharmony_ci * 5618c2ecf20Sopenharmony_ci * If @nr_pages is greater than one, we are guaranteed that the cluster size is 5628c2ecf20Sopenharmony_ci * greater than PAGE_SIZE, that all pages in @pages are entirely inside 5638c2ecf20Sopenharmony_ci * the same cluster and that they are the entirety of that cluster, and that 5648c2ecf20Sopenharmony_ci * the cluster is sparse, i.e. we need to allocate a cluster to fill the hole. 5658c2ecf20Sopenharmony_ci * 5668c2ecf20Sopenharmony_ci * i_size is not to be modified yet. 5678c2ecf20Sopenharmony_ci * 5688c2ecf20Sopenharmony_ci * Return 0 on success or -errno on error. 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_cistatic int ntfs_prepare_pages_for_non_resident_write(struct page **pages, 5718c2ecf20Sopenharmony_ci unsigned nr_pages, s64 pos, size_t bytes) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci VCN vcn, highest_vcn = 0, cpos, cend, bh_cpos, bh_cend; 5748c2ecf20Sopenharmony_ci LCN lcn; 5758c2ecf20Sopenharmony_ci s64 bh_pos, vcn_len, end, initialized_size; 5768c2ecf20Sopenharmony_ci sector_t lcn_block; 5778c2ecf20Sopenharmony_ci struct page *page; 5788c2ecf20Sopenharmony_ci struct inode *vi; 5798c2ecf20Sopenharmony_ci ntfs_inode *ni, *base_ni = NULL; 5808c2ecf20Sopenharmony_ci ntfs_volume *vol; 5818c2ecf20Sopenharmony_ci runlist_element *rl, *rl2; 5828c2ecf20Sopenharmony_ci struct buffer_head *bh, *head, *wait[2], **wait_bh = wait; 5838c2ecf20Sopenharmony_ci ntfs_attr_search_ctx *ctx = NULL; 5848c2ecf20Sopenharmony_ci MFT_RECORD *m = NULL; 5858c2ecf20Sopenharmony_ci ATTR_RECORD *a = NULL; 5868c2ecf20Sopenharmony_ci unsigned long flags; 5878c2ecf20Sopenharmony_ci u32 attr_rec_len = 0; 5888c2ecf20Sopenharmony_ci unsigned blocksize, u; 5898c2ecf20Sopenharmony_ci int err, mp_size; 5908c2ecf20Sopenharmony_ci bool rl_write_locked, was_hole, is_retry; 5918c2ecf20Sopenharmony_ci unsigned char blocksize_bits; 5928c2ecf20Sopenharmony_ci struct { 5938c2ecf20Sopenharmony_ci u8 runlist_merged:1; 5948c2ecf20Sopenharmony_ci u8 mft_attr_mapped:1; 5958c2ecf20Sopenharmony_ci u8 mp_rebuilt:1; 5968c2ecf20Sopenharmony_ci u8 attr_switched:1; 5978c2ecf20Sopenharmony_ci } status = { 0, 0, 0, 0 }; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci BUG_ON(!nr_pages); 6008c2ecf20Sopenharmony_ci BUG_ON(!pages); 6018c2ecf20Sopenharmony_ci BUG_ON(!*pages); 6028c2ecf20Sopenharmony_ci vi = pages[0]->mapping->host; 6038c2ecf20Sopenharmony_ci ni = NTFS_I(vi); 6048c2ecf20Sopenharmony_ci vol = ni->vol; 6058c2ecf20Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page " 6068c2ecf20Sopenharmony_ci "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.", 6078c2ecf20Sopenharmony_ci vi->i_ino, ni->type, pages[0]->index, nr_pages, 6088c2ecf20Sopenharmony_ci (long long)pos, bytes); 6098c2ecf20Sopenharmony_ci blocksize = vol->sb->s_blocksize; 6108c2ecf20Sopenharmony_ci blocksize_bits = vol->sb->s_blocksize_bits; 6118c2ecf20Sopenharmony_ci u = 0; 6128c2ecf20Sopenharmony_ci do { 6138c2ecf20Sopenharmony_ci page = pages[u]; 6148c2ecf20Sopenharmony_ci BUG_ON(!page); 6158c2ecf20Sopenharmony_ci /* 6168c2ecf20Sopenharmony_ci * create_empty_buffers() will create uptodate/dirty buffers if 6178c2ecf20Sopenharmony_ci * the page is uptodate/dirty. 6188c2ecf20Sopenharmony_ci */ 6198c2ecf20Sopenharmony_ci if (!page_has_buffers(page)) { 6208c2ecf20Sopenharmony_ci create_empty_buffers(page, blocksize, 0); 6218c2ecf20Sopenharmony_ci if (unlikely(!page_has_buffers(page))) 6228c2ecf20Sopenharmony_ci return -ENOMEM; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci } while (++u < nr_pages); 6258c2ecf20Sopenharmony_ci rl_write_locked = false; 6268c2ecf20Sopenharmony_ci rl = NULL; 6278c2ecf20Sopenharmony_ci err = 0; 6288c2ecf20Sopenharmony_ci vcn = lcn = -1; 6298c2ecf20Sopenharmony_ci vcn_len = 0; 6308c2ecf20Sopenharmony_ci lcn_block = -1; 6318c2ecf20Sopenharmony_ci was_hole = false; 6328c2ecf20Sopenharmony_ci cpos = pos >> vol->cluster_size_bits; 6338c2ecf20Sopenharmony_ci end = pos + bytes; 6348c2ecf20Sopenharmony_ci cend = (end + vol->cluster_size - 1) >> vol->cluster_size_bits; 6358c2ecf20Sopenharmony_ci /* 6368c2ecf20Sopenharmony_ci * Loop over each page and for each page over each buffer. Use goto to 6378c2ecf20Sopenharmony_ci * reduce indentation. 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_ci u = 0; 6408c2ecf20Sopenharmony_cido_next_page: 6418c2ecf20Sopenharmony_ci page = pages[u]; 6428c2ecf20Sopenharmony_ci bh_pos = (s64)page->index << PAGE_SHIFT; 6438c2ecf20Sopenharmony_ci bh = head = page_buffers(page); 6448c2ecf20Sopenharmony_ci do { 6458c2ecf20Sopenharmony_ci VCN cdelta; 6468c2ecf20Sopenharmony_ci s64 bh_end; 6478c2ecf20Sopenharmony_ci unsigned bh_cofs; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* Clear buffer_new on all buffers to reinitialise state. */ 6508c2ecf20Sopenharmony_ci if (buffer_new(bh)) 6518c2ecf20Sopenharmony_ci clear_buffer_new(bh); 6528c2ecf20Sopenharmony_ci bh_end = bh_pos + blocksize; 6538c2ecf20Sopenharmony_ci bh_cpos = bh_pos >> vol->cluster_size_bits; 6548c2ecf20Sopenharmony_ci bh_cofs = bh_pos & vol->cluster_size_mask; 6558c2ecf20Sopenharmony_ci if (buffer_mapped(bh)) { 6568c2ecf20Sopenharmony_ci /* 6578c2ecf20Sopenharmony_ci * The buffer is already mapped. If it is uptodate, 6588c2ecf20Sopenharmony_ci * ignore it. 6598c2ecf20Sopenharmony_ci */ 6608c2ecf20Sopenharmony_ci if (buffer_uptodate(bh)) 6618c2ecf20Sopenharmony_ci continue; 6628c2ecf20Sopenharmony_ci /* 6638c2ecf20Sopenharmony_ci * The buffer is not uptodate. If the page is uptodate 6648c2ecf20Sopenharmony_ci * set the buffer uptodate and otherwise ignore it. 6658c2ecf20Sopenharmony_ci */ 6668c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 6678c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 6688c2ecf20Sopenharmony_ci continue; 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * Neither the page nor the buffer are uptodate. If 6728c2ecf20Sopenharmony_ci * the buffer is only partially being written to, we 6738c2ecf20Sopenharmony_ci * need to read it in before the write, i.e. now. 6748c2ecf20Sopenharmony_ci */ 6758c2ecf20Sopenharmony_ci if ((bh_pos < pos && bh_end > pos) || 6768c2ecf20Sopenharmony_ci (bh_pos < end && bh_end > end)) { 6778c2ecf20Sopenharmony_ci /* 6788c2ecf20Sopenharmony_ci * If the buffer is fully or partially within 6798c2ecf20Sopenharmony_ci * the initialized size, do an actual read. 6808c2ecf20Sopenharmony_ci * Otherwise, simply zero the buffer. 6818c2ecf20Sopenharmony_ci */ 6828c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 6838c2ecf20Sopenharmony_ci initialized_size = ni->initialized_size; 6848c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 6858c2ecf20Sopenharmony_ci if (bh_pos < initialized_size) { 6868c2ecf20Sopenharmony_ci ntfs_submit_bh_for_read(bh); 6878c2ecf20Sopenharmony_ci *wait_bh++ = bh; 6888c2ecf20Sopenharmony_ci } else { 6898c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), 6908c2ecf20Sopenharmony_ci blocksize); 6918c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci continue; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci /* Unmapped buffer. Need to map it. */ 6978c2ecf20Sopenharmony_ci bh->b_bdev = vol->sb->s_bdev; 6988c2ecf20Sopenharmony_ci /* 6998c2ecf20Sopenharmony_ci * If the current buffer is in the same clusters as the map 7008c2ecf20Sopenharmony_ci * cache, there is no need to check the runlist again. The 7018c2ecf20Sopenharmony_ci * map cache is made up of @vcn, which is the first cached file 7028c2ecf20Sopenharmony_ci * cluster, @vcn_len which is the number of cached file 7038c2ecf20Sopenharmony_ci * clusters, @lcn is the device cluster corresponding to @vcn, 7048c2ecf20Sopenharmony_ci * and @lcn_block is the block number corresponding to @lcn. 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci cdelta = bh_cpos - vcn; 7078c2ecf20Sopenharmony_ci if (likely(!cdelta || (cdelta > 0 && cdelta < vcn_len))) { 7088c2ecf20Sopenharmony_cimap_buffer_cached: 7098c2ecf20Sopenharmony_ci BUG_ON(lcn < 0); 7108c2ecf20Sopenharmony_ci bh->b_blocknr = lcn_block + 7118c2ecf20Sopenharmony_ci (cdelta << (vol->cluster_size_bits - 7128c2ecf20Sopenharmony_ci blocksize_bits)) + 7138c2ecf20Sopenharmony_ci (bh_cofs >> blocksize_bits); 7148c2ecf20Sopenharmony_ci set_buffer_mapped(bh); 7158c2ecf20Sopenharmony_ci /* 7168c2ecf20Sopenharmony_ci * If the page is uptodate so is the buffer. If the 7178c2ecf20Sopenharmony_ci * buffer is fully outside the write, we ignore it if 7188c2ecf20Sopenharmony_ci * it was already allocated and we mark it dirty so it 7198c2ecf20Sopenharmony_ci * gets written out if we allocated it. On the other 7208c2ecf20Sopenharmony_ci * hand, if we allocated the buffer but we are not 7218c2ecf20Sopenharmony_ci * marking it dirty we set buffer_new so we can do 7228c2ecf20Sopenharmony_ci * error recovery. 7238c2ecf20Sopenharmony_ci */ 7248c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 7258c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) 7268c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 7278c2ecf20Sopenharmony_ci if (unlikely(was_hole)) { 7288c2ecf20Sopenharmony_ci /* We allocated the buffer. */ 7298c2ecf20Sopenharmony_ci clean_bdev_bh_alias(bh); 7308c2ecf20Sopenharmony_ci if (bh_end <= pos || bh_pos >= end) 7318c2ecf20Sopenharmony_ci mark_buffer_dirty(bh); 7328c2ecf20Sopenharmony_ci else 7338c2ecf20Sopenharmony_ci set_buffer_new(bh); 7348c2ecf20Sopenharmony_ci } 7358c2ecf20Sopenharmony_ci continue; 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci /* Page is _not_ uptodate. */ 7388c2ecf20Sopenharmony_ci if (likely(!was_hole)) { 7398c2ecf20Sopenharmony_ci /* 7408c2ecf20Sopenharmony_ci * Buffer was already allocated. If it is not 7418c2ecf20Sopenharmony_ci * uptodate and is only partially being written 7428c2ecf20Sopenharmony_ci * to, we need to read it in before the write, 7438c2ecf20Sopenharmony_ci * i.e. now. 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh) && bh_pos < end && 7468c2ecf20Sopenharmony_ci bh_end > pos && 7478c2ecf20Sopenharmony_ci (bh_pos < pos || 7488c2ecf20Sopenharmony_ci bh_end > end)) { 7498c2ecf20Sopenharmony_ci /* 7508c2ecf20Sopenharmony_ci * If the buffer is fully or partially 7518c2ecf20Sopenharmony_ci * within the initialized size, do an 7528c2ecf20Sopenharmony_ci * actual read. Otherwise, simply zero 7538c2ecf20Sopenharmony_ci * the buffer. 7548c2ecf20Sopenharmony_ci */ 7558c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, 7568c2ecf20Sopenharmony_ci flags); 7578c2ecf20Sopenharmony_ci initialized_size = ni->initialized_size; 7588c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, 7598c2ecf20Sopenharmony_ci flags); 7608c2ecf20Sopenharmony_ci if (bh_pos < initialized_size) { 7618c2ecf20Sopenharmony_ci ntfs_submit_bh_for_read(bh); 7628c2ecf20Sopenharmony_ci *wait_bh++ = bh; 7638c2ecf20Sopenharmony_ci } else { 7648c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), 7658c2ecf20Sopenharmony_ci blocksize); 7668c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci continue; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci /* We allocated the buffer. */ 7728c2ecf20Sopenharmony_ci clean_bdev_bh_alias(bh); 7738c2ecf20Sopenharmony_ci /* 7748c2ecf20Sopenharmony_ci * If the buffer is fully outside the write, zero it, 7758c2ecf20Sopenharmony_ci * set it uptodate, and mark it dirty so it gets 7768c2ecf20Sopenharmony_ci * written out. If it is partially being written to, 7778c2ecf20Sopenharmony_ci * zero region surrounding the write but leave it to 7788c2ecf20Sopenharmony_ci * commit write to do anything else. Finally, if the 7798c2ecf20Sopenharmony_ci * buffer is fully being overwritten, do nothing. 7808c2ecf20Sopenharmony_ci */ 7818c2ecf20Sopenharmony_ci if (bh_end <= pos || bh_pos >= end) { 7828c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) { 7838c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), 7848c2ecf20Sopenharmony_ci blocksize); 7858c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci mark_buffer_dirty(bh); 7888c2ecf20Sopenharmony_ci continue; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci set_buffer_new(bh); 7918c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh) && 7928c2ecf20Sopenharmony_ci (bh_pos < pos || bh_end > end)) { 7938c2ecf20Sopenharmony_ci u8 *kaddr; 7948c2ecf20Sopenharmony_ci unsigned pofs; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci kaddr = kmap_atomic(page); 7978c2ecf20Sopenharmony_ci if (bh_pos < pos) { 7988c2ecf20Sopenharmony_ci pofs = bh_pos & ~PAGE_MASK; 7998c2ecf20Sopenharmony_ci memset(kaddr + pofs, 0, pos - bh_pos); 8008c2ecf20Sopenharmony_ci } 8018c2ecf20Sopenharmony_ci if (bh_end > end) { 8028c2ecf20Sopenharmony_ci pofs = end & ~PAGE_MASK; 8038c2ecf20Sopenharmony_ci memset(kaddr + pofs, 0, bh_end - end); 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci kunmap_atomic(kaddr); 8068c2ecf20Sopenharmony_ci flush_dcache_page(page); 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci continue; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci /* 8118c2ecf20Sopenharmony_ci * Slow path: this is the first buffer in the cluster. If it 8128c2ecf20Sopenharmony_ci * is outside allocated size and is not uptodate, zero it and 8138c2ecf20Sopenharmony_ci * set it uptodate. 8148c2ecf20Sopenharmony_ci */ 8158c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 8168c2ecf20Sopenharmony_ci initialized_size = ni->allocated_size; 8178c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 8188c2ecf20Sopenharmony_ci if (bh_pos > initialized_size) { 8198c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 8208c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) 8218c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 8228c2ecf20Sopenharmony_ci } else if (!buffer_uptodate(bh)) { 8238c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), blocksize); 8248c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci continue; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci is_retry = false; 8298c2ecf20Sopenharmony_ci if (!rl) { 8308c2ecf20Sopenharmony_ci down_read(&ni->runlist.lock); 8318c2ecf20Sopenharmony_ciretry_remap: 8328c2ecf20Sopenharmony_ci rl = ni->runlist.rl; 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci if (likely(rl != NULL)) { 8358c2ecf20Sopenharmony_ci /* Seek to element containing target cluster. */ 8368c2ecf20Sopenharmony_ci while (rl->length && rl[1].vcn <= bh_cpos) 8378c2ecf20Sopenharmony_ci rl++; 8388c2ecf20Sopenharmony_ci lcn = ntfs_rl_vcn_to_lcn(rl, bh_cpos); 8398c2ecf20Sopenharmony_ci if (likely(lcn >= 0)) { 8408c2ecf20Sopenharmony_ci /* 8418c2ecf20Sopenharmony_ci * Successful remap, setup the map cache and 8428c2ecf20Sopenharmony_ci * use that to deal with the buffer. 8438c2ecf20Sopenharmony_ci */ 8448c2ecf20Sopenharmony_ci was_hole = false; 8458c2ecf20Sopenharmony_ci vcn = bh_cpos; 8468c2ecf20Sopenharmony_ci vcn_len = rl[1].vcn - vcn; 8478c2ecf20Sopenharmony_ci lcn_block = lcn << (vol->cluster_size_bits - 8488c2ecf20Sopenharmony_ci blocksize_bits); 8498c2ecf20Sopenharmony_ci cdelta = 0; 8508c2ecf20Sopenharmony_ci /* 8518c2ecf20Sopenharmony_ci * If the number of remaining clusters touched 8528c2ecf20Sopenharmony_ci * by the write is smaller or equal to the 8538c2ecf20Sopenharmony_ci * number of cached clusters, unlock the 8548c2ecf20Sopenharmony_ci * runlist as the map cache will be used from 8558c2ecf20Sopenharmony_ci * now on. 8568c2ecf20Sopenharmony_ci */ 8578c2ecf20Sopenharmony_ci if (likely(vcn + vcn_len >= cend)) { 8588c2ecf20Sopenharmony_ci if (rl_write_locked) { 8598c2ecf20Sopenharmony_ci up_write(&ni->runlist.lock); 8608c2ecf20Sopenharmony_ci rl_write_locked = false; 8618c2ecf20Sopenharmony_ci } else 8628c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 8638c2ecf20Sopenharmony_ci rl = NULL; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci goto map_buffer_cached; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci } else 8688c2ecf20Sopenharmony_ci lcn = LCN_RL_NOT_MAPPED; 8698c2ecf20Sopenharmony_ci /* 8708c2ecf20Sopenharmony_ci * If it is not a hole and not out of bounds, the runlist is 8718c2ecf20Sopenharmony_ci * probably unmapped so try to map it now. 8728c2ecf20Sopenharmony_ci */ 8738c2ecf20Sopenharmony_ci if (unlikely(lcn != LCN_HOLE && lcn != LCN_ENOENT)) { 8748c2ecf20Sopenharmony_ci if (likely(!is_retry && lcn == LCN_RL_NOT_MAPPED)) { 8758c2ecf20Sopenharmony_ci /* Attempt to map runlist. */ 8768c2ecf20Sopenharmony_ci if (!rl_write_locked) { 8778c2ecf20Sopenharmony_ci /* 8788c2ecf20Sopenharmony_ci * We need the runlist locked for 8798c2ecf20Sopenharmony_ci * writing, so if it is locked for 8808c2ecf20Sopenharmony_ci * reading relock it now and retry in 8818c2ecf20Sopenharmony_ci * case it changed whilst we dropped 8828c2ecf20Sopenharmony_ci * the lock. 8838c2ecf20Sopenharmony_ci */ 8848c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 8858c2ecf20Sopenharmony_ci down_write(&ni->runlist.lock); 8868c2ecf20Sopenharmony_ci rl_write_locked = true; 8878c2ecf20Sopenharmony_ci goto retry_remap; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci err = ntfs_map_runlist_nolock(ni, bh_cpos, 8908c2ecf20Sopenharmony_ci NULL); 8918c2ecf20Sopenharmony_ci if (likely(!err)) { 8928c2ecf20Sopenharmony_ci is_retry = true; 8938c2ecf20Sopenharmony_ci goto retry_remap; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci /* 8968c2ecf20Sopenharmony_ci * If @vcn is out of bounds, pretend @lcn is 8978c2ecf20Sopenharmony_ci * LCN_ENOENT. As long as the buffer is out 8988c2ecf20Sopenharmony_ci * of bounds this will work fine. 8998c2ecf20Sopenharmony_ci */ 9008c2ecf20Sopenharmony_ci if (err == -ENOENT) { 9018c2ecf20Sopenharmony_ci lcn = LCN_ENOENT; 9028c2ecf20Sopenharmony_ci err = 0; 9038c2ecf20Sopenharmony_ci goto rl_not_mapped_enoent; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci } else 9068c2ecf20Sopenharmony_ci err = -EIO; 9078c2ecf20Sopenharmony_ci /* Failed to map the buffer, even after retrying. */ 9088c2ecf20Sopenharmony_ci bh->b_blocknr = -1; 9098c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to write to inode 0x%lx, " 9108c2ecf20Sopenharmony_ci "attribute type 0x%x, vcn 0x%llx, " 9118c2ecf20Sopenharmony_ci "vcn offset 0x%x, because its " 9128c2ecf20Sopenharmony_ci "location on disk could not be " 9138c2ecf20Sopenharmony_ci "determined%s (error code %i).", 9148c2ecf20Sopenharmony_ci ni->mft_no, ni->type, 9158c2ecf20Sopenharmony_ci (unsigned long long)bh_cpos, 9168c2ecf20Sopenharmony_ci (unsigned)bh_pos & 9178c2ecf20Sopenharmony_ci vol->cluster_size_mask, 9188c2ecf20Sopenharmony_ci is_retry ? " even after retrying" : "", 9198c2ecf20Sopenharmony_ci err); 9208c2ecf20Sopenharmony_ci break; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_cirl_not_mapped_enoent: 9238c2ecf20Sopenharmony_ci /* 9248c2ecf20Sopenharmony_ci * The buffer is in a hole or out of bounds. We need to fill 9258c2ecf20Sopenharmony_ci * the hole, unless the buffer is in a cluster which is not 9268c2ecf20Sopenharmony_ci * touched by the write, in which case we just leave the buffer 9278c2ecf20Sopenharmony_ci * unmapped. This can only happen when the cluster size is 9288c2ecf20Sopenharmony_ci * less than the page cache size. 9298c2ecf20Sopenharmony_ci */ 9308c2ecf20Sopenharmony_ci if (unlikely(vol->cluster_size < PAGE_SIZE)) { 9318c2ecf20Sopenharmony_ci bh_cend = (bh_end + vol->cluster_size - 1) >> 9328c2ecf20Sopenharmony_ci vol->cluster_size_bits; 9338c2ecf20Sopenharmony_ci if ((bh_cend <= cpos || bh_cpos >= cend)) { 9348c2ecf20Sopenharmony_ci bh->b_blocknr = -1; 9358c2ecf20Sopenharmony_ci /* 9368c2ecf20Sopenharmony_ci * If the buffer is uptodate we skip it. If it 9378c2ecf20Sopenharmony_ci * is not but the page is uptodate, we can set 9388c2ecf20Sopenharmony_ci * the buffer uptodate. If the page is not 9398c2ecf20Sopenharmony_ci * uptodate, we can clear the buffer and set it 9408c2ecf20Sopenharmony_ci * uptodate. Whether this is worthwhile is 9418c2ecf20Sopenharmony_ci * debatable and this could be removed. 9428c2ecf20Sopenharmony_ci */ 9438c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 9448c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) 9458c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 9468c2ecf20Sopenharmony_ci } else if (!buffer_uptodate(bh)) { 9478c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), 9488c2ecf20Sopenharmony_ci blocksize); 9498c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci continue; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci } 9548c2ecf20Sopenharmony_ci /* 9558c2ecf20Sopenharmony_ci * Out of bounds buffer is invalid if it was not really out of 9568c2ecf20Sopenharmony_ci * bounds. 9578c2ecf20Sopenharmony_ci */ 9588c2ecf20Sopenharmony_ci BUG_ON(lcn != LCN_HOLE); 9598c2ecf20Sopenharmony_ci /* 9608c2ecf20Sopenharmony_ci * We need the runlist locked for writing, so if it is locked 9618c2ecf20Sopenharmony_ci * for reading relock it now and retry in case it changed 9628c2ecf20Sopenharmony_ci * whilst we dropped the lock. 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_ci BUG_ON(!rl); 9658c2ecf20Sopenharmony_ci if (!rl_write_locked) { 9668c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 9678c2ecf20Sopenharmony_ci down_write(&ni->runlist.lock); 9688c2ecf20Sopenharmony_ci rl_write_locked = true; 9698c2ecf20Sopenharmony_ci goto retry_remap; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci /* Find the previous last allocated cluster. */ 9728c2ecf20Sopenharmony_ci BUG_ON(rl->lcn != LCN_HOLE); 9738c2ecf20Sopenharmony_ci lcn = -1; 9748c2ecf20Sopenharmony_ci rl2 = rl; 9758c2ecf20Sopenharmony_ci while (--rl2 >= ni->runlist.rl) { 9768c2ecf20Sopenharmony_ci if (rl2->lcn >= 0) { 9778c2ecf20Sopenharmony_ci lcn = rl2->lcn + rl2->length; 9788c2ecf20Sopenharmony_ci break; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci rl2 = ntfs_cluster_alloc(vol, bh_cpos, 1, lcn, DATA_ZONE, 9828c2ecf20Sopenharmony_ci false); 9838c2ecf20Sopenharmony_ci if (IS_ERR(rl2)) { 9848c2ecf20Sopenharmony_ci err = PTR_ERR(rl2); 9858c2ecf20Sopenharmony_ci ntfs_debug("Failed to allocate cluster, error code %i.", 9868c2ecf20Sopenharmony_ci err); 9878c2ecf20Sopenharmony_ci break; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci lcn = rl2->lcn; 9908c2ecf20Sopenharmony_ci rl = ntfs_runlists_merge(ni->runlist.rl, rl2); 9918c2ecf20Sopenharmony_ci if (IS_ERR(rl)) { 9928c2ecf20Sopenharmony_ci err = PTR_ERR(rl); 9938c2ecf20Sopenharmony_ci if (err != -ENOMEM) 9948c2ecf20Sopenharmony_ci err = -EIO; 9958c2ecf20Sopenharmony_ci if (ntfs_cluster_free_from_rl(vol, rl2)) { 9968c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to release " 9978c2ecf20Sopenharmony_ci "allocated cluster in error " 9988c2ecf20Sopenharmony_ci "code path. Run chkdsk to " 9998c2ecf20Sopenharmony_ci "recover the lost cluster."); 10008c2ecf20Sopenharmony_ci NVolSetErrors(vol); 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci ntfs_free(rl2); 10038c2ecf20Sopenharmony_ci break; 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci ni->runlist.rl = rl; 10068c2ecf20Sopenharmony_ci status.runlist_merged = 1; 10078c2ecf20Sopenharmony_ci ntfs_debug("Allocated cluster, lcn 0x%llx.", 10088c2ecf20Sopenharmony_ci (unsigned long long)lcn); 10098c2ecf20Sopenharmony_ci /* Map and lock the mft record and get the attribute record. */ 10108c2ecf20Sopenharmony_ci if (!NInoAttr(ni)) 10118c2ecf20Sopenharmony_ci base_ni = ni; 10128c2ecf20Sopenharmony_ci else 10138c2ecf20Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 10148c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 10158c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 10168c2ecf20Sopenharmony_ci err = PTR_ERR(m); 10178c2ecf20Sopenharmony_ci break; 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 10208c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 10218c2ecf20Sopenharmony_ci err = -ENOMEM; 10228c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 10238c2ecf20Sopenharmony_ci break; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci status.mft_attr_mapped = 1; 10268c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 10278c2ecf20Sopenharmony_ci CASE_SENSITIVE, bh_cpos, NULL, 0, ctx); 10288c2ecf20Sopenharmony_ci if (unlikely(err)) { 10298c2ecf20Sopenharmony_ci if (err == -ENOENT) 10308c2ecf20Sopenharmony_ci err = -EIO; 10318c2ecf20Sopenharmony_ci break; 10328c2ecf20Sopenharmony_ci } 10338c2ecf20Sopenharmony_ci m = ctx->mrec; 10348c2ecf20Sopenharmony_ci a = ctx->attr; 10358c2ecf20Sopenharmony_ci /* 10368c2ecf20Sopenharmony_ci * Find the runlist element with which the attribute extent 10378c2ecf20Sopenharmony_ci * starts. Note, we cannot use the _attr_ version because we 10388c2ecf20Sopenharmony_ci * have mapped the mft record. That is ok because we know the 10398c2ecf20Sopenharmony_ci * runlist fragment must be mapped already to have ever gotten 10408c2ecf20Sopenharmony_ci * here, so we can just use the _rl_ version. 10418c2ecf20Sopenharmony_ci */ 10428c2ecf20Sopenharmony_ci vcn = sle64_to_cpu(a->data.non_resident.lowest_vcn); 10438c2ecf20Sopenharmony_ci rl2 = ntfs_rl_find_vcn_nolock(rl, vcn); 10448c2ecf20Sopenharmony_ci BUG_ON(!rl2); 10458c2ecf20Sopenharmony_ci BUG_ON(!rl2->length); 10468c2ecf20Sopenharmony_ci BUG_ON(rl2->lcn < LCN_HOLE); 10478c2ecf20Sopenharmony_ci highest_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn); 10488c2ecf20Sopenharmony_ci /* 10498c2ecf20Sopenharmony_ci * If @highest_vcn is zero, calculate the real highest_vcn 10508c2ecf20Sopenharmony_ci * (which can really be zero). 10518c2ecf20Sopenharmony_ci */ 10528c2ecf20Sopenharmony_ci if (!highest_vcn) 10538c2ecf20Sopenharmony_ci highest_vcn = (sle64_to_cpu( 10548c2ecf20Sopenharmony_ci a->data.non_resident.allocated_size) >> 10558c2ecf20Sopenharmony_ci vol->cluster_size_bits) - 1; 10568c2ecf20Sopenharmony_ci /* 10578c2ecf20Sopenharmony_ci * Determine the size of the mapping pairs array for the new 10588c2ecf20Sopenharmony_ci * extent, i.e. the old extent with the hole filled. 10598c2ecf20Sopenharmony_ci */ 10608c2ecf20Sopenharmony_ci mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, vcn, 10618c2ecf20Sopenharmony_ci highest_vcn); 10628c2ecf20Sopenharmony_ci if (unlikely(mp_size <= 0)) { 10638c2ecf20Sopenharmony_ci if (!(err = mp_size)) 10648c2ecf20Sopenharmony_ci err = -EIO; 10658c2ecf20Sopenharmony_ci ntfs_debug("Failed to get size for mapping pairs " 10668c2ecf20Sopenharmony_ci "array, error code %i.", err); 10678c2ecf20Sopenharmony_ci break; 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci /* 10708c2ecf20Sopenharmony_ci * Resize the attribute record to fit the new mapping pairs 10718c2ecf20Sopenharmony_ci * array. 10728c2ecf20Sopenharmony_ci */ 10738c2ecf20Sopenharmony_ci attr_rec_len = le32_to_cpu(a->length); 10748c2ecf20Sopenharmony_ci err = ntfs_attr_record_resize(m, a, mp_size + le16_to_cpu( 10758c2ecf20Sopenharmony_ci a->data.non_resident.mapping_pairs_offset)); 10768c2ecf20Sopenharmony_ci if (unlikely(err)) { 10778c2ecf20Sopenharmony_ci BUG_ON(err != -ENOSPC); 10788c2ecf20Sopenharmony_ci // TODO: Deal with this by using the current attribute 10798c2ecf20Sopenharmony_ci // and fill it with as much of the mapping pairs 10808c2ecf20Sopenharmony_ci // array as possible. Then loop over each attribute 10818c2ecf20Sopenharmony_ci // extent rewriting the mapping pairs arrays as we go 10828c2ecf20Sopenharmony_ci // along and if when we reach the end we have not 10838c2ecf20Sopenharmony_ci // enough space, try to resize the last attribute 10848c2ecf20Sopenharmony_ci // extent and if even that fails, add a new attribute 10858c2ecf20Sopenharmony_ci // extent. 10868c2ecf20Sopenharmony_ci // We could also try to resize at each step in the hope 10878c2ecf20Sopenharmony_ci // that we will not need to rewrite every single extent. 10888c2ecf20Sopenharmony_ci // Note, we may need to decompress some extents to fill 10898c2ecf20Sopenharmony_ci // the runlist as we are walking the extents... 10908c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Not enough space in the mft " 10918c2ecf20Sopenharmony_ci "record for the extended attribute " 10928c2ecf20Sopenharmony_ci "record. This case is not " 10938c2ecf20Sopenharmony_ci "implemented yet."); 10948c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 10958c2ecf20Sopenharmony_ci break ; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci status.mp_rebuilt = 1; 10988c2ecf20Sopenharmony_ci /* 10998c2ecf20Sopenharmony_ci * Generate the mapping pairs array directly into the attribute 11008c2ecf20Sopenharmony_ci * record. 11018c2ecf20Sopenharmony_ci */ 11028c2ecf20Sopenharmony_ci err = ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( 11038c2ecf20Sopenharmony_ci a->data.non_resident.mapping_pairs_offset), 11048c2ecf20Sopenharmony_ci mp_size, rl2, vcn, highest_vcn, NULL); 11058c2ecf20Sopenharmony_ci if (unlikely(err)) { 11068c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Cannot fill hole in inode 0x%lx, " 11078c2ecf20Sopenharmony_ci "attribute type 0x%x, because building " 11088c2ecf20Sopenharmony_ci "the mapping pairs failed with error " 11098c2ecf20Sopenharmony_ci "code %i.", vi->i_ino, 11108c2ecf20Sopenharmony_ci (unsigned)le32_to_cpu(ni->type), err); 11118c2ecf20Sopenharmony_ci err = -EIO; 11128c2ecf20Sopenharmony_ci break; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci /* Update the highest_vcn but only if it was not set. */ 11158c2ecf20Sopenharmony_ci if (unlikely(!a->data.non_resident.highest_vcn)) 11168c2ecf20Sopenharmony_ci a->data.non_resident.highest_vcn = 11178c2ecf20Sopenharmony_ci cpu_to_sle64(highest_vcn); 11188c2ecf20Sopenharmony_ci /* 11198c2ecf20Sopenharmony_ci * If the attribute is sparse/compressed, update the compressed 11208c2ecf20Sopenharmony_ci * size in the ntfs_inode structure and the attribute record. 11218c2ecf20Sopenharmony_ci */ 11228c2ecf20Sopenharmony_ci if (likely(NInoSparse(ni) || NInoCompressed(ni))) { 11238c2ecf20Sopenharmony_ci /* 11248c2ecf20Sopenharmony_ci * If we are not in the first attribute extent, switch 11258c2ecf20Sopenharmony_ci * to it, but first ensure the changes will make it to 11268c2ecf20Sopenharmony_ci * disk later. 11278c2ecf20Sopenharmony_ci */ 11288c2ecf20Sopenharmony_ci if (a->data.non_resident.lowest_vcn) { 11298c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 11308c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 11318c2ecf20Sopenharmony_ci ntfs_attr_reinit_search_ctx(ctx); 11328c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, 11338c2ecf20Sopenharmony_ci ni->name_len, CASE_SENSITIVE, 11348c2ecf20Sopenharmony_ci 0, NULL, 0, ctx); 11358c2ecf20Sopenharmony_ci if (unlikely(err)) { 11368c2ecf20Sopenharmony_ci status.attr_switched = 1; 11378c2ecf20Sopenharmony_ci break; 11388c2ecf20Sopenharmony_ci } 11398c2ecf20Sopenharmony_ci /* @m is not used any more so do not set it. */ 11408c2ecf20Sopenharmony_ci a = ctx->attr; 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 11438c2ecf20Sopenharmony_ci ni->itype.compressed.size += vol->cluster_size; 11448c2ecf20Sopenharmony_ci a->data.non_resident.compressed_size = 11458c2ecf20Sopenharmony_ci cpu_to_sle64(ni->itype.compressed.size); 11468c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci /* Ensure the changes make it to disk. */ 11498c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 11508c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 11518c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 11528c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 11538c2ecf20Sopenharmony_ci /* Successfully filled the hole. */ 11548c2ecf20Sopenharmony_ci status.runlist_merged = 0; 11558c2ecf20Sopenharmony_ci status.mft_attr_mapped = 0; 11568c2ecf20Sopenharmony_ci status.mp_rebuilt = 0; 11578c2ecf20Sopenharmony_ci /* Setup the map cache and use that to deal with the buffer. */ 11588c2ecf20Sopenharmony_ci was_hole = true; 11598c2ecf20Sopenharmony_ci vcn = bh_cpos; 11608c2ecf20Sopenharmony_ci vcn_len = 1; 11618c2ecf20Sopenharmony_ci lcn_block = lcn << (vol->cluster_size_bits - blocksize_bits); 11628c2ecf20Sopenharmony_ci cdelta = 0; 11638c2ecf20Sopenharmony_ci /* 11648c2ecf20Sopenharmony_ci * If the number of remaining clusters in the @pages is smaller 11658c2ecf20Sopenharmony_ci * or equal to the number of cached clusters, unlock the 11668c2ecf20Sopenharmony_ci * runlist as the map cache will be used from now on. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_ci if (likely(vcn + vcn_len >= cend)) { 11698c2ecf20Sopenharmony_ci up_write(&ni->runlist.lock); 11708c2ecf20Sopenharmony_ci rl_write_locked = false; 11718c2ecf20Sopenharmony_ci rl = NULL; 11728c2ecf20Sopenharmony_ci } 11738c2ecf20Sopenharmony_ci goto map_buffer_cached; 11748c2ecf20Sopenharmony_ci } while (bh_pos += blocksize, (bh = bh->b_this_page) != head); 11758c2ecf20Sopenharmony_ci /* If there are no errors, do the next page. */ 11768c2ecf20Sopenharmony_ci if (likely(!err && ++u < nr_pages)) 11778c2ecf20Sopenharmony_ci goto do_next_page; 11788c2ecf20Sopenharmony_ci /* If there are no errors, release the runlist lock if we took it. */ 11798c2ecf20Sopenharmony_ci if (likely(!err)) { 11808c2ecf20Sopenharmony_ci if (unlikely(rl_write_locked)) { 11818c2ecf20Sopenharmony_ci up_write(&ni->runlist.lock); 11828c2ecf20Sopenharmony_ci rl_write_locked = false; 11838c2ecf20Sopenharmony_ci } else if (unlikely(rl)) 11848c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 11858c2ecf20Sopenharmony_ci rl = NULL; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci /* If we issued read requests, let them complete. */ 11888c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 11898c2ecf20Sopenharmony_ci initialized_size = ni->initialized_size; 11908c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 11918c2ecf20Sopenharmony_ci while (wait_bh > wait) { 11928c2ecf20Sopenharmony_ci bh = *--wait_bh; 11938c2ecf20Sopenharmony_ci wait_on_buffer(bh); 11948c2ecf20Sopenharmony_ci if (likely(buffer_uptodate(bh))) { 11958c2ecf20Sopenharmony_ci page = bh->b_page; 11968c2ecf20Sopenharmony_ci bh_pos = ((s64)page->index << PAGE_SHIFT) + 11978c2ecf20Sopenharmony_ci bh_offset(bh); 11988c2ecf20Sopenharmony_ci /* 11998c2ecf20Sopenharmony_ci * If the buffer overflows the initialized size, need 12008c2ecf20Sopenharmony_ci * to zero the overflowing region. 12018c2ecf20Sopenharmony_ci */ 12028c2ecf20Sopenharmony_ci if (unlikely(bh_pos + blocksize > initialized_size)) { 12038c2ecf20Sopenharmony_ci int ofs = 0; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (likely(bh_pos < initialized_size)) 12068c2ecf20Sopenharmony_ci ofs = initialized_size - bh_pos; 12078c2ecf20Sopenharmony_ci zero_user_segment(page, bh_offset(bh) + ofs, 12088c2ecf20Sopenharmony_ci blocksize); 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci } else /* if (unlikely(!buffer_uptodate(bh))) */ 12118c2ecf20Sopenharmony_ci err = -EIO; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci if (likely(!err)) { 12148c2ecf20Sopenharmony_ci /* Clear buffer_new on all buffers. */ 12158c2ecf20Sopenharmony_ci u = 0; 12168c2ecf20Sopenharmony_ci do { 12178c2ecf20Sopenharmony_ci bh = head = page_buffers(pages[u]); 12188c2ecf20Sopenharmony_ci do { 12198c2ecf20Sopenharmony_ci if (buffer_new(bh)) 12208c2ecf20Sopenharmony_ci clear_buffer_new(bh); 12218c2ecf20Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 12228c2ecf20Sopenharmony_ci } while (++u < nr_pages); 12238c2ecf20Sopenharmony_ci ntfs_debug("Done."); 12248c2ecf20Sopenharmony_ci return err; 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci if (status.attr_switched) { 12278c2ecf20Sopenharmony_ci /* Get back to the attribute extent we modified. */ 12288c2ecf20Sopenharmony_ci ntfs_attr_reinit_search_ctx(ctx); 12298c2ecf20Sopenharmony_ci if (ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 12308c2ecf20Sopenharmony_ci CASE_SENSITIVE, bh_cpos, NULL, 0, ctx)) { 12318c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to find required " 12328c2ecf20Sopenharmony_ci "attribute extent of attribute in " 12338c2ecf20Sopenharmony_ci "error code path. Run chkdsk to " 12348c2ecf20Sopenharmony_ci "recover."); 12358c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 12368c2ecf20Sopenharmony_ci ni->itype.compressed.size += vol->cluster_size; 12378c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 12388c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 12398c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 12408c2ecf20Sopenharmony_ci /* 12418c2ecf20Sopenharmony_ci * The only thing that is now wrong is the compressed 12428c2ecf20Sopenharmony_ci * size of the base attribute extent which chkdsk 12438c2ecf20Sopenharmony_ci * should be able to fix. 12448c2ecf20Sopenharmony_ci */ 12458c2ecf20Sopenharmony_ci NVolSetErrors(vol); 12468c2ecf20Sopenharmony_ci } else { 12478c2ecf20Sopenharmony_ci m = ctx->mrec; 12488c2ecf20Sopenharmony_ci a = ctx->attr; 12498c2ecf20Sopenharmony_ci status.attr_switched = 0; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci /* 12538c2ecf20Sopenharmony_ci * If the runlist has been modified, need to restore it by punching a 12548c2ecf20Sopenharmony_ci * hole into it and we then need to deallocate the on-disk cluster as 12558c2ecf20Sopenharmony_ci * well. Note, we only modify the runlist if we are able to generate a 12568c2ecf20Sopenharmony_ci * new mapping pairs array, i.e. only when the mapped attribute extent 12578c2ecf20Sopenharmony_ci * is not switched. 12588c2ecf20Sopenharmony_ci */ 12598c2ecf20Sopenharmony_ci if (status.runlist_merged && !status.attr_switched) { 12608c2ecf20Sopenharmony_ci BUG_ON(!rl_write_locked); 12618c2ecf20Sopenharmony_ci /* Make the file cluster we allocated sparse in the runlist. */ 12628c2ecf20Sopenharmony_ci if (ntfs_rl_punch_nolock(vol, &ni->runlist, bh_cpos, 1)) { 12638c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to punch hole into " 12648c2ecf20Sopenharmony_ci "attribute runlist in error code " 12658c2ecf20Sopenharmony_ci "path. Run chkdsk to recover the " 12668c2ecf20Sopenharmony_ci "lost cluster."); 12678c2ecf20Sopenharmony_ci NVolSetErrors(vol); 12688c2ecf20Sopenharmony_ci } else /* if (success) */ { 12698c2ecf20Sopenharmony_ci status.runlist_merged = 0; 12708c2ecf20Sopenharmony_ci /* 12718c2ecf20Sopenharmony_ci * Deallocate the on-disk cluster we allocated but only 12728c2ecf20Sopenharmony_ci * if we succeeded in punching its vcn out of the 12738c2ecf20Sopenharmony_ci * runlist. 12748c2ecf20Sopenharmony_ci */ 12758c2ecf20Sopenharmony_ci down_write(&vol->lcnbmp_lock); 12768c2ecf20Sopenharmony_ci if (ntfs_bitmap_clear_bit(vol->lcnbmp_ino, lcn)) { 12778c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to release " 12788c2ecf20Sopenharmony_ci "allocated cluster in error " 12798c2ecf20Sopenharmony_ci "code path. Run chkdsk to " 12808c2ecf20Sopenharmony_ci "recover the lost cluster."); 12818c2ecf20Sopenharmony_ci NVolSetErrors(vol); 12828c2ecf20Sopenharmony_ci } 12838c2ecf20Sopenharmony_ci up_write(&vol->lcnbmp_lock); 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci /* 12878c2ecf20Sopenharmony_ci * Resize the attribute record to its old size and rebuild the mapping 12888c2ecf20Sopenharmony_ci * pairs array. Note, we only can do this if the runlist has been 12898c2ecf20Sopenharmony_ci * restored to its old state which also implies that the mapped 12908c2ecf20Sopenharmony_ci * attribute extent is not switched. 12918c2ecf20Sopenharmony_ci */ 12928c2ecf20Sopenharmony_ci if (status.mp_rebuilt && !status.runlist_merged) { 12938c2ecf20Sopenharmony_ci if (ntfs_attr_record_resize(m, a, attr_rec_len)) { 12948c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to restore attribute " 12958c2ecf20Sopenharmony_ci "record in error code path. Run " 12968c2ecf20Sopenharmony_ci "chkdsk to recover."); 12978c2ecf20Sopenharmony_ci NVolSetErrors(vol); 12988c2ecf20Sopenharmony_ci } else /* if (success) */ { 12998c2ecf20Sopenharmony_ci if (ntfs_mapping_pairs_build(vol, (u8*)a + 13008c2ecf20Sopenharmony_ci le16_to_cpu(a->data.non_resident. 13018c2ecf20Sopenharmony_ci mapping_pairs_offset), attr_rec_len - 13028c2ecf20Sopenharmony_ci le16_to_cpu(a->data.non_resident. 13038c2ecf20Sopenharmony_ci mapping_pairs_offset), ni->runlist.rl, 13048c2ecf20Sopenharmony_ci vcn, highest_vcn, NULL)) { 13058c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed to restore " 13068c2ecf20Sopenharmony_ci "mapping pairs array in error " 13078c2ecf20Sopenharmony_ci "code path. Run chkdsk to " 13088c2ecf20Sopenharmony_ci "recover."); 13098c2ecf20Sopenharmony_ci NVolSetErrors(vol); 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 13128c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 13138c2ecf20Sopenharmony_ci } 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci /* Release the mft record and the attribute. */ 13168c2ecf20Sopenharmony_ci if (status.mft_attr_mapped) { 13178c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 13188c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci /* Release the runlist lock. */ 13218c2ecf20Sopenharmony_ci if (rl_write_locked) 13228c2ecf20Sopenharmony_ci up_write(&ni->runlist.lock); 13238c2ecf20Sopenharmony_ci else if (rl) 13248c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 13258c2ecf20Sopenharmony_ci /* 13268c2ecf20Sopenharmony_ci * Zero out any newly allocated blocks to avoid exposing stale data. 13278c2ecf20Sopenharmony_ci * If BH_New is set, we know that the block was newly allocated above 13288c2ecf20Sopenharmony_ci * and that it has not been fully zeroed and marked dirty yet. 13298c2ecf20Sopenharmony_ci */ 13308c2ecf20Sopenharmony_ci nr_pages = u; 13318c2ecf20Sopenharmony_ci u = 0; 13328c2ecf20Sopenharmony_ci end = bh_cpos << vol->cluster_size_bits; 13338c2ecf20Sopenharmony_ci do { 13348c2ecf20Sopenharmony_ci page = pages[u]; 13358c2ecf20Sopenharmony_ci bh = head = page_buffers(page); 13368c2ecf20Sopenharmony_ci do { 13378c2ecf20Sopenharmony_ci if (u == nr_pages && 13388c2ecf20Sopenharmony_ci ((s64)page->index << PAGE_SHIFT) + 13398c2ecf20Sopenharmony_ci bh_offset(bh) >= end) 13408c2ecf20Sopenharmony_ci break; 13418c2ecf20Sopenharmony_ci if (!buffer_new(bh)) 13428c2ecf20Sopenharmony_ci continue; 13438c2ecf20Sopenharmony_ci clear_buffer_new(bh); 13448c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) { 13458c2ecf20Sopenharmony_ci if (PageUptodate(page)) 13468c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 13478c2ecf20Sopenharmony_ci else { 13488c2ecf20Sopenharmony_ci zero_user(page, bh_offset(bh), 13498c2ecf20Sopenharmony_ci blocksize); 13508c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci } 13538c2ecf20Sopenharmony_ci mark_buffer_dirty(bh); 13548c2ecf20Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 13558c2ecf20Sopenharmony_ci } while (++u <= nr_pages); 13568c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Failed. Returning error code %i.", err); 13578c2ecf20Sopenharmony_ci return err; 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_cistatic inline void ntfs_flush_dcache_pages(struct page **pages, 13618c2ecf20Sopenharmony_ci unsigned nr_pages) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci BUG_ON(!nr_pages); 13648c2ecf20Sopenharmony_ci /* 13658c2ecf20Sopenharmony_ci * Warning: Do not do the decrement at the same time as the call to 13668c2ecf20Sopenharmony_ci * flush_dcache_page() because it is a NULL macro on i386 and hence the 13678c2ecf20Sopenharmony_ci * decrement never happens so the loop never terminates. 13688c2ecf20Sopenharmony_ci */ 13698c2ecf20Sopenharmony_ci do { 13708c2ecf20Sopenharmony_ci --nr_pages; 13718c2ecf20Sopenharmony_ci flush_dcache_page(pages[nr_pages]); 13728c2ecf20Sopenharmony_ci } while (nr_pages > 0); 13738c2ecf20Sopenharmony_ci} 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci/** 13768c2ecf20Sopenharmony_ci * ntfs_commit_pages_after_non_resident_write - commit the received data 13778c2ecf20Sopenharmony_ci * @pages: array of destination pages 13788c2ecf20Sopenharmony_ci * @nr_pages: number of pages in @pages 13798c2ecf20Sopenharmony_ci * @pos: byte position in file at which the write begins 13808c2ecf20Sopenharmony_ci * @bytes: number of bytes to be written 13818c2ecf20Sopenharmony_ci * 13828c2ecf20Sopenharmony_ci * See description of ntfs_commit_pages_after_write(), below. 13838c2ecf20Sopenharmony_ci */ 13848c2ecf20Sopenharmony_cistatic inline int ntfs_commit_pages_after_non_resident_write( 13858c2ecf20Sopenharmony_ci struct page **pages, const unsigned nr_pages, 13868c2ecf20Sopenharmony_ci s64 pos, size_t bytes) 13878c2ecf20Sopenharmony_ci{ 13888c2ecf20Sopenharmony_ci s64 end, initialized_size; 13898c2ecf20Sopenharmony_ci struct inode *vi; 13908c2ecf20Sopenharmony_ci ntfs_inode *ni, *base_ni; 13918c2ecf20Sopenharmony_ci struct buffer_head *bh, *head; 13928c2ecf20Sopenharmony_ci ntfs_attr_search_ctx *ctx; 13938c2ecf20Sopenharmony_ci MFT_RECORD *m; 13948c2ecf20Sopenharmony_ci ATTR_RECORD *a; 13958c2ecf20Sopenharmony_ci unsigned long flags; 13968c2ecf20Sopenharmony_ci unsigned blocksize, u; 13978c2ecf20Sopenharmony_ci int err; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci vi = pages[0]->mapping->host; 14008c2ecf20Sopenharmony_ci ni = NTFS_I(vi); 14018c2ecf20Sopenharmony_ci blocksize = vi->i_sb->s_blocksize; 14028c2ecf20Sopenharmony_ci end = pos + bytes; 14038c2ecf20Sopenharmony_ci u = 0; 14048c2ecf20Sopenharmony_ci do { 14058c2ecf20Sopenharmony_ci s64 bh_pos; 14068c2ecf20Sopenharmony_ci struct page *page; 14078c2ecf20Sopenharmony_ci bool partial; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci page = pages[u]; 14108c2ecf20Sopenharmony_ci bh_pos = (s64)page->index << PAGE_SHIFT; 14118c2ecf20Sopenharmony_ci bh = head = page_buffers(page); 14128c2ecf20Sopenharmony_ci partial = false; 14138c2ecf20Sopenharmony_ci do { 14148c2ecf20Sopenharmony_ci s64 bh_end; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci bh_end = bh_pos + blocksize; 14178c2ecf20Sopenharmony_ci if (bh_end <= pos || bh_pos >= end) { 14188c2ecf20Sopenharmony_ci if (!buffer_uptodate(bh)) 14198c2ecf20Sopenharmony_ci partial = true; 14208c2ecf20Sopenharmony_ci } else { 14218c2ecf20Sopenharmony_ci set_buffer_uptodate(bh); 14228c2ecf20Sopenharmony_ci mark_buffer_dirty(bh); 14238c2ecf20Sopenharmony_ci } 14248c2ecf20Sopenharmony_ci } while (bh_pos += blocksize, (bh = bh->b_this_page) != head); 14258c2ecf20Sopenharmony_ci /* 14268c2ecf20Sopenharmony_ci * If all buffers are now uptodate but the page is not, set the 14278c2ecf20Sopenharmony_ci * page uptodate. 14288c2ecf20Sopenharmony_ci */ 14298c2ecf20Sopenharmony_ci if (!partial && !PageUptodate(page)) 14308c2ecf20Sopenharmony_ci SetPageUptodate(page); 14318c2ecf20Sopenharmony_ci } while (++u < nr_pages); 14328c2ecf20Sopenharmony_ci /* 14338c2ecf20Sopenharmony_ci * Finally, if we do not need to update initialized_size or i_size we 14348c2ecf20Sopenharmony_ci * are finished. 14358c2ecf20Sopenharmony_ci */ 14368c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 14378c2ecf20Sopenharmony_ci initialized_size = ni->initialized_size; 14388c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 14398c2ecf20Sopenharmony_ci if (end <= initialized_size) { 14408c2ecf20Sopenharmony_ci ntfs_debug("Done."); 14418c2ecf20Sopenharmony_ci return 0; 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci /* 14448c2ecf20Sopenharmony_ci * Update initialized_size/i_size as appropriate, both in the inode and 14458c2ecf20Sopenharmony_ci * the mft record. 14468c2ecf20Sopenharmony_ci */ 14478c2ecf20Sopenharmony_ci if (!NInoAttr(ni)) 14488c2ecf20Sopenharmony_ci base_ni = ni; 14498c2ecf20Sopenharmony_ci else 14508c2ecf20Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 14518c2ecf20Sopenharmony_ci /* Map, pin, and lock the mft record. */ 14528c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 14538c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 14548c2ecf20Sopenharmony_ci err = PTR_ERR(m); 14558c2ecf20Sopenharmony_ci m = NULL; 14568c2ecf20Sopenharmony_ci ctx = NULL; 14578c2ecf20Sopenharmony_ci goto err_out; 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci BUG_ON(!NInoNonResident(ni)); 14608c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 14618c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 14628c2ecf20Sopenharmony_ci err = -ENOMEM; 14638c2ecf20Sopenharmony_ci goto err_out; 14648c2ecf20Sopenharmony_ci } 14658c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 14668c2ecf20Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 14678c2ecf20Sopenharmony_ci if (unlikely(err)) { 14688c2ecf20Sopenharmony_ci if (err == -ENOENT) 14698c2ecf20Sopenharmony_ci err = -EIO; 14708c2ecf20Sopenharmony_ci goto err_out; 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci a = ctx->attr; 14738c2ecf20Sopenharmony_ci BUG_ON(!a->non_resident); 14748c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 14758c2ecf20Sopenharmony_ci BUG_ON(end > ni->allocated_size); 14768c2ecf20Sopenharmony_ci ni->initialized_size = end; 14778c2ecf20Sopenharmony_ci a->data.non_resident.initialized_size = cpu_to_sle64(end); 14788c2ecf20Sopenharmony_ci if (end > i_size_read(vi)) { 14798c2ecf20Sopenharmony_ci i_size_write(vi, end); 14808c2ecf20Sopenharmony_ci a->data.non_resident.data_size = 14818c2ecf20Sopenharmony_ci a->data.non_resident.initialized_size; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 14848c2ecf20Sopenharmony_ci /* Mark the mft record dirty, so it gets written back. */ 14858c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 14868c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 14878c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 14888c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 14898c2ecf20Sopenharmony_ci ntfs_debug("Done."); 14908c2ecf20Sopenharmony_ci return 0; 14918c2ecf20Sopenharmony_cierr_out: 14928c2ecf20Sopenharmony_ci if (ctx) 14938c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 14948c2ecf20Sopenharmony_ci if (m) 14958c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 14968c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Failed to update initialized_size/i_size (error " 14978c2ecf20Sopenharmony_ci "code %i).", err); 14988c2ecf20Sopenharmony_ci if (err != -ENOMEM) 14998c2ecf20Sopenharmony_ci NVolSetErrors(ni->vol); 15008c2ecf20Sopenharmony_ci return err; 15018c2ecf20Sopenharmony_ci} 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci/** 15048c2ecf20Sopenharmony_ci * ntfs_commit_pages_after_write - commit the received data 15058c2ecf20Sopenharmony_ci * @pages: array of destination pages 15068c2ecf20Sopenharmony_ci * @nr_pages: number of pages in @pages 15078c2ecf20Sopenharmony_ci * @pos: byte position in file at which the write begins 15088c2ecf20Sopenharmony_ci * @bytes: number of bytes to be written 15098c2ecf20Sopenharmony_ci * 15108c2ecf20Sopenharmony_ci * This is called from ntfs_file_buffered_write() with i_mutex held on the inode 15118c2ecf20Sopenharmony_ci * (@pages[0]->mapping->host). There are @nr_pages pages in @pages which are 15128c2ecf20Sopenharmony_ci * locked but not kmap()ped. The source data has already been copied into the 15138c2ecf20Sopenharmony_ci * @page. ntfs_prepare_pages_for_non_resident_write() has been called before 15148c2ecf20Sopenharmony_ci * the data was copied (for non-resident attributes only) and it returned 15158c2ecf20Sopenharmony_ci * success. 15168c2ecf20Sopenharmony_ci * 15178c2ecf20Sopenharmony_ci * Need to set uptodate and mark dirty all buffers within the boundary of the 15188c2ecf20Sopenharmony_ci * write. If all buffers in a page are uptodate we set the page uptodate, too. 15198c2ecf20Sopenharmony_ci * 15208c2ecf20Sopenharmony_ci * Setting the buffers dirty ensures that they get written out later when 15218c2ecf20Sopenharmony_ci * ntfs_writepage() is invoked by the VM. 15228c2ecf20Sopenharmony_ci * 15238c2ecf20Sopenharmony_ci * Finally, we need to update i_size and initialized_size as appropriate both 15248c2ecf20Sopenharmony_ci * in the inode and the mft record. 15258c2ecf20Sopenharmony_ci * 15268c2ecf20Sopenharmony_ci * This is modelled after fs/buffer.c::generic_commit_write(), which marks 15278c2ecf20Sopenharmony_ci * buffers uptodate and dirty, sets the page uptodate if all buffers in the 15288c2ecf20Sopenharmony_ci * page are uptodate, and updates i_size if the end of io is beyond i_size. In 15298c2ecf20Sopenharmony_ci * that case, it also marks the inode dirty. 15308c2ecf20Sopenharmony_ci * 15318c2ecf20Sopenharmony_ci * If things have gone as outlined in 15328c2ecf20Sopenharmony_ci * ntfs_prepare_pages_for_non_resident_write(), we do not need to do any page 15338c2ecf20Sopenharmony_ci * content modifications here for non-resident attributes. For resident 15348c2ecf20Sopenharmony_ci * attributes we need to do the uptodate bringing here which we combine with 15358c2ecf20Sopenharmony_ci * the copying into the mft record which means we save one atomic kmap. 15368c2ecf20Sopenharmony_ci * 15378c2ecf20Sopenharmony_ci * Return 0 on success or -errno on error. 15388c2ecf20Sopenharmony_ci */ 15398c2ecf20Sopenharmony_cistatic int ntfs_commit_pages_after_write(struct page **pages, 15408c2ecf20Sopenharmony_ci const unsigned nr_pages, s64 pos, size_t bytes) 15418c2ecf20Sopenharmony_ci{ 15428c2ecf20Sopenharmony_ci s64 end, initialized_size; 15438c2ecf20Sopenharmony_ci loff_t i_size; 15448c2ecf20Sopenharmony_ci struct inode *vi; 15458c2ecf20Sopenharmony_ci ntfs_inode *ni, *base_ni; 15468c2ecf20Sopenharmony_ci struct page *page; 15478c2ecf20Sopenharmony_ci ntfs_attr_search_ctx *ctx; 15488c2ecf20Sopenharmony_ci MFT_RECORD *m; 15498c2ecf20Sopenharmony_ci ATTR_RECORD *a; 15508c2ecf20Sopenharmony_ci char *kattr, *kaddr; 15518c2ecf20Sopenharmony_ci unsigned long flags; 15528c2ecf20Sopenharmony_ci u32 attr_len; 15538c2ecf20Sopenharmony_ci int err; 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci BUG_ON(!nr_pages); 15568c2ecf20Sopenharmony_ci BUG_ON(!pages); 15578c2ecf20Sopenharmony_ci page = pages[0]; 15588c2ecf20Sopenharmony_ci BUG_ON(!page); 15598c2ecf20Sopenharmony_ci vi = page->mapping->host; 15608c2ecf20Sopenharmony_ci ni = NTFS_I(vi); 15618c2ecf20Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page " 15628c2ecf20Sopenharmony_ci "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.", 15638c2ecf20Sopenharmony_ci vi->i_ino, ni->type, page->index, nr_pages, 15648c2ecf20Sopenharmony_ci (long long)pos, bytes); 15658c2ecf20Sopenharmony_ci if (NInoNonResident(ni)) 15668c2ecf20Sopenharmony_ci return ntfs_commit_pages_after_non_resident_write(pages, 15678c2ecf20Sopenharmony_ci nr_pages, pos, bytes); 15688c2ecf20Sopenharmony_ci BUG_ON(nr_pages > 1); 15698c2ecf20Sopenharmony_ci /* 15708c2ecf20Sopenharmony_ci * Attribute is resident, implying it is not compressed, encrypted, or 15718c2ecf20Sopenharmony_ci * sparse. 15728c2ecf20Sopenharmony_ci */ 15738c2ecf20Sopenharmony_ci if (!NInoAttr(ni)) 15748c2ecf20Sopenharmony_ci base_ni = ni; 15758c2ecf20Sopenharmony_ci else 15768c2ecf20Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 15778c2ecf20Sopenharmony_ci BUG_ON(NInoNonResident(ni)); 15788c2ecf20Sopenharmony_ci /* Map, pin, and lock the mft record. */ 15798c2ecf20Sopenharmony_ci m = map_mft_record(base_ni); 15808c2ecf20Sopenharmony_ci if (IS_ERR(m)) { 15818c2ecf20Sopenharmony_ci err = PTR_ERR(m); 15828c2ecf20Sopenharmony_ci m = NULL; 15838c2ecf20Sopenharmony_ci ctx = NULL; 15848c2ecf20Sopenharmony_ci goto err_out; 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 15878c2ecf20Sopenharmony_ci if (unlikely(!ctx)) { 15888c2ecf20Sopenharmony_ci err = -ENOMEM; 15898c2ecf20Sopenharmony_ci goto err_out; 15908c2ecf20Sopenharmony_ci } 15918c2ecf20Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 15928c2ecf20Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 15938c2ecf20Sopenharmony_ci if (unlikely(err)) { 15948c2ecf20Sopenharmony_ci if (err == -ENOENT) 15958c2ecf20Sopenharmony_ci err = -EIO; 15968c2ecf20Sopenharmony_ci goto err_out; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci a = ctx->attr; 15998c2ecf20Sopenharmony_ci BUG_ON(a->non_resident); 16008c2ecf20Sopenharmony_ci /* The total length of the attribute value. */ 16018c2ecf20Sopenharmony_ci attr_len = le32_to_cpu(a->data.resident.value_length); 16028c2ecf20Sopenharmony_ci i_size = i_size_read(vi); 16038c2ecf20Sopenharmony_ci BUG_ON(attr_len != i_size); 16048c2ecf20Sopenharmony_ci BUG_ON(pos > attr_len); 16058c2ecf20Sopenharmony_ci end = pos + bytes; 16068c2ecf20Sopenharmony_ci BUG_ON(end > le32_to_cpu(a->length) - 16078c2ecf20Sopenharmony_ci le16_to_cpu(a->data.resident.value_offset)); 16088c2ecf20Sopenharmony_ci kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset); 16098c2ecf20Sopenharmony_ci kaddr = kmap_atomic(page); 16108c2ecf20Sopenharmony_ci /* Copy the received data from the page to the mft record. */ 16118c2ecf20Sopenharmony_ci memcpy(kattr + pos, kaddr + pos, bytes); 16128c2ecf20Sopenharmony_ci /* Update the attribute length if necessary. */ 16138c2ecf20Sopenharmony_ci if (end > attr_len) { 16148c2ecf20Sopenharmony_ci attr_len = end; 16158c2ecf20Sopenharmony_ci a->data.resident.value_length = cpu_to_le32(attr_len); 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci /* 16188c2ecf20Sopenharmony_ci * If the page is not uptodate, bring the out of bounds area(s) 16198c2ecf20Sopenharmony_ci * uptodate by copying data from the mft record to the page. 16208c2ecf20Sopenharmony_ci */ 16218c2ecf20Sopenharmony_ci if (!PageUptodate(page)) { 16228c2ecf20Sopenharmony_ci if (pos > 0) 16238c2ecf20Sopenharmony_ci memcpy(kaddr, kattr, pos); 16248c2ecf20Sopenharmony_ci if (end < attr_len) 16258c2ecf20Sopenharmony_ci memcpy(kaddr + end, kattr + end, attr_len - end); 16268c2ecf20Sopenharmony_ci /* Zero the region outside the end of the attribute value. */ 16278c2ecf20Sopenharmony_ci memset(kaddr + attr_len, 0, PAGE_SIZE - attr_len); 16288c2ecf20Sopenharmony_ci flush_dcache_page(page); 16298c2ecf20Sopenharmony_ci SetPageUptodate(page); 16308c2ecf20Sopenharmony_ci } 16318c2ecf20Sopenharmony_ci kunmap_atomic(kaddr); 16328c2ecf20Sopenharmony_ci /* Update initialized_size/i_size if necessary. */ 16338c2ecf20Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 16348c2ecf20Sopenharmony_ci initialized_size = ni->initialized_size; 16358c2ecf20Sopenharmony_ci BUG_ON(end > ni->allocated_size); 16368c2ecf20Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 16378c2ecf20Sopenharmony_ci BUG_ON(initialized_size != i_size); 16388c2ecf20Sopenharmony_ci if (end > initialized_size) { 16398c2ecf20Sopenharmony_ci write_lock_irqsave(&ni->size_lock, flags); 16408c2ecf20Sopenharmony_ci ni->initialized_size = end; 16418c2ecf20Sopenharmony_ci i_size_write(vi, end); 16428c2ecf20Sopenharmony_ci write_unlock_irqrestore(&ni->size_lock, flags); 16438c2ecf20Sopenharmony_ci } 16448c2ecf20Sopenharmony_ci /* Mark the mft record dirty, so it gets written back. */ 16458c2ecf20Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 16468c2ecf20Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 16478c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 16488c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 16498c2ecf20Sopenharmony_ci ntfs_debug("Done."); 16508c2ecf20Sopenharmony_ci return 0; 16518c2ecf20Sopenharmony_cierr_out: 16528c2ecf20Sopenharmony_ci if (err == -ENOMEM) { 16538c2ecf20Sopenharmony_ci ntfs_warning(vi->i_sb, "Error allocating memory required to " 16548c2ecf20Sopenharmony_ci "commit the write."); 16558c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 16568c2ecf20Sopenharmony_ci ntfs_warning(vi->i_sb, "Page is uptodate, setting " 16578c2ecf20Sopenharmony_ci "dirty so the write will be retried " 16588c2ecf20Sopenharmony_ci "later on by the VM."); 16598c2ecf20Sopenharmony_ci /* 16608c2ecf20Sopenharmony_ci * Put the page on mapping->dirty_pages, but leave its 16618c2ecf20Sopenharmony_ci * buffers' dirty state as-is. 16628c2ecf20Sopenharmony_ci */ 16638c2ecf20Sopenharmony_ci __set_page_dirty_nobuffers(page); 16648c2ecf20Sopenharmony_ci err = 0; 16658c2ecf20Sopenharmony_ci } else 16668c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Page is not uptodate. Written " 16678c2ecf20Sopenharmony_ci "data has been lost."); 16688c2ecf20Sopenharmony_ci } else { 16698c2ecf20Sopenharmony_ci ntfs_error(vi->i_sb, "Resident attribute commit write failed " 16708c2ecf20Sopenharmony_ci "with error %i.", err); 16718c2ecf20Sopenharmony_ci NVolSetErrors(ni->vol); 16728c2ecf20Sopenharmony_ci } 16738c2ecf20Sopenharmony_ci if (ctx) 16748c2ecf20Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 16758c2ecf20Sopenharmony_ci if (m) 16768c2ecf20Sopenharmony_ci unmap_mft_record(base_ni); 16778c2ecf20Sopenharmony_ci return err; 16788c2ecf20Sopenharmony_ci} 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci/* 16818c2ecf20Sopenharmony_ci * Copy as much as we can into the pages and return the number of bytes which 16828c2ecf20Sopenharmony_ci * were successfully copied. If a fault is encountered then clear the pages 16838c2ecf20Sopenharmony_ci * out to (ofs + bytes) and return the number of bytes which were copied. 16848c2ecf20Sopenharmony_ci */ 16858c2ecf20Sopenharmony_cistatic size_t ntfs_copy_from_user_iter(struct page **pages, unsigned nr_pages, 16868c2ecf20Sopenharmony_ci unsigned ofs, struct iov_iter *i, size_t bytes) 16878c2ecf20Sopenharmony_ci{ 16888c2ecf20Sopenharmony_ci struct page **last_page = pages + nr_pages; 16898c2ecf20Sopenharmony_ci size_t total = 0; 16908c2ecf20Sopenharmony_ci struct iov_iter data = *i; 16918c2ecf20Sopenharmony_ci unsigned len, copied; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci do { 16948c2ecf20Sopenharmony_ci len = PAGE_SIZE - ofs; 16958c2ecf20Sopenharmony_ci if (len > bytes) 16968c2ecf20Sopenharmony_ci len = bytes; 16978c2ecf20Sopenharmony_ci copied = iov_iter_copy_from_user_atomic(*pages, &data, ofs, 16988c2ecf20Sopenharmony_ci len); 16998c2ecf20Sopenharmony_ci total += copied; 17008c2ecf20Sopenharmony_ci bytes -= copied; 17018c2ecf20Sopenharmony_ci if (!bytes) 17028c2ecf20Sopenharmony_ci break; 17038c2ecf20Sopenharmony_ci iov_iter_advance(&data, copied); 17048c2ecf20Sopenharmony_ci if (copied < len) 17058c2ecf20Sopenharmony_ci goto err; 17068c2ecf20Sopenharmony_ci ofs = 0; 17078c2ecf20Sopenharmony_ci } while (++pages < last_page); 17088c2ecf20Sopenharmony_ciout: 17098c2ecf20Sopenharmony_ci return total; 17108c2ecf20Sopenharmony_cierr: 17118c2ecf20Sopenharmony_ci /* Zero the rest of the target like __copy_from_user(). */ 17128c2ecf20Sopenharmony_ci len = PAGE_SIZE - copied; 17138c2ecf20Sopenharmony_ci do { 17148c2ecf20Sopenharmony_ci if (len > bytes) 17158c2ecf20Sopenharmony_ci len = bytes; 17168c2ecf20Sopenharmony_ci zero_user(*pages, copied, len); 17178c2ecf20Sopenharmony_ci bytes -= len; 17188c2ecf20Sopenharmony_ci copied = 0; 17198c2ecf20Sopenharmony_ci len = PAGE_SIZE; 17208c2ecf20Sopenharmony_ci } while (++pages < last_page); 17218c2ecf20Sopenharmony_ci goto out; 17228c2ecf20Sopenharmony_ci} 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci/** 17258c2ecf20Sopenharmony_ci * ntfs_perform_write - perform buffered write to a file 17268c2ecf20Sopenharmony_ci * @file: file to write to 17278c2ecf20Sopenharmony_ci * @i: iov_iter with data to write 17288c2ecf20Sopenharmony_ci * @pos: byte offset in file at which to begin writing to 17298c2ecf20Sopenharmony_ci */ 17308c2ecf20Sopenharmony_cistatic ssize_t ntfs_perform_write(struct file *file, struct iov_iter *i, 17318c2ecf20Sopenharmony_ci loff_t pos) 17328c2ecf20Sopenharmony_ci{ 17338c2ecf20Sopenharmony_ci struct address_space *mapping = file->f_mapping; 17348c2ecf20Sopenharmony_ci struct inode *vi = mapping->host; 17358c2ecf20Sopenharmony_ci ntfs_inode *ni = NTFS_I(vi); 17368c2ecf20Sopenharmony_ci ntfs_volume *vol = ni->vol; 17378c2ecf20Sopenharmony_ci struct page *pages[NTFS_MAX_PAGES_PER_CLUSTER]; 17388c2ecf20Sopenharmony_ci struct page *cached_page = NULL; 17398c2ecf20Sopenharmony_ci VCN last_vcn; 17408c2ecf20Sopenharmony_ci LCN lcn; 17418c2ecf20Sopenharmony_ci size_t bytes; 17428c2ecf20Sopenharmony_ci ssize_t status, written = 0; 17438c2ecf20Sopenharmony_ci unsigned nr_pages; 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos " 17468c2ecf20Sopenharmony_ci "0x%llx, count 0x%lx.", vi->i_ino, 17478c2ecf20Sopenharmony_ci (unsigned)le32_to_cpu(ni->type), 17488c2ecf20Sopenharmony_ci (unsigned long long)pos, 17498c2ecf20Sopenharmony_ci (unsigned long)iov_iter_count(i)); 17508c2ecf20Sopenharmony_ci /* 17518c2ecf20Sopenharmony_ci * If a previous ntfs_truncate() failed, repeat it and abort if it 17528c2ecf20Sopenharmony_ci * fails again. 17538c2ecf20Sopenharmony_ci */ 17548c2ecf20Sopenharmony_ci if (unlikely(NInoTruncateFailed(ni))) { 17558c2ecf20Sopenharmony_ci int err; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci inode_dio_wait(vi); 17588c2ecf20Sopenharmony_ci err = ntfs_truncate(vi); 17598c2ecf20Sopenharmony_ci if (err || NInoTruncateFailed(ni)) { 17608c2ecf20Sopenharmony_ci if (!err) 17618c2ecf20Sopenharmony_ci err = -EIO; 17628c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Cannot perform write to inode " 17638c2ecf20Sopenharmony_ci "0x%lx, attribute type 0x%x, because " 17648c2ecf20Sopenharmony_ci "ntfs_truncate() failed (error code " 17658c2ecf20Sopenharmony_ci "%i).", vi->i_ino, 17668c2ecf20Sopenharmony_ci (unsigned)le32_to_cpu(ni->type), err); 17678c2ecf20Sopenharmony_ci return err; 17688c2ecf20Sopenharmony_ci } 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci /* 17718c2ecf20Sopenharmony_ci * Determine the number of pages per cluster for non-resident 17728c2ecf20Sopenharmony_ci * attributes. 17738c2ecf20Sopenharmony_ci */ 17748c2ecf20Sopenharmony_ci nr_pages = 1; 17758c2ecf20Sopenharmony_ci if (vol->cluster_size > PAGE_SIZE && NInoNonResident(ni)) 17768c2ecf20Sopenharmony_ci nr_pages = vol->cluster_size >> PAGE_SHIFT; 17778c2ecf20Sopenharmony_ci last_vcn = -1; 17788c2ecf20Sopenharmony_ci do { 17798c2ecf20Sopenharmony_ci VCN vcn; 17808c2ecf20Sopenharmony_ci pgoff_t idx, start_idx; 17818c2ecf20Sopenharmony_ci unsigned ofs, do_pages, u; 17828c2ecf20Sopenharmony_ci size_t copied; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci start_idx = idx = pos >> PAGE_SHIFT; 17858c2ecf20Sopenharmony_ci ofs = pos & ~PAGE_MASK; 17868c2ecf20Sopenharmony_ci bytes = PAGE_SIZE - ofs; 17878c2ecf20Sopenharmony_ci do_pages = 1; 17888c2ecf20Sopenharmony_ci if (nr_pages > 1) { 17898c2ecf20Sopenharmony_ci vcn = pos >> vol->cluster_size_bits; 17908c2ecf20Sopenharmony_ci if (vcn != last_vcn) { 17918c2ecf20Sopenharmony_ci last_vcn = vcn; 17928c2ecf20Sopenharmony_ci /* 17938c2ecf20Sopenharmony_ci * Get the lcn of the vcn the write is in. If 17948c2ecf20Sopenharmony_ci * it is a hole, need to lock down all pages in 17958c2ecf20Sopenharmony_ci * the cluster. 17968c2ecf20Sopenharmony_ci */ 17978c2ecf20Sopenharmony_ci down_read(&ni->runlist.lock); 17988c2ecf20Sopenharmony_ci lcn = ntfs_attr_vcn_to_lcn_nolock(ni, pos >> 17998c2ecf20Sopenharmony_ci vol->cluster_size_bits, false); 18008c2ecf20Sopenharmony_ci up_read(&ni->runlist.lock); 18018c2ecf20Sopenharmony_ci if (unlikely(lcn < LCN_HOLE)) { 18028c2ecf20Sopenharmony_ci if (lcn == LCN_ENOMEM) 18038c2ecf20Sopenharmony_ci status = -ENOMEM; 18048c2ecf20Sopenharmony_ci else { 18058c2ecf20Sopenharmony_ci status = -EIO; 18068c2ecf20Sopenharmony_ci ntfs_error(vol->sb, "Cannot " 18078c2ecf20Sopenharmony_ci "perform write to " 18088c2ecf20Sopenharmony_ci "inode 0x%lx, " 18098c2ecf20Sopenharmony_ci "attribute type 0x%x, " 18108c2ecf20Sopenharmony_ci "because the attribute " 18118c2ecf20Sopenharmony_ci "is corrupt.", 18128c2ecf20Sopenharmony_ci vi->i_ino, (unsigned) 18138c2ecf20Sopenharmony_ci le32_to_cpu(ni->type)); 18148c2ecf20Sopenharmony_ci } 18158c2ecf20Sopenharmony_ci break; 18168c2ecf20Sopenharmony_ci } 18178c2ecf20Sopenharmony_ci if (lcn == LCN_HOLE) { 18188c2ecf20Sopenharmony_ci start_idx = (pos & ~(s64) 18198c2ecf20Sopenharmony_ci vol->cluster_size_mask) 18208c2ecf20Sopenharmony_ci >> PAGE_SHIFT; 18218c2ecf20Sopenharmony_ci bytes = vol->cluster_size - (pos & 18228c2ecf20Sopenharmony_ci vol->cluster_size_mask); 18238c2ecf20Sopenharmony_ci do_pages = nr_pages; 18248c2ecf20Sopenharmony_ci } 18258c2ecf20Sopenharmony_ci } 18268c2ecf20Sopenharmony_ci } 18278c2ecf20Sopenharmony_ci if (bytes > iov_iter_count(i)) 18288c2ecf20Sopenharmony_ci bytes = iov_iter_count(i); 18298c2ecf20Sopenharmony_ciagain: 18308c2ecf20Sopenharmony_ci /* 18318c2ecf20Sopenharmony_ci * Bring in the user page(s) that we will copy from _first_. 18328c2ecf20Sopenharmony_ci * Otherwise there is a nasty deadlock on copying from the same 18338c2ecf20Sopenharmony_ci * page(s) as we are writing to, without it/them being marked 18348c2ecf20Sopenharmony_ci * up-to-date. Note, at present there is nothing to stop the 18358c2ecf20Sopenharmony_ci * pages being swapped out between us bringing them into memory 18368c2ecf20Sopenharmony_ci * and doing the actual copying. 18378c2ecf20Sopenharmony_ci */ 18388c2ecf20Sopenharmony_ci if (unlikely(iov_iter_fault_in_readable(i, bytes))) { 18398c2ecf20Sopenharmony_ci status = -EFAULT; 18408c2ecf20Sopenharmony_ci break; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci /* Get and lock @do_pages starting at index @start_idx. */ 18438c2ecf20Sopenharmony_ci status = __ntfs_grab_cache_pages(mapping, start_idx, do_pages, 18448c2ecf20Sopenharmony_ci pages, &cached_page); 18458c2ecf20Sopenharmony_ci if (unlikely(status)) 18468c2ecf20Sopenharmony_ci break; 18478c2ecf20Sopenharmony_ci /* 18488c2ecf20Sopenharmony_ci * For non-resident attributes, we need to fill any holes with 18498c2ecf20Sopenharmony_ci * actual clusters and ensure all bufferes are mapped. We also 18508c2ecf20Sopenharmony_ci * need to bring uptodate any buffers that are only partially 18518c2ecf20Sopenharmony_ci * being written to. 18528c2ecf20Sopenharmony_ci */ 18538c2ecf20Sopenharmony_ci if (NInoNonResident(ni)) { 18548c2ecf20Sopenharmony_ci status = ntfs_prepare_pages_for_non_resident_write( 18558c2ecf20Sopenharmony_ci pages, do_pages, pos, bytes); 18568c2ecf20Sopenharmony_ci if (unlikely(status)) { 18578c2ecf20Sopenharmony_ci do { 18588c2ecf20Sopenharmony_ci unlock_page(pages[--do_pages]); 18598c2ecf20Sopenharmony_ci put_page(pages[do_pages]); 18608c2ecf20Sopenharmony_ci } while (do_pages); 18618c2ecf20Sopenharmony_ci break; 18628c2ecf20Sopenharmony_ci } 18638c2ecf20Sopenharmony_ci } 18648c2ecf20Sopenharmony_ci u = (pos >> PAGE_SHIFT) - pages[0]->index; 18658c2ecf20Sopenharmony_ci copied = ntfs_copy_from_user_iter(pages + u, do_pages - u, ofs, 18668c2ecf20Sopenharmony_ci i, bytes); 18678c2ecf20Sopenharmony_ci ntfs_flush_dcache_pages(pages + u, do_pages - u); 18688c2ecf20Sopenharmony_ci status = 0; 18698c2ecf20Sopenharmony_ci if (likely(copied == bytes)) { 18708c2ecf20Sopenharmony_ci status = ntfs_commit_pages_after_write(pages, do_pages, 18718c2ecf20Sopenharmony_ci pos, bytes); 18728c2ecf20Sopenharmony_ci if (!status) 18738c2ecf20Sopenharmony_ci status = bytes; 18748c2ecf20Sopenharmony_ci } 18758c2ecf20Sopenharmony_ci do { 18768c2ecf20Sopenharmony_ci unlock_page(pages[--do_pages]); 18778c2ecf20Sopenharmony_ci put_page(pages[do_pages]); 18788c2ecf20Sopenharmony_ci } while (do_pages); 18798c2ecf20Sopenharmony_ci if (unlikely(status < 0)) 18808c2ecf20Sopenharmony_ci break; 18818c2ecf20Sopenharmony_ci copied = status; 18828c2ecf20Sopenharmony_ci cond_resched(); 18838c2ecf20Sopenharmony_ci if (unlikely(!copied)) { 18848c2ecf20Sopenharmony_ci size_t sc; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci /* 18878c2ecf20Sopenharmony_ci * We failed to copy anything. Fall back to single 18888c2ecf20Sopenharmony_ci * segment length write. 18898c2ecf20Sopenharmony_ci * 18908c2ecf20Sopenharmony_ci * This is needed to avoid possible livelock in the 18918c2ecf20Sopenharmony_ci * case that all segments in the iov cannot be copied 18928c2ecf20Sopenharmony_ci * at once without a pagefault. 18938c2ecf20Sopenharmony_ci */ 18948c2ecf20Sopenharmony_ci sc = iov_iter_single_seg_count(i); 18958c2ecf20Sopenharmony_ci if (bytes > sc) 18968c2ecf20Sopenharmony_ci bytes = sc; 18978c2ecf20Sopenharmony_ci goto again; 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci iov_iter_advance(i, copied); 19008c2ecf20Sopenharmony_ci pos += copied; 19018c2ecf20Sopenharmony_ci written += copied; 19028c2ecf20Sopenharmony_ci balance_dirty_pages_ratelimited(mapping); 19038c2ecf20Sopenharmony_ci if (fatal_signal_pending(current)) { 19048c2ecf20Sopenharmony_ci status = -EINTR; 19058c2ecf20Sopenharmony_ci break; 19068c2ecf20Sopenharmony_ci } 19078c2ecf20Sopenharmony_ci } while (iov_iter_count(i)); 19088c2ecf20Sopenharmony_ci if (cached_page) 19098c2ecf20Sopenharmony_ci put_page(cached_page); 19108c2ecf20Sopenharmony_ci ntfs_debug("Done. Returning %s (written 0x%lx, status %li).", 19118c2ecf20Sopenharmony_ci written ? "written" : "status", (unsigned long)written, 19128c2ecf20Sopenharmony_ci (long)status); 19138c2ecf20Sopenharmony_ci return written ? written : status; 19148c2ecf20Sopenharmony_ci} 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci/** 19178c2ecf20Sopenharmony_ci * ntfs_file_write_iter - simple wrapper for ntfs_file_write_iter_nolock() 19188c2ecf20Sopenharmony_ci * @iocb: IO state structure 19198c2ecf20Sopenharmony_ci * @from: iov_iter with data to write 19208c2ecf20Sopenharmony_ci * 19218c2ecf20Sopenharmony_ci * Basically the same as generic_file_write_iter() except that it ends up 19228c2ecf20Sopenharmony_ci * up calling ntfs_perform_write() instead of generic_perform_write() and that 19238c2ecf20Sopenharmony_ci * O_DIRECT is not implemented. 19248c2ecf20Sopenharmony_ci */ 19258c2ecf20Sopenharmony_cistatic ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 19268c2ecf20Sopenharmony_ci{ 19278c2ecf20Sopenharmony_ci struct file *file = iocb->ki_filp; 19288c2ecf20Sopenharmony_ci struct inode *vi = file_inode(file); 19298c2ecf20Sopenharmony_ci ssize_t written = 0; 19308c2ecf20Sopenharmony_ci ssize_t err; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci inode_lock(vi); 19338c2ecf20Sopenharmony_ci /* We can write back this queue in page reclaim. */ 19348c2ecf20Sopenharmony_ci current->backing_dev_info = inode_to_bdi(vi); 19358c2ecf20Sopenharmony_ci err = ntfs_prepare_file_for_write(iocb, from); 19368c2ecf20Sopenharmony_ci if (iov_iter_count(from) && !err) 19378c2ecf20Sopenharmony_ci written = ntfs_perform_write(file, from, iocb->ki_pos); 19388c2ecf20Sopenharmony_ci current->backing_dev_info = NULL; 19398c2ecf20Sopenharmony_ci inode_unlock(vi); 19408c2ecf20Sopenharmony_ci iocb->ki_pos += written; 19418c2ecf20Sopenharmony_ci if (likely(written > 0)) 19428c2ecf20Sopenharmony_ci written = generic_write_sync(iocb, written); 19438c2ecf20Sopenharmony_ci return written ? written : err; 19448c2ecf20Sopenharmony_ci} 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci/** 19478c2ecf20Sopenharmony_ci * ntfs_file_fsync - sync a file to disk 19488c2ecf20Sopenharmony_ci * @filp: file to be synced 19498c2ecf20Sopenharmony_ci * @datasync: if non-zero only flush user data and not metadata 19508c2ecf20Sopenharmony_ci * 19518c2ecf20Sopenharmony_ci * Data integrity sync of a file to disk. Used for fsync, fdatasync, and msync 19528c2ecf20Sopenharmony_ci * system calls. This function is inspired by fs/buffer.c::file_fsync(). 19538c2ecf20Sopenharmony_ci * 19548c2ecf20Sopenharmony_ci * If @datasync is false, write the mft record and all associated extent mft 19558c2ecf20Sopenharmony_ci * records as well as the $DATA attribute and then sync the block device. 19568c2ecf20Sopenharmony_ci * 19578c2ecf20Sopenharmony_ci * If @datasync is true and the attribute is non-resident, we skip the writing 19588c2ecf20Sopenharmony_ci * of the mft record and all associated extent mft records (this might still 19598c2ecf20Sopenharmony_ci * happen due to the write_inode_now() call). 19608c2ecf20Sopenharmony_ci * 19618c2ecf20Sopenharmony_ci * Also, if @datasync is true, we do not wait on the inode to be written out 19628c2ecf20Sopenharmony_ci * but we always wait on the page cache pages to be written out. 19638c2ecf20Sopenharmony_ci * 19648c2ecf20Sopenharmony_ci * Locking: Caller must hold i_mutex on the inode. 19658c2ecf20Sopenharmony_ci * 19668c2ecf20Sopenharmony_ci * TODO: We should probably also write all attribute/index inodes associated 19678c2ecf20Sopenharmony_ci * with this inode but since we have no simple way of getting to them we ignore 19688c2ecf20Sopenharmony_ci * this problem for now. 19698c2ecf20Sopenharmony_ci */ 19708c2ecf20Sopenharmony_cistatic int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end, 19718c2ecf20Sopenharmony_ci int datasync) 19728c2ecf20Sopenharmony_ci{ 19738c2ecf20Sopenharmony_ci struct inode *vi = filp->f_mapping->host; 19748c2ecf20Sopenharmony_ci int err, ret = 0; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci err = file_write_and_wait_range(filp, start, end); 19798c2ecf20Sopenharmony_ci if (err) 19808c2ecf20Sopenharmony_ci return err; 19818c2ecf20Sopenharmony_ci inode_lock(vi); 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci BUG_ON(S_ISDIR(vi->i_mode)); 19848c2ecf20Sopenharmony_ci if (!datasync || !NInoNonResident(NTFS_I(vi))) 19858c2ecf20Sopenharmony_ci ret = __ntfs_write_inode(vi, 1); 19868c2ecf20Sopenharmony_ci write_inode_now(vi, !datasync); 19878c2ecf20Sopenharmony_ci /* 19888c2ecf20Sopenharmony_ci * NOTE: If we were to use mapping->private_list (see ext2 and 19898c2ecf20Sopenharmony_ci * fs/buffer.c) for dirty blocks then we could optimize the below to be 19908c2ecf20Sopenharmony_ci * sync_mapping_buffers(vi->i_mapping). 19918c2ecf20Sopenharmony_ci */ 19928c2ecf20Sopenharmony_ci err = sync_blockdev(vi->i_sb->s_bdev); 19938c2ecf20Sopenharmony_ci if (unlikely(err && !ret)) 19948c2ecf20Sopenharmony_ci ret = err; 19958c2ecf20Sopenharmony_ci if (likely(!ret)) 19968c2ecf20Sopenharmony_ci ntfs_debug("Done."); 19978c2ecf20Sopenharmony_ci else 19988c2ecf20Sopenharmony_ci ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx. Error " 19998c2ecf20Sopenharmony_ci "%u.", datasync ? "data" : "", vi->i_ino, -ret); 20008c2ecf20Sopenharmony_ci inode_unlock(vi); 20018c2ecf20Sopenharmony_ci return ret; 20028c2ecf20Sopenharmony_ci} 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci#endif /* NTFS_RW */ 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ciconst struct file_operations ntfs_file_ops = { 20078c2ecf20Sopenharmony_ci .llseek = generic_file_llseek, 20088c2ecf20Sopenharmony_ci .read_iter = generic_file_read_iter, 20098c2ecf20Sopenharmony_ci#ifdef NTFS_RW 20108c2ecf20Sopenharmony_ci .write_iter = ntfs_file_write_iter, 20118c2ecf20Sopenharmony_ci .fsync = ntfs_file_fsync, 20128c2ecf20Sopenharmony_ci#endif /* NTFS_RW */ 20138c2ecf20Sopenharmony_ci .mmap = generic_file_mmap, 20148c2ecf20Sopenharmony_ci .open = ntfs_file_open, 20158c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 20168c2ecf20Sopenharmony_ci}; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ciconst struct inode_operations ntfs_file_inode_ops = { 20198c2ecf20Sopenharmony_ci#ifdef NTFS_RW 20208c2ecf20Sopenharmony_ci .setattr = ntfs_setattr, 20218c2ecf20Sopenharmony_ci#endif /* NTFS_RW */ 20228c2ecf20Sopenharmony_ci}; 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ciconst struct file_operations ntfs_empty_file_ops = {}; 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ciconst struct inode_operations ntfs_empty_inode_ops = {}; 2027