162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * aops.c - NTFS kernel address space operations and page cache handling. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc. 662306a36Sopenharmony_ci * Copyright (c) 2002 Richard Russon 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/errno.h> 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/gfp.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/pagemap.h> 1462306a36Sopenharmony_ci#include <linux/swap.h> 1562306a36Sopenharmony_ci#include <linux/buffer_head.h> 1662306a36Sopenharmony_ci#include <linux/writeback.h> 1762306a36Sopenharmony_ci#include <linux/bit_spinlock.h> 1862306a36Sopenharmony_ci#include <linux/bio.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "aops.h" 2162306a36Sopenharmony_ci#include "attrib.h" 2262306a36Sopenharmony_ci#include "debug.h" 2362306a36Sopenharmony_ci#include "inode.h" 2462306a36Sopenharmony_ci#include "mft.h" 2562306a36Sopenharmony_ci#include "runlist.h" 2662306a36Sopenharmony_ci#include "types.h" 2762306a36Sopenharmony_ci#include "ntfs.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * ntfs_end_buffer_async_read - async io completion for reading attributes 3162306a36Sopenharmony_ci * @bh: buffer head on which io is completed 3262306a36Sopenharmony_ci * @uptodate: whether @bh is now uptodate or not 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * Asynchronous I/O completion handler for reading pages belonging to the 3562306a36Sopenharmony_ci * attribute address space of an inode. The inodes can either be files or 3662306a36Sopenharmony_ci * directories or they can be fake inodes describing some attribute. 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * If NInoMstProtected(), perform the post read mst fixups when all IO on the 3962306a36Sopenharmony_ci * page has been completed and mark the page uptodate or set the error bit on 4062306a36Sopenharmony_ci * the page. To determine the size of the records that need fixing up, we 4162306a36Sopenharmony_ci * cheat a little bit by setting the index_block_size in ntfs_inode to the ntfs 4262306a36Sopenharmony_ci * record size, and index_block_size_bits, to the log(base 2) of the ntfs 4362306a36Sopenharmony_ci * record size. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_cistatic void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci unsigned long flags; 4862306a36Sopenharmony_ci struct buffer_head *first, *tmp; 4962306a36Sopenharmony_ci struct page *page; 5062306a36Sopenharmony_ci struct inode *vi; 5162306a36Sopenharmony_ci ntfs_inode *ni; 5262306a36Sopenharmony_ci int page_uptodate = 1; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci page = bh->b_page; 5562306a36Sopenharmony_ci vi = page->mapping->host; 5662306a36Sopenharmony_ci ni = NTFS_I(vi); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (likely(uptodate)) { 5962306a36Sopenharmony_ci loff_t i_size; 6062306a36Sopenharmony_ci s64 file_ofs, init_size; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci set_buffer_uptodate(bh); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci file_ofs = ((s64)page->index << PAGE_SHIFT) + 6562306a36Sopenharmony_ci bh_offset(bh); 6662306a36Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 6762306a36Sopenharmony_ci init_size = ni->initialized_size; 6862306a36Sopenharmony_ci i_size = i_size_read(vi); 6962306a36Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 7062306a36Sopenharmony_ci if (unlikely(init_size > i_size)) { 7162306a36Sopenharmony_ci /* Race with shrinking truncate. */ 7262306a36Sopenharmony_ci init_size = i_size; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci /* Check for the current buffer head overflowing. */ 7562306a36Sopenharmony_ci if (unlikely(file_ofs + bh->b_size > init_size)) { 7662306a36Sopenharmony_ci int ofs; 7762306a36Sopenharmony_ci void *kaddr; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci ofs = 0; 8062306a36Sopenharmony_ci if (file_ofs < init_size) 8162306a36Sopenharmony_ci ofs = init_size - file_ofs; 8262306a36Sopenharmony_ci kaddr = kmap_atomic(page); 8362306a36Sopenharmony_ci memset(kaddr + bh_offset(bh) + ofs, 0, 8462306a36Sopenharmony_ci bh->b_size - ofs); 8562306a36Sopenharmony_ci flush_dcache_page(page); 8662306a36Sopenharmony_ci kunmap_atomic(kaddr); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci } else { 8962306a36Sopenharmony_ci clear_buffer_uptodate(bh); 9062306a36Sopenharmony_ci SetPageError(page); 9162306a36Sopenharmony_ci ntfs_error(ni->vol->sb, "Buffer I/O error, logical block " 9262306a36Sopenharmony_ci "0x%llx.", (unsigned long long)bh->b_blocknr); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci first = page_buffers(page); 9562306a36Sopenharmony_ci spin_lock_irqsave(&first->b_uptodate_lock, flags); 9662306a36Sopenharmony_ci clear_buffer_async_read(bh); 9762306a36Sopenharmony_ci unlock_buffer(bh); 9862306a36Sopenharmony_ci tmp = bh; 9962306a36Sopenharmony_ci do { 10062306a36Sopenharmony_ci if (!buffer_uptodate(tmp)) 10162306a36Sopenharmony_ci page_uptodate = 0; 10262306a36Sopenharmony_ci if (buffer_async_read(tmp)) { 10362306a36Sopenharmony_ci if (likely(buffer_locked(tmp))) 10462306a36Sopenharmony_ci goto still_busy; 10562306a36Sopenharmony_ci /* Async buffers must be locked. */ 10662306a36Sopenharmony_ci BUG(); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci tmp = tmp->b_this_page; 10962306a36Sopenharmony_ci } while (tmp != bh); 11062306a36Sopenharmony_ci spin_unlock_irqrestore(&first->b_uptodate_lock, flags); 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * If none of the buffers had errors then we can set the page uptodate, 11362306a36Sopenharmony_ci * but we first have to perform the post read mst fixups, if the 11462306a36Sopenharmony_ci * attribute is mst protected, i.e. if NInoMstProteced(ni) is true. 11562306a36Sopenharmony_ci * Note we ignore fixup errors as those are detected when 11662306a36Sopenharmony_ci * map_mft_record() is called which gives us per record granularity 11762306a36Sopenharmony_ci * rather than per page granularity. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci if (!NInoMstProtected(ni)) { 12062306a36Sopenharmony_ci if (likely(page_uptodate && !PageError(page))) 12162306a36Sopenharmony_ci SetPageUptodate(page); 12262306a36Sopenharmony_ci } else { 12362306a36Sopenharmony_ci u8 *kaddr; 12462306a36Sopenharmony_ci unsigned int i, recs; 12562306a36Sopenharmony_ci u32 rec_size; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci rec_size = ni->itype.index.block_size; 12862306a36Sopenharmony_ci recs = PAGE_SIZE / rec_size; 12962306a36Sopenharmony_ci /* Should have been verified before we got here... */ 13062306a36Sopenharmony_ci BUG_ON(!recs); 13162306a36Sopenharmony_ci kaddr = kmap_atomic(page); 13262306a36Sopenharmony_ci for (i = 0; i < recs; i++) 13362306a36Sopenharmony_ci post_read_mst_fixup((NTFS_RECORD*)(kaddr + 13462306a36Sopenharmony_ci i * rec_size), rec_size); 13562306a36Sopenharmony_ci kunmap_atomic(kaddr); 13662306a36Sopenharmony_ci flush_dcache_page(page); 13762306a36Sopenharmony_ci if (likely(page_uptodate && !PageError(page))) 13862306a36Sopenharmony_ci SetPageUptodate(page); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci unlock_page(page); 14162306a36Sopenharmony_ci return; 14262306a36Sopenharmony_cistill_busy: 14362306a36Sopenharmony_ci spin_unlock_irqrestore(&first->b_uptodate_lock, flags); 14462306a36Sopenharmony_ci return; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/** 14862306a36Sopenharmony_ci * ntfs_read_block - fill a @page of an address space with data 14962306a36Sopenharmony_ci * @page: page cache page to fill with data 15062306a36Sopenharmony_ci * 15162306a36Sopenharmony_ci * Fill the page @page of the address space belonging to the @page->host inode. 15262306a36Sopenharmony_ci * We read each buffer asynchronously and when all buffers are read in, our io 15362306a36Sopenharmony_ci * completion handler ntfs_end_buffer_read_async(), if required, automatically 15462306a36Sopenharmony_ci * applies the mst fixups to the page before finally marking it uptodate and 15562306a36Sopenharmony_ci * unlocking it. 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * We only enforce allocated_size limit because i_size is checked for in 15862306a36Sopenharmony_ci * generic_file_read(). 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * Return 0 on success and -errno on error. 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * Contains an adapted version of fs/buffer.c::block_read_full_folio(). 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_cistatic int ntfs_read_block(struct page *page) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci loff_t i_size; 16762306a36Sopenharmony_ci VCN vcn; 16862306a36Sopenharmony_ci LCN lcn; 16962306a36Sopenharmony_ci s64 init_size; 17062306a36Sopenharmony_ci struct inode *vi; 17162306a36Sopenharmony_ci ntfs_inode *ni; 17262306a36Sopenharmony_ci ntfs_volume *vol; 17362306a36Sopenharmony_ci runlist_element *rl; 17462306a36Sopenharmony_ci struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; 17562306a36Sopenharmony_ci sector_t iblock, lblock, zblock; 17662306a36Sopenharmony_ci unsigned long flags; 17762306a36Sopenharmony_ci unsigned int blocksize, vcn_ofs; 17862306a36Sopenharmony_ci int i, nr; 17962306a36Sopenharmony_ci unsigned char blocksize_bits; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci vi = page->mapping->host; 18262306a36Sopenharmony_ci ni = NTFS_I(vi); 18362306a36Sopenharmony_ci vol = ni->vol; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* $MFT/$DATA must have its complete runlist in memory at all times. */ 18662306a36Sopenharmony_ci BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci blocksize = vol->sb->s_blocksize; 18962306a36Sopenharmony_ci blocksize_bits = vol->sb->s_blocksize_bits; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (!page_has_buffers(page)) { 19262306a36Sopenharmony_ci create_empty_buffers(page, blocksize, 0); 19362306a36Sopenharmony_ci if (unlikely(!page_has_buffers(page))) { 19462306a36Sopenharmony_ci unlock_page(page); 19562306a36Sopenharmony_ci return -ENOMEM; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci bh = head = page_buffers(page); 19962306a36Sopenharmony_ci BUG_ON(!bh); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* 20262306a36Sopenharmony_ci * We may be racing with truncate. To avoid some of the problems we 20362306a36Sopenharmony_ci * now take a snapshot of the various sizes and use those for the whole 20462306a36Sopenharmony_ci * of the function. In case of an extending truncate it just means we 20562306a36Sopenharmony_ci * may leave some buffers unmapped which are now allocated. This is 20662306a36Sopenharmony_ci * not a problem since these buffers will just get mapped when a write 20762306a36Sopenharmony_ci * occurs. In case of a shrinking truncate, we will detect this later 20862306a36Sopenharmony_ci * on due to the runlist being incomplete and if the page is being 20962306a36Sopenharmony_ci * fully truncated, truncate will throw it away as soon as we unlock 21062306a36Sopenharmony_ci * it so no need to worry what we do with it. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci iblock = (s64)page->index << (PAGE_SHIFT - blocksize_bits); 21362306a36Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 21462306a36Sopenharmony_ci lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; 21562306a36Sopenharmony_ci init_size = ni->initialized_size; 21662306a36Sopenharmony_ci i_size = i_size_read(vi); 21762306a36Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 21862306a36Sopenharmony_ci if (unlikely(init_size > i_size)) { 21962306a36Sopenharmony_ci /* Race with shrinking truncate. */ 22062306a36Sopenharmony_ci init_size = i_size; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci zblock = (init_size + blocksize - 1) >> blocksize_bits; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* Loop through all the buffers in the page. */ 22562306a36Sopenharmony_ci rl = NULL; 22662306a36Sopenharmony_ci nr = i = 0; 22762306a36Sopenharmony_ci do { 22862306a36Sopenharmony_ci int err = 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (unlikely(buffer_uptodate(bh))) 23162306a36Sopenharmony_ci continue; 23262306a36Sopenharmony_ci if (unlikely(buffer_mapped(bh))) { 23362306a36Sopenharmony_ci arr[nr++] = bh; 23462306a36Sopenharmony_ci continue; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci bh->b_bdev = vol->sb->s_bdev; 23762306a36Sopenharmony_ci /* Is the block within the allowed limits? */ 23862306a36Sopenharmony_ci if (iblock < lblock) { 23962306a36Sopenharmony_ci bool is_retry = false; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* Convert iblock into corresponding vcn and offset. */ 24262306a36Sopenharmony_ci vcn = (VCN)iblock << blocksize_bits >> 24362306a36Sopenharmony_ci vol->cluster_size_bits; 24462306a36Sopenharmony_ci vcn_ofs = ((VCN)iblock << blocksize_bits) & 24562306a36Sopenharmony_ci vol->cluster_size_mask; 24662306a36Sopenharmony_ci if (!rl) { 24762306a36Sopenharmony_cilock_retry_remap: 24862306a36Sopenharmony_ci down_read(&ni->runlist.lock); 24962306a36Sopenharmony_ci rl = ni->runlist.rl; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci if (likely(rl != NULL)) { 25262306a36Sopenharmony_ci /* Seek to element containing target vcn. */ 25362306a36Sopenharmony_ci while (rl->length && rl[1].vcn <= vcn) 25462306a36Sopenharmony_ci rl++; 25562306a36Sopenharmony_ci lcn = ntfs_rl_vcn_to_lcn(rl, vcn); 25662306a36Sopenharmony_ci } else 25762306a36Sopenharmony_ci lcn = LCN_RL_NOT_MAPPED; 25862306a36Sopenharmony_ci /* Successful remap. */ 25962306a36Sopenharmony_ci if (lcn >= 0) { 26062306a36Sopenharmony_ci /* Setup buffer head to correct block. */ 26162306a36Sopenharmony_ci bh->b_blocknr = ((lcn << vol->cluster_size_bits) 26262306a36Sopenharmony_ci + vcn_ofs) >> blocksize_bits; 26362306a36Sopenharmony_ci set_buffer_mapped(bh); 26462306a36Sopenharmony_ci /* Only read initialized data blocks. */ 26562306a36Sopenharmony_ci if (iblock < zblock) { 26662306a36Sopenharmony_ci arr[nr++] = bh; 26762306a36Sopenharmony_ci continue; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci /* Fully non-initialized data block, zero it. */ 27062306a36Sopenharmony_ci goto handle_zblock; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci /* It is a hole, need to zero it. */ 27362306a36Sopenharmony_ci if (lcn == LCN_HOLE) 27462306a36Sopenharmony_ci goto handle_hole; 27562306a36Sopenharmony_ci /* If first try and runlist unmapped, map and retry. */ 27662306a36Sopenharmony_ci if (!is_retry && lcn == LCN_RL_NOT_MAPPED) { 27762306a36Sopenharmony_ci is_retry = true; 27862306a36Sopenharmony_ci /* 27962306a36Sopenharmony_ci * Attempt to map runlist, dropping lock for 28062306a36Sopenharmony_ci * the duration. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci up_read(&ni->runlist.lock); 28362306a36Sopenharmony_ci err = ntfs_map_runlist(ni, vcn); 28462306a36Sopenharmony_ci if (likely(!err)) 28562306a36Sopenharmony_ci goto lock_retry_remap; 28662306a36Sopenharmony_ci rl = NULL; 28762306a36Sopenharmony_ci } else if (!rl) 28862306a36Sopenharmony_ci up_read(&ni->runlist.lock); 28962306a36Sopenharmony_ci /* 29062306a36Sopenharmony_ci * If buffer is outside the runlist, treat it as a 29162306a36Sopenharmony_ci * hole. This can happen due to concurrent truncate 29262306a36Sopenharmony_ci * for example. 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_ci if (err == -ENOENT || lcn == LCN_ENOENT) { 29562306a36Sopenharmony_ci err = 0; 29662306a36Sopenharmony_ci goto handle_hole; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci /* Hard error, zero out region. */ 29962306a36Sopenharmony_ci if (!err) 30062306a36Sopenharmony_ci err = -EIO; 30162306a36Sopenharmony_ci bh->b_blocknr = -1; 30262306a36Sopenharmony_ci SetPageError(page); 30362306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to read from inode 0x%lx, " 30462306a36Sopenharmony_ci "attribute type 0x%x, vcn 0x%llx, " 30562306a36Sopenharmony_ci "offset 0x%x because its location on " 30662306a36Sopenharmony_ci "disk could not be determined%s " 30762306a36Sopenharmony_ci "(error code %i).", ni->mft_no, 30862306a36Sopenharmony_ci ni->type, (unsigned long long)vcn, 30962306a36Sopenharmony_ci vcn_ofs, is_retry ? " even after " 31062306a36Sopenharmony_ci "retrying" : "", err); 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci /* 31362306a36Sopenharmony_ci * Either iblock was outside lblock limits or 31462306a36Sopenharmony_ci * ntfs_rl_vcn_to_lcn() returned error. Just zero that portion 31562306a36Sopenharmony_ci * of the page and set the buffer uptodate. 31662306a36Sopenharmony_ci */ 31762306a36Sopenharmony_cihandle_hole: 31862306a36Sopenharmony_ci bh->b_blocknr = -1UL; 31962306a36Sopenharmony_ci clear_buffer_mapped(bh); 32062306a36Sopenharmony_cihandle_zblock: 32162306a36Sopenharmony_ci zero_user(page, i * blocksize, blocksize); 32262306a36Sopenharmony_ci if (likely(!err)) 32362306a36Sopenharmony_ci set_buffer_uptodate(bh); 32462306a36Sopenharmony_ci } while (i++, iblock++, (bh = bh->b_this_page) != head); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* Release the lock if we took it. */ 32762306a36Sopenharmony_ci if (rl) 32862306a36Sopenharmony_ci up_read(&ni->runlist.lock); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* Check we have at least one buffer ready for i/o. */ 33162306a36Sopenharmony_ci if (nr) { 33262306a36Sopenharmony_ci struct buffer_head *tbh; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* Lock the buffers. */ 33562306a36Sopenharmony_ci for (i = 0; i < nr; i++) { 33662306a36Sopenharmony_ci tbh = arr[i]; 33762306a36Sopenharmony_ci lock_buffer(tbh); 33862306a36Sopenharmony_ci tbh->b_end_io = ntfs_end_buffer_async_read; 33962306a36Sopenharmony_ci set_buffer_async_read(tbh); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci /* Finally, start i/o on the buffers. */ 34262306a36Sopenharmony_ci for (i = 0; i < nr; i++) { 34362306a36Sopenharmony_ci tbh = arr[i]; 34462306a36Sopenharmony_ci if (likely(!buffer_uptodate(tbh))) 34562306a36Sopenharmony_ci submit_bh(REQ_OP_READ, tbh); 34662306a36Sopenharmony_ci else 34762306a36Sopenharmony_ci ntfs_end_buffer_async_read(tbh, 1); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci return 0; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci /* No i/o was scheduled on any of the buffers. */ 35262306a36Sopenharmony_ci if (likely(!PageError(page))) 35362306a36Sopenharmony_ci SetPageUptodate(page); 35462306a36Sopenharmony_ci else /* Signal synchronous i/o error. */ 35562306a36Sopenharmony_ci nr = -EIO; 35662306a36Sopenharmony_ci unlock_page(page); 35762306a36Sopenharmony_ci return nr; 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci/** 36162306a36Sopenharmony_ci * ntfs_read_folio - fill a @folio of a @file with data from the device 36262306a36Sopenharmony_ci * @file: open file to which the folio @folio belongs or NULL 36362306a36Sopenharmony_ci * @folio: page cache folio to fill with data 36462306a36Sopenharmony_ci * 36562306a36Sopenharmony_ci * For non-resident attributes, ntfs_read_folio() fills the @folio of the open 36662306a36Sopenharmony_ci * file @file by calling the ntfs version of the generic block_read_full_folio() 36762306a36Sopenharmony_ci * function, ntfs_read_block(), which in turn creates and reads in the buffers 36862306a36Sopenharmony_ci * associated with the folio asynchronously. 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * For resident attributes, OTOH, ntfs_read_folio() fills @folio by copying the 37162306a36Sopenharmony_ci * data from the mft record (which at this stage is most likely in memory) and 37262306a36Sopenharmony_ci * fills the remainder with zeroes. Thus, in this case, I/O is synchronous, as 37362306a36Sopenharmony_ci * even if the mft record is not cached at this point in time, we need to wait 37462306a36Sopenharmony_ci * for it to be read in before we can do the copy. 37562306a36Sopenharmony_ci * 37662306a36Sopenharmony_ci * Return 0 on success and -errno on error. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_cistatic int ntfs_read_folio(struct file *file, struct folio *folio) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci struct page *page = &folio->page; 38162306a36Sopenharmony_ci loff_t i_size; 38262306a36Sopenharmony_ci struct inode *vi; 38362306a36Sopenharmony_ci ntfs_inode *ni, *base_ni; 38462306a36Sopenharmony_ci u8 *addr; 38562306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx; 38662306a36Sopenharmony_ci MFT_RECORD *mrec; 38762306a36Sopenharmony_ci unsigned long flags; 38862306a36Sopenharmony_ci u32 attr_len; 38962306a36Sopenharmony_ci int err = 0; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ciretry_readpage: 39262306a36Sopenharmony_ci BUG_ON(!PageLocked(page)); 39362306a36Sopenharmony_ci vi = page->mapping->host; 39462306a36Sopenharmony_ci i_size = i_size_read(vi); 39562306a36Sopenharmony_ci /* Is the page fully outside i_size? (truncate in progress) */ 39662306a36Sopenharmony_ci if (unlikely(page->index >= (i_size + PAGE_SIZE - 1) >> 39762306a36Sopenharmony_ci PAGE_SHIFT)) { 39862306a36Sopenharmony_ci zero_user(page, 0, PAGE_SIZE); 39962306a36Sopenharmony_ci ntfs_debug("Read outside i_size - truncated?"); 40062306a36Sopenharmony_ci goto done; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci /* 40362306a36Sopenharmony_ci * This can potentially happen because we clear PageUptodate() during 40462306a36Sopenharmony_ci * ntfs_writepage() of MstProtected() attributes. 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci if (PageUptodate(page)) { 40762306a36Sopenharmony_ci unlock_page(page); 40862306a36Sopenharmony_ci return 0; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci ni = NTFS_I(vi); 41162306a36Sopenharmony_ci /* 41262306a36Sopenharmony_ci * Only $DATA attributes can be encrypted and only unnamed $DATA 41362306a36Sopenharmony_ci * attributes can be compressed. Index root can have the flags set but 41462306a36Sopenharmony_ci * this means to create compressed/encrypted files, not that the 41562306a36Sopenharmony_ci * attribute is compressed/encrypted. Note we need to check for 41662306a36Sopenharmony_ci * AT_INDEX_ALLOCATION since this is the type of both directory and 41762306a36Sopenharmony_ci * index inodes. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci if (ni->type != AT_INDEX_ALLOCATION) { 42062306a36Sopenharmony_ci /* If attribute is encrypted, deny access, just like NT4. */ 42162306a36Sopenharmony_ci if (NInoEncrypted(ni)) { 42262306a36Sopenharmony_ci BUG_ON(ni->type != AT_DATA); 42362306a36Sopenharmony_ci err = -EACCES; 42462306a36Sopenharmony_ci goto err_out; 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci /* Compressed data streams are handled in compress.c. */ 42762306a36Sopenharmony_ci if (NInoNonResident(ni) && NInoCompressed(ni)) { 42862306a36Sopenharmony_ci BUG_ON(ni->type != AT_DATA); 42962306a36Sopenharmony_ci BUG_ON(ni->name_len); 43062306a36Sopenharmony_ci return ntfs_read_compressed_block(page); 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci /* NInoNonResident() == NInoIndexAllocPresent() */ 43462306a36Sopenharmony_ci if (NInoNonResident(ni)) { 43562306a36Sopenharmony_ci /* Normal, non-resident data stream. */ 43662306a36Sopenharmony_ci return ntfs_read_block(page); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci /* 43962306a36Sopenharmony_ci * Attribute is resident, implying it is not compressed or encrypted. 44062306a36Sopenharmony_ci * This also means the attribute is smaller than an mft record and 44162306a36Sopenharmony_ci * hence smaller than a page, so can simply zero out any pages with 44262306a36Sopenharmony_ci * index above 0. Note the attribute can actually be marked compressed 44362306a36Sopenharmony_ci * but if it is resident the actual data is not compressed so we are 44462306a36Sopenharmony_ci * ok to ignore the compressed flag here. 44562306a36Sopenharmony_ci */ 44662306a36Sopenharmony_ci if (unlikely(page->index > 0)) { 44762306a36Sopenharmony_ci zero_user(page, 0, PAGE_SIZE); 44862306a36Sopenharmony_ci goto done; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci if (!NInoAttr(ni)) 45162306a36Sopenharmony_ci base_ni = ni; 45262306a36Sopenharmony_ci else 45362306a36Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 45462306a36Sopenharmony_ci /* Map, pin, and lock the mft record. */ 45562306a36Sopenharmony_ci mrec = map_mft_record(base_ni); 45662306a36Sopenharmony_ci if (IS_ERR(mrec)) { 45762306a36Sopenharmony_ci err = PTR_ERR(mrec); 45862306a36Sopenharmony_ci goto err_out; 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci /* 46162306a36Sopenharmony_ci * If a parallel write made the attribute non-resident, drop the mft 46262306a36Sopenharmony_ci * record and retry the read_folio. 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci if (unlikely(NInoNonResident(ni))) { 46562306a36Sopenharmony_ci unmap_mft_record(base_ni); 46662306a36Sopenharmony_ci goto retry_readpage; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, mrec); 46962306a36Sopenharmony_ci if (unlikely(!ctx)) { 47062306a36Sopenharmony_ci err = -ENOMEM; 47162306a36Sopenharmony_ci goto unm_err_out; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 47462306a36Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 47562306a36Sopenharmony_ci if (unlikely(err)) 47662306a36Sopenharmony_ci goto put_unm_err_out; 47762306a36Sopenharmony_ci attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); 47862306a36Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 47962306a36Sopenharmony_ci if (unlikely(attr_len > ni->initialized_size)) 48062306a36Sopenharmony_ci attr_len = ni->initialized_size; 48162306a36Sopenharmony_ci i_size = i_size_read(vi); 48262306a36Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 48362306a36Sopenharmony_ci if (unlikely(attr_len > i_size)) { 48462306a36Sopenharmony_ci /* Race with shrinking truncate. */ 48562306a36Sopenharmony_ci attr_len = i_size; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci addr = kmap_atomic(page); 48862306a36Sopenharmony_ci /* Copy the data to the page. */ 48962306a36Sopenharmony_ci memcpy(addr, (u8*)ctx->attr + 49062306a36Sopenharmony_ci le16_to_cpu(ctx->attr->data.resident.value_offset), 49162306a36Sopenharmony_ci attr_len); 49262306a36Sopenharmony_ci /* Zero the remainder of the page. */ 49362306a36Sopenharmony_ci memset(addr + attr_len, 0, PAGE_SIZE - attr_len); 49462306a36Sopenharmony_ci flush_dcache_page(page); 49562306a36Sopenharmony_ci kunmap_atomic(addr); 49662306a36Sopenharmony_ciput_unm_err_out: 49762306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 49862306a36Sopenharmony_ciunm_err_out: 49962306a36Sopenharmony_ci unmap_mft_record(base_ni); 50062306a36Sopenharmony_cidone: 50162306a36Sopenharmony_ci SetPageUptodate(page); 50262306a36Sopenharmony_cierr_out: 50362306a36Sopenharmony_ci unlock_page(page); 50462306a36Sopenharmony_ci return err; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci#ifdef NTFS_RW 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci/** 51062306a36Sopenharmony_ci * ntfs_write_block - write a @page to the backing store 51162306a36Sopenharmony_ci * @page: page cache page to write out 51262306a36Sopenharmony_ci * @wbc: writeback control structure 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * This function is for writing pages belonging to non-resident, non-mst 51562306a36Sopenharmony_ci * protected attributes to their backing store. 51662306a36Sopenharmony_ci * 51762306a36Sopenharmony_ci * For a page with buffers, map and write the dirty buffers asynchronously 51862306a36Sopenharmony_ci * under page writeback. For a page without buffers, create buffers for the 51962306a36Sopenharmony_ci * page, then proceed as above. 52062306a36Sopenharmony_ci * 52162306a36Sopenharmony_ci * If a page doesn't have buffers the page dirty state is definitive. If a page 52262306a36Sopenharmony_ci * does have buffers, the page dirty state is just a hint, and the buffer dirty 52362306a36Sopenharmony_ci * state is definitive. (A hint which has rules: dirty buffers against a clean 52462306a36Sopenharmony_ci * page is illegal. Other combinations are legal and need to be handled. In 52562306a36Sopenharmony_ci * particular a dirty page containing clean buffers for example.) 52662306a36Sopenharmony_ci * 52762306a36Sopenharmony_ci * Return 0 on success and -errno on error. 52862306a36Sopenharmony_ci * 52962306a36Sopenharmony_ci * Based on ntfs_read_block() and __block_write_full_folio(). 53062306a36Sopenharmony_ci */ 53162306a36Sopenharmony_cistatic int ntfs_write_block(struct page *page, struct writeback_control *wbc) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci VCN vcn; 53462306a36Sopenharmony_ci LCN lcn; 53562306a36Sopenharmony_ci s64 initialized_size; 53662306a36Sopenharmony_ci loff_t i_size; 53762306a36Sopenharmony_ci sector_t block, dblock, iblock; 53862306a36Sopenharmony_ci struct inode *vi; 53962306a36Sopenharmony_ci ntfs_inode *ni; 54062306a36Sopenharmony_ci ntfs_volume *vol; 54162306a36Sopenharmony_ci runlist_element *rl; 54262306a36Sopenharmony_ci struct buffer_head *bh, *head; 54362306a36Sopenharmony_ci unsigned long flags; 54462306a36Sopenharmony_ci unsigned int blocksize, vcn_ofs; 54562306a36Sopenharmony_ci int err; 54662306a36Sopenharmony_ci bool need_end_writeback; 54762306a36Sopenharmony_ci unsigned char blocksize_bits; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci vi = page->mapping->host; 55062306a36Sopenharmony_ci ni = NTFS_I(vi); 55162306a36Sopenharmony_ci vol = ni->vol; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index " 55462306a36Sopenharmony_ci "0x%lx.", ni->mft_no, ni->type, page->index); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci BUG_ON(!NInoNonResident(ni)); 55762306a36Sopenharmony_ci BUG_ON(NInoMstProtected(ni)); 55862306a36Sopenharmony_ci blocksize = vol->sb->s_blocksize; 55962306a36Sopenharmony_ci blocksize_bits = vol->sb->s_blocksize_bits; 56062306a36Sopenharmony_ci if (!page_has_buffers(page)) { 56162306a36Sopenharmony_ci BUG_ON(!PageUptodate(page)); 56262306a36Sopenharmony_ci create_empty_buffers(page, blocksize, 56362306a36Sopenharmony_ci (1 << BH_Uptodate) | (1 << BH_Dirty)); 56462306a36Sopenharmony_ci if (unlikely(!page_has_buffers(page))) { 56562306a36Sopenharmony_ci ntfs_warning(vol->sb, "Error allocating page " 56662306a36Sopenharmony_ci "buffers. Redirtying page so we try " 56762306a36Sopenharmony_ci "again later."); 56862306a36Sopenharmony_ci /* 56962306a36Sopenharmony_ci * Put the page back on mapping->dirty_pages, but leave 57062306a36Sopenharmony_ci * its buffers' dirty state as-is. 57162306a36Sopenharmony_ci */ 57262306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 57362306a36Sopenharmony_ci unlock_page(page); 57462306a36Sopenharmony_ci return 0; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci bh = head = page_buffers(page); 57862306a36Sopenharmony_ci BUG_ON(!bh); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci /* NOTE: Different naming scheme to ntfs_read_block()! */ 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* The first block in the page. */ 58362306a36Sopenharmony_ci block = (s64)page->index << (PAGE_SHIFT - blocksize_bits); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 58662306a36Sopenharmony_ci i_size = i_size_read(vi); 58762306a36Sopenharmony_ci initialized_size = ni->initialized_size; 58862306a36Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci /* The first out of bounds block for the data size. */ 59162306a36Sopenharmony_ci dblock = (i_size + blocksize - 1) >> blocksize_bits; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci /* The last (fully or partially) initialized block. */ 59462306a36Sopenharmony_ci iblock = initialized_size >> blocksize_bits; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* 59762306a36Sopenharmony_ci * Be very careful. We have no exclusion from block_dirty_folio 59862306a36Sopenharmony_ci * here, and the (potentially unmapped) buffers may become dirty at 59962306a36Sopenharmony_ci * any time. If a buffer becomes dirty here after we've inspected it 60062306a36Sopenharmony_ci * then we just miss that fact, and the page stays dirty. 60162306a36Sopenharmony_ci * 60262306a36Sopenharmony_ci * Buffers outside i_size may be dirtied by block_dirty_folio; 60362306a36Sopenharmony_ci * handle that here by just cleaning them. 60462306a36Sopenharmony_ci */ 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* 60762306a36Sopenharmony_ci * Loop through all the buffers in the page, mapping all the dirty 60862306a36Sopenharmony_ci * buffers to disk addresses and handling any aliases from the 60962306a36Sopenharmony_ci * underlying block device's mapping. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci rl = NULL; 61262306a36Sopenharmony_ci err = 0; 61362306a36Sopenharmony_ci do { 61462306a36Sopenharmony_ci bool is_retry = false; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (unlikely(block >= dblock)) { 61762306a36Sopenharmony_ci /* 61862306a36Sopenharmony_ci * Mapped buffers outside i_size will occur, because 61962306a36Sopenharmony_ci * this page can be outside i_size when there is a 62062306a36Sopenharmony_ci * truncate in progress. The contents of such buffers 62162306a36Sopenharmony_ci * were zeroed by ntfs_writepage(). 62262306a36Sopenharmony_ci * 62362306a36Sopenharmony_ci * FIXME: What about the small race window where 62462306a36Sopenharmony_ci * ntfs_writepage() has not done any clearing because 62562306a36Sopenharmony_ci * the page was within i_size but before we get here, 62662306a36Sopenharmony_ci * vmtruncate() modifies i_size? 62762306a36Sopenharmony_ci */ 62862306a36Sopenharmony_ci clear_buffer_dirty(bh); 62962306a36Sopenharmony_ci set_buffer_uptodate(bh); 63062306a36Sopenharmony_ci continue; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* Clean buffers are not written out, so no need to map them. */ 63462306a36Sopenharmony_ci if (!buffer_dirty(bh)) 63562306a36Sopenharmony_ci continue; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /* Make sure we have enough initialized size. */ 63862306a36Sopenharmony_ci if (unlikely((block >= iblock) && 63962306a36Sopenharmony_ci (initialized_size < i_size))) { 64062306a36Sopenharmony_ci /* 64162306a36Sopenharmony_ci * If this page is fully outside initialized 64262306a36Sopenharmony_ci * size, zero out all pages between the current 64362306a36Sopenharmony_ci * initialized size and the current page. Just 64462306a36Sopenharmony_ci * use ntfs_read_folio() to do the zeroing 64562306a36Sopenharmony_ci * transparently. 64662306a36Sopenharmony_ci */ 64762306a36Sopenharmony_ci if (block > iblock) { 64862306a36Sopenharmony_ci // TODO: 64962306a36Sopenharmony_ci // For each page do: 65062306a36Sopenharmony_ci // - read_cache_page() 65162306a36Sopenharmony_ci // Again for each page do: 65262306a36Sopenharmony_ci // - wait_on_page_locked() 65362306a36Sopenharmony_ci // - Check (PageUptodate(page) && 65462306a36Sopenharmony_ci // !PageError(page)) 65562306a36Sopenharmony_ci // Update initialized size in the attribute and 65662306a36Sopenharmony_ci // in the inode. 65762306a36Sopenharmony_ci // Again, for each page do: 65862306a36Sopenharmony_ci // block_dirty_folio(); 65962306a36Sopenharmony_ci // put_page() 66062306a36Sopenharmony_ci // We don't need to wait on the writes. 66162306a36Sopenharmony_ci // Update iblock. 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci /* 66462306a36Sopenharmony_ci * The current page straddles initialized size. Zero 66562306a36Sopenharmony_ci * all non-uptodate buffers and set them uptodate (and 66662306a36Sopenharmony_ci * dirty?). Note, there aren't any non-uptodate buffers 66762306a36Sopenharmony_ci * if the page is uptodate. 66862306a36Sopenharmony_ci * FIXME: For an uptodate page, the buffers may need to 66962306a36Sopenharmony_ci * be written out because they were not initialized on 67062306a36Sopenharmony_ci * disk before. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci if (!PageUptodate(page)) { 67362306a36Sopenharmony_ci // TODO: 67462306a36Sopenharmony_ci // Zero any non-uptodate buffers up to i_size. 67562306a36Sopenharmony_ci // Set them uptodate and dirty. 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci // TODO: 67862306a36Sopenharmony_ci // Update initialized size in the attribute and in the 67962306a36Sopenharmony_ci // inode (up to i_size). 68062306a36Sopenharmony_ci // Update iblock. 68162306a36Sopenharmony_ci // FIXME: This is inefficient. Try to batch the two 68262306a36Sopenharmony_ci // size changes to happen in one go. 68362306a36Sopenharmony_ci ntfs_error(vol->sb, "Writing beyond initialized size " 68462306a36Sopenharmony_ci "is not supported yet. Sorry."); 68562306a36Sopenharmony_ci err = -EOPNOTSUPP; 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci // Do NOT set_buffer_new() BUT DO clear buffer range 68862306a36Sopenharmony_ci // outside write request range. 68962306a36Sopenharmony_ci // set_buffer_uptodate() on complete buffers as well as 69062306a36Sopenharmony_ci // set_buffer_dirty(). 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* No need to map buffers that are already mapped. */ 69462306a36Sopenharmony_ci if (buffer_mapped(bh)) 69562306a36Sopenharmony_ci continue; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci /* Unmapped, dirty buffer. Need to map it. */ 69862306a36Sopenharmony_ci bh->b_bdev = vol->sb->s_bdev; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* Convert block into corresponding vcn and offset. */ 70162306a36Sopenharmony_ci vcn = (VCN)block << blocksize_bits; 70262306a36Sopenharmony_ci vcn_ofs = vcn & vol->cluster_size_mask; 70362306a36Sopenharmony_ci vcn >>= vol->cluster_size_bits; 70462306a36Sopenharmony_ci if (!rl) { 70562306a36Sopenharmony_cilock_retry_remap: 70662306a36Sopenharmony_ci down_read(&ni->runlist.lock); 70762306a36Sopenharmony_ci rl = ni->runlist.rl; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci if (likely(rl != NULL)) { 71062306a36Sopenharmony_ci /* Seek to element containing target vcn. */ 71162306a36Sopenharmony_ci while (rl->length && rl[1].vcn <= vcn) 71262306a36Sopenharmony_ci rl++; 71362306a36Sopenharmony_ci lcn = ntfs_rl_vcn_to_lcn(rl, vcn); 71462306a36Sopenharmony_ci } else 71562306a36Sopenharmony_ci lcn = LCN_RL_NOT_MAPPED; 71662306a36Sopenharmony_ci /* Successful remap. */ 71762306a36Sopenharmony_ci if (lcn >= 0) { 71862306a36Sopenharmony_ci /* Setup buffer head to point to correct block. */ 71962306a36Sopenharmony_ci bh->b_blocknr = ((lcn << vol->cluster_size_bits) + 72062306a36Sopenharmony_ci vcn_ofs) >> blocksize_bits; 72162306a36Sopenharmony_ci set_buffer_mapped(bh); 72262306a36Sopenharmony_ci continue; 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci /* It is a hole, need to instantiate it. */ 72562306a36Sopenharmony_ci if (lcn == LCN_HOLE) { 72662306a36Sopenharmony_ci u8 *kaddr; 72762306a36Sopenharmony_ci unsigned long *bpos, *bend; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* Check if the buffer is zero. */ 73062306a36Sopenharmony_ci kaddr = kmap_atomic(page); 73162306a36Sopenharmony_ci bpos = (unsigned long *)(kaddr + bh_offset(bh)); 73262306a36Sopenharmony_ci bend = (unsigned long *)((u8*)bpos + blocksize); 73362306a36Sopenharmony_ci do { 73462306a36Sopenharmony_ci if (unlikely(*bpos)) 73562306a36Sopenharmony_ci break; 73662306a36Sopenharmony_ci } while (likely(++bpos < bend)); 73762306a36Sopenharmony_ci kunmap_atomic(kaddr); 73862306a36Sopenharmony_ci if (bpos == bend) { 73962306a36Sopenharmony_ci /* 74062306a36Sopenharmony_ci * Buffer is zero and sparse, no need to write 74162306a36Sopenharmony_ci * it. 74262306a36Sopenharmony_ci */ 74362306a36Sopenharmony_ci bh->b_blocknr = -1; 74462306a36Sopenharmony_ci clear_buffer_dirty(bh); 74562306a36Sopenharmony_ci continue; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci // TODO: Instantiate the hole. 74862306a36Sopenharmony_ci // clear_buffer_new(bh); 74962306a36Sopenharmony_ci // clean_bdev_bh_alias(bh); 75062306a36Sopenharmony_ci ntfs_error(vol->sb, "Writing into sparse regions is " 75162306a36Sopenharmony_ci "not supported yet. Sorry."); 75262306a36Sopenharmony_ci err = -EOPNOTSUPP; 75362306a36Sopenharmony_ci break; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci /* If first try and runlist unmapped, map and retry. */ 75662306a36Sopenharmony_ci if (!is_retry && lcn == LCN_RL_NOT_MAPPED) { 75762306a36Sopenharmony_ci is_retry = true; 75862306a36Sopenharmony_ci /* 75962306a36Sopenharmony_ci * Attempt to map runlist, dropping lock for 76062306a36Sopenharmony_ci * the duration. 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_ci up_read(&ni->runlist.lock); 76362306a36Sopenharmony_ci err = ntfs_map_runlist(ni, vcn); 76462306a36Sopenharmony_ci if (likely(!err)) 76562306a36Sopenharmony_ci goto lock_retry_remap; 76662306a36Sopenharmony_ci rl = NULL; 76762306a36Sopenharmony_ci } else if (!rl) 76862306a36Sopenharmony_ci up_read(&ni->runlist.lock); 76962306a36Sopenharmony_ci /* 77062306a36Sopenharmony_ci * If buffer is outside the runlist, truncate has cut it out 77162306a36Sopenharmony_ci * of the runlist. Just clean and clear the buffer and set it 77262306a36Sopenharmony_ci * uptodate so it can get discarded by the VM. 77362306a36Sopenharmony_ci */ 77462306a36Sopenharmony_ci if (err == -ENOENT || lcn == LCN_ENOENT) { 77562306a36Sopenharmony_ci bh->b_blocknr = -1; 77662306a36Sopenharmony_ci clear_buffer_dirty(bh); 77762306a36Sopenharmony_ci zero_user(page, bh_offset(bh), blocksize); 77862306a36Sopenharmony_ci set_buffer_uptodate(bh); 77962306a36Sopenharmony_ci err = 0; 78062306a36Sopenharmony_ci continue; 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci /* Failed to map the buffer, even after retrying. */ 78362306a36Sopenharmony_ci if (!err) 78462306a36Sopenharmony_ci err = -EIO; 78562306a36Sopenharmony_ci bh->b_blocknr = -1; 78662306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to write to inode 0x%lx, " 78762306a36Sopenharmony_ci "attribute type 0x%x, vcn 0x%llx, offset 0x%x " 78862306a36Sopenharmony_ci "because its location on disk could not be " 78962306a36Sopenharmony_ci "determined%s (error code %i).", ni->mft_no, 79062306a36Sopenharmony_ci ni->type, (unsigned long long)vcn, 79162306a36Sopenharmony_ci vcn_ofs, is_retry ? " even after " 79262306a36Sopenharmony_ci "retrying" : "", err); 79362306a36Sopenharmony_ci break; 79462306a36Sopenharmony_ci } while (block++, (bh = bh->b_this_page) != head); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci /* Release the lock if we took it. */ 79762306a36Sopenharmony_ci if (rl) 79862306a36Sopenharmony_ci up_read(&ni->runlist.lock); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci /* For the error case, need to reset bh to the beginning. */ 80162306a36Sopenharmony_ci bh = head; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci /* Just an optimization, so ->read_folio() is not called later. */ 80462306a36Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 80562306a36Sopenharmony_ci int uptodate = 1; 80662306a36Sopenharmony_ci do { 80762306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 80862306a36Sopenharmony_ci uptodate = 0; 80962306a36Sopenharmony_ci bh = head; 81062306a36Sopenharmony_ci break; 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 81362306a36Sopenharmony_ci if (uptodate) 81462306a36Sopenharmony_ci SetPageUptodate(page); 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* Setup all mapped, dirty buffers for async write i/o. */ 81862306a36Sopenharmony_ci do { 81962306a36Sopenharmony_ci if (buffer_mapped(bh) && buffer_dirty(bh)) { 82062306a36Sopenharmony_ci lock_buffer(bh); 82162306a36Sopenharmony_ci if (test_clear_buffer_dirty(bh)) { 82262306a36Sopenharmony_ci BUG_ON(!buffer_uptodate(bh)); 82362306a36Sopenharmony_ci mark_buffer_async_write(bh); 82462306a36Sopenharmony_ci } else 82562306a36Sopenharmony_ci unlock_buffer(bh); 82662306a36Sopenharmony_ci } else if (unlikely(err)) { 82762306a36Sopenharmony_ci /* 82862306a36Sopenharmony_ci * For the error case. The buffer may have been set 82962306a36Sopenharmony_ci * dirty during attachment to a dirty page. 83062306a36Sopenharmony_ci */ 83162306a36Sopenharmony_ci if (err != -ENOMEM) 83262306a36Sopenharmony_ci clear_buffer_dirty(bh); 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci if (unlikely(err)) { 83762306a36Sopenharmony_ci // TODO: Remove the -EOPNOTSUPP check later on... 83862306a36Sopenharmony_ci if (unlikely(err == -EOPNOTSUPP)) 83962306a36Sopenharmony_ci err = 0; 84062306a36Sopenharmony_ci else if (err == -ENOMEM) { 84162306a36Sopenharmony_ci ntfs_warning(vol->sb, "Error allocating memory. " 84262306a36Sopenharmony_ci "Redirtying page so we try again " 84362306a36Sopenharmony_ci "later."); 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * Put the page back on mapping->dirty_pages, but 84662306a36Sopenharmony_ci * leave its buffer's dirty state as-is. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 84962306a36Sopenharmony_ci err = 0; 85062306a36Sopenharmony_ci } else 85162306a36Sopenharmony_ci SetPageError(page); 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 85562306a36Sopenharmony_ci set_page_writeback(page); /* Keeps try_to_free_buffers() away. */ 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* Submit the prepared buffers for i/o. */ 85862306a36Sopenharmony_ci need_end_writeback = true; 85962306a36Sopenharmony_ci do { 86062306a36Sopenharmony_ci struct buffer_head *next = bh->b_this_page; 86162306a36Sopenharmony_ci if (buffer_async_write(bh)) { 86262306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, bh); 86362306a36Sopenharmony_ci need_end_writeback = false; 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci bh = next; 86662306a36Sopenharmony_ci } while (bh != head); 86762306a36Sopenharmony_ci unlock_page(page); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* If no i/o was started, need to end_page_writeback(). */ 87062306a36Sopenharmony_ci if (unlikely(need_end_writeback)) 87162306a36Sopenharmony_ci end_page_writeback(page); 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci ntfs_debug("Done."); 87462306a36Sopenharmony_ci return err; 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci/** 87862306a36Sopenharmony_ci * ntfs_write_mst_block - write a @page to the backing store 87962306a36Sopenharmony_ci * @page: page cache page to write out 88062306a36Sopenharmony_ci * @wbc: writeback control structure 88162306a36Sopenharmony_ci * 88262306a36Sopenharmony_ci * This function is for writing pages belonging to non-resident, mst protected 88362306a36Sopenharmony_ci * attributes to their backing store. The only supported attributes are index 88462306a36Sopenharmony_ci * allocation and $MFT/$DATA. Both directory inodes and index inodes are 88562306a36Sopenharmony_ci * supported for the index allocation case. 88662306a36Sopenharmony_ci * 88762306a36Sopenharmony_ci * The page must remain locked for the duration of the write because we apply 88862306a36Sopenharmony_ci * the mst fixups, write, and then undo the fixups, so if we were to unlock the 88962306a36Sopenharmony_ci * page before undoing the fixups, any other user of the page will see the 89062306a36Sopenharmony_ci * page contents as corrupt. 89162306a36Sopenharmony_ci * 89262306a36Sopenharmony_ci * We clear the page uptodate flag for the duration of the function to ensure 89362306a36Sopenharmony_ci * exclusion for the $MFT/$DATA case against someone mapping an mft record we 89462306a36Sopenharmony_ci * are about to apply the mst fixups to. 89562306a36Sopenharmony_ci * 89662306a36Sopenharmony_ci * Return 0 on success and -errno on error. 89762306a36Sopenharmony_ci * 89862306a36Sopenharmony_ci * Based on ntfs_write_block(), ntfs_mft_writepage(), and 89962306a36Sopenharmony_ci * write_mft_record_nolock(). 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_cistatic int ntfs_write_mst_block(struct page *page, 90262306a36Sopenharmony_ci struct writeback_control *wbc) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci sector_t block, dblock, rec_block; 90562306a36Sopenharmony_ci struct inode *vi = page->mapping->host; 90662306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(vi); 90762306a36Sopenharmony_ci ntfs_volume *vol = ni->vol; 90862306a36Sopenharmony_ci u8 *kaddr; 90962306a36Sopenharmony_ci unsigned int rec_size = ni->itype.index.block_size; 91062306a36Sopenharmony_ci ntfs_inode *locked_nis[PAGE_SIZE / NTFS_BLOCK_SIZE]; 91162306a36Sopenharmony_ci struct buffer_head *bh, *head, *tbh, *rec_start_bh; 91262306a36Sopenharmony_ci struct buffer_head *bhs[MAX_BUF_PER_PAGE]; 91362306a36Sopenharmony_ci runlist_element *rl; 91462306a36Sopenharmony_ci int i, nr_locked_nis, nr_recs, nr_bhs, max_bhs, bhs_per_rec, err, err2; 91562306a36Sopenharmony_ci unsigned bh_size, rec_size_bits; 91662306a36Sopenharmony_ci bool sync, is_mft, page_is_dirty, rec_is_dirty; 91762306a36Sopenharmony_ci unsigned char bh_size_bits; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (WARN_ON(rec_size < NTFS_BLOCK_SIZE)) 92062306a36Sopenharmony_ci return -EINVAL; 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index " 92362306a36Sopenharmony_ci "0x%lx.", vi->i_ino, ni->type, page->index); 92462306a36Sopenharmony_ci BUG_ON(!NInoNonResident(ni)); 92562306a36Sopenharmony_ci BUG_ON(!NInoMstProtected(ni)); 92662306a36Sopenharmony_ci is_mft = (S_ISREG(vi->i_mode) && !vi->i_ino); 92762306a36Sopenharmony_ci /* 92862306a36Sopenharmony_ci * NOTE: ntfs_write_mst_block() would be called for $MFTMirr if a page 92962306a36Sopenharmony_ci * in its page cache were to be marked dirty. However this should 93062306a36Sopenharmony_ci * never happen with the current driver and considering we do not 93162306a36Sopenharmony_ci * handle this case here we do want to BUG(), at least for now. 93262306a36Sopenharmony_ci */ 93362306a36Sopenharmony_ci BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) || 93462306a36Sopenharmony_ci (NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION))); 93562306a36Sopenharmony_ci bh_size = vol->sb->s_blocksize; 93662306a36Sopenharmony_ci bh_size_bits = vol->sb->s_blocksize_bits; 93762306a36Sopenharmony_ci max_bhs = PAGE_SIZE / bh_size; 93862306a36Sopenharmony_ci BUG_ON(!max_bhs); 93962306a36Sopenharmony_ci BUG_ON(max_bhs > MAX_BUF_PER_PAGE); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci /* Were we called for sync purposes? */ 94262306a36Sopenharmony_ci sync = (wbc->sync_mode == WB_SYNC_ALL); 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* Make sure we have mapped buffers. */ 94562306a36Sopenharmony_ci bh = head = page_buffers(page); 94662306a36Sopenharmony_ci BUG_ON(!bh); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci rec_size_bits = ni->itype.index.block_size_bits; 94962306a36Sopenharmony_ci BUG_ON(!(PAGE_SIZE >> rec_size_bits)); 95062306a36Sopenharmony_ci bhs_per_rec = rec_size >> bh_size_bits; 95162306a36Sopenharmony_ci BUG_ON(!bhs_per_rec); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci /* The first block in the page. */ 95462306a36Sopenharmony_ci rec_block = block = (sector_t)page->index << 95562306a36Sopenharmony_ci (PAGE_SHIFT - bh_size_bits); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci /* The first out of bounds block for the data size. */ 95862306a36Sopenharmony_ci dblock = (i_size_read(vi) + bh_size - 1) >> bh_size_bits; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci rl = NULL; 96162306a36Sopenharmony_ci err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0; 96262306a36Sopenharmony_ci page_is_dirty = rec_is_dirty = false; 96362306a36Sopenharmony_ci rec_start_bh = NULL; 96462306a36Sopenharmony_ci do { 96562306a36Sopenharmony_ci bool is_retry = false; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci if (likely(block < rec_block)) { 96862306a36Sopenharmony_ci if (unlikely(block >= dblock)) { 96962306a36Sopenharmony_ci clear_buffer_dirty(bh); 97062306a36Sopenharmony_ci set_buffer_uptodate(bh); 97162306a36Sopenharmony_ci continue; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci /* 97462306a36Sopenharmony_ci * This block is not the first one in the record. We 97562306a36Sopenharmony_ci * ignore the buffer's dirty state because we could 97662306a36Sopenharmony_ci * have raced with a parallel mark_ntfs_record_dirty(). 97762306a36Sopenharmony_ci */ 97862306a36Sopenharmony_ci if (!rec_is_dirty) 97962306a36Sopenharmony_ci continue; 98062306a36Sopenharmony_ci if (unlikely(err2)) { 98162306a36Sopenharmony_ci if (err2 != -ENOMEM) 98262306a36Sopenharmony_ci clear_buffer_dirty(bh); 98362306a36Sopenharmony_ci continue; 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci } else /* if (block == rec_block) */ { 98662306a36Sopenharmony_ci BUG_ON(block > rec_block); 98762306a36Sopenharmony_ci /* This block is the first one in the record. */ 98862306a36Sopenharmony_ci rec_block += bhs_per_rec; 98962306a36Sopenharmony_ci err2 = 0; 99062306a36Sopenharmony_ci if (unlikely(block >= dblock)) { 99162306a36Sopenharmony_ci clear_buffer_dirty(bh); 99262306a36Sopenharmony_ci continue; 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci if (!buffer_dirty(bh)) { 99562306a36Sopenharmony_ci /* Clean records are not written out. */ 99662306a36Sopenharmony_ci rec_is_dirty = false; 99762306a36Sopenharmony_ci continue; 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci rec_is_dirty = true; 100062306a36Sopenharmony_ci rec_start_bh = bh; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci /* Need to map the buffer if it is not mapped already. */ 100362306a36Sopenharmony_ci if (unlikely(!buffer_mapped(bh))) { 100462306a36Sopenharmony_ci VCN vcn; 100562306a36Sopenharmony_ci LCN lcn; 100662306a36Sopenharmony_ci unsigned int vcn_ofs; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci bh->b_bdev = vol->sb->s_bdev; 100962306a36Sopenharmony_ci /* Obtain the vcn and offset of the current block. */ 101062306a36Sopenharmony_ci vcn = (VCN)block << bh_size_bits; 101162306a36Sopenharmony_ci vcn_ofs = vcn & vol->cluster_size_mask; 101262306a36Sopenharmony_ci vcn >>= vol->cluster_size_bits; 101362306a36Sopenharmony_ci if (!rl) { 101462306a36Sopenharmony_cilock_retry_remap: 101562306a36Sopenharmony_ci down_read(&ni->runlist.lock); 101662306a36Sopenharmony_ci rl = ni->runlist.rl; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci if (likely(rl != NULL)) { 101962306a36Sopenharmony_ci /* Seek to element containing target vcn. */ 102062306a36Sopenharmony_ci while (rl->length && rl[1].vcn <= vcn) 102162306a36Sopenharmony_ci rl++; 102262306a36Sopenharmony_ci lcn = ntfs_rl_vcn_to_lcn(rl, vcn); 102362306a36Sopenharmony_ci } else 102462306a36Sopenharmony_ci lcn = LCN_RL_NOT_MAPPED; 102562306a36Sopenharmony_ci /* Successful remap. */ 102662306a36Sopenharmony_ci if (likely(lcn >= 0)) { 102762306a36Sopenharmony_ci /* Setup buffer head to correct block. */ 102862306a36Sopenharmony_ci bh->b_blocknr = ((lcn << 102962306a36Sopenharmony_ci vol->cluster_size_bits) + 103062306a36Sopenharmony_ci vcn_ofs) >> bh_size_bits; 103162306a36Sopenharmony_ci set_buffer_mapped(bh); 103262306a36Sopenharmony_ci } else { 103362306a36Sopenharmony_ci /* 103462306a36Sopenharmony_ci * Remap failed. Retry to map the runlist once 103562306a36Sopenharmony_ci * unless we are working on $MFT which always 103662306a36Sopenharmony_ci * has the whole of its runlist in memory. 103762306a36Sopenharmony_ci */ 103862306a36Sopenharmony_ci if (!is_mft && !is_retry && 103962306a36Sopenharmony_ci lcn == LCN_RL_NOT_MAPPED) { 104062306a36Sopenharmony_ci is_retry = true; 104162306a36Sopenharmony_ci /* 104262306a36Sopenharmony_ci * Attempt to map runlist, dropping 104362306a36Sopenharmony_ci * lock for the duration. 104462306a36Sopenharmony_ci */ 104562306a36Sopenharmony_ci up_read(&ni->runlist.lock); 104662306a36Sopenharmony_ci err2 = ntfs_map_runlist(ni, vcn); 104762306a36Sopenharmony_ci if (likely(!err2)) 104862306a36Sopenharmony_ci goto lock_retry_remap; 104962306a36Sopenharmony_ci if (err2 == -ENOMEM) 105062306a36Sopenharmony_ci page_is_dirty = true; 105162306a36Sopenharmony_ci lcn = err2; 105262306a36Sopenharmony_ci } else { 105362306a36Sopenharmony_ci err2 = -EIO; 105462306a36Sopenharmony_ci if (!rl) 105562306a36Sopenharmony_ci up_read(&ni->runlist.lock); 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci /* Hard error. Abort writing this record. */ 105862306a36Sopenharmony_ci if (!err || err == -ENOMEM) 105962306a36Sopenharmony_ci err = err2; 106062306a36Sopenharmony_ci bh->b_blocknr = -1; 106162306a36Sopenharmony_ci ntfs_error(vol->sb, "Cannot write ntfs record " 106262306a36Sopenharmony_ci "0x%llx (inode 0x%lx, " 106362306a36Sopenharmony_ci "attribute type 0x%x) because " 106462306a36Sopenharmony_ci "its location on disk could " 106562306a36Sopenharmony_ci "not be determined (error " 106662306a36Sopenharmony_ci "code %lli).", 106762306a36Sopenharmony_ci (long long)block << 106862306a36Sopenharmony_ci bh_size_bits >> 106962306a36Sopenharmony_ci vol->mft_record_size_bits, 107062306a36Sopenharmony_ci ni->mft_no, ni->type, 107162306a36Sopenharmony_ci (long long)lcn); 107262306a36Sopenharmony_ci /* 107362306a36Sopenharmony_ci * If this is not the first buffer, remove the 107462306a36Sopenharmony_ci * buffers in this record from the list of 107562306a36Sopenharmony_ci * buffers to write and clear their dirty bit 107662306a36Sopenharmony_ci * if not error -ENOMEM. 107762306a36Sopenharmony_ci */ 107862306a36Sopenharmony_ci if (rec_start_bh != bh) { 107962306a36Sopenharmony_ci while (bhs[--nr_bhs] != rec_start_bh) 108062306a36Sopenharmony_ci ; 108162306a36Sopenharmony_ci if (err2 != -ENOMEM) { 108262306a36Sopenharmony_ci do { 108362306a36Sopenharmony_ci clear_buffer_dirty( 108462306a36Sopenharmony_ci rec_start_bh); 108562306a36Sopenharmony_ci } while ((rec_start_bh = 108662306a36Sopenharmony_ci rec_start_bh-> 108762306a36Sopenharmony_ci b_this_page) != 108862306a36Sopenharmony_ci bh); 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci } 109162306a36Sopenharmony_ci continue; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci } 109462306a36Sopenharmony_ci BUG_ON(!buffer_uptodate(bh)); 109562306a36Sopenharmony_ci BUG_ON(nr_bhs >= max_bhs); 109662306a36Sopenharmony_ci bhs[nr_bhs++] = bh; 109762306a36Sopenharmony_ci } while (block++, (bh = bh->b_this_page) != head); 109862306a36Sopenharmony_ci if (unlikely(rl)) 109962306a36Sopenharmony_ci up_read(&ni->runlist.lock); 110062306a36Sopenharmony_ci /* If there were no dirty buffers, we are done. */ 110162306a36Sopenharmony_ci if (!nr_bhs) 110262306a36Sopenharmony_ci goto done; 110362306a36Sopenharmony_ci /* Map the page so we can access its contents. */ 110462306a36Sopenharmony_ci kaddr = kmap(page); 110562306a36Sopenharmony_ci /* Clear the page uptodate flag whilst the mst fixups are applied. */ 110662306a36Sopenharmony_ci BUG_ON(!PageUptodate(page)); 110762306a36Sopenharmony_ci ClearPageUptodate(page); 110862306a36Sopenharmony_ci for (i = 0; i < nr_bhs; i++) { 110962306a36Sopenharmony_ci unsigned int ofs; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci /* Skip buffers which are not at the beginning of records. */ 111262306a36Sopenharmony_ci if (i % bhs_per_rec) 111362306a36Sopenharmony_ci continue; 111462306a36Sopenharmony_ci tbh = bhs[i]; 111562306a36Sopenharmony_ci ofs = bh_offset(tbh); 111662306a36Sopenharmony_ci if (is_mft) { 111762306a36Sopenharmony_ci ntfs_inode *tni; 111862306a36Sopenharmony_ci unsigned long mft_no; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci /* Get the mft record number. */ 112162306a36Sopenharmony_ci mft_no = (((s64)page->index << PAGE_SHIFT) + ofs) 112262306a36Sopenharmony_ci >> rec_size_bits; 112362306a36Sopenharmony_ci /* Check whether to write this mft record. */ 112462306a36Sopenharmony_ci tni = NULL; 112562306a36Sopenharmony_ci if (!ntfs_may_write_mft_record(vol, mft_no, 112662306a36Sopenharmony_ci (MFT_RECORD*)(kaddr + ofs), &tni)) { 112762306a36Sopenharmony_ci /* 112862306a36Sopenharmony_ci * The record should not be written. This 112962306a36Sopenharmony_ci * means we need to redirty the page before 113062306a36Sopenharmony_ci * returning. 113162306a36Sopenharmony_ci */ 113262306a36Sopenharmony_ci page_is_dirty = true; 113362306a36Sopenharmony_ci /* 113462306a36Sopenharmony_ci * Remove the buffers in this mft record from 113562306a36Sopenharmony_ci * the list of buffers to write. 113662306a36Sopenharmony_ci */ 113762306a36Sopenharmony_ci do { 113862306a36Sopenharmony_ci bhs[i] = NULL; 113962306a36Sopenharmony_ci } while (++i % bhs_per_rec); 114062306a36Sopenharmony_ci continue; 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci /* 114362306a36Sopenharmony_ci * The record should be written. If a locked ntfs 114462306a36Sopenharmony_ci * inode was returned, add it to the array of locked 114562306a36Sopenharmony_ci * ntfs inodes. 114662306a36Sopenharmony_ci */ 114762306a36Sopenharmony_ci if (tni) 114862306a36Sopenharmony_ci locked_nis[nr_locked_nis++] = tni; 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci /* Apply the mst protection fixups. */ 115162306a36Sopenharmony_ci err2 = pre_write_mst_fixup((NTFS_RECORD*)(kaddr + ofs), 115262306a36Sopenharmony_ci rec_size); 115362306a36Sopenharmony_ci if (unlikely(err2)) { 115462306a36Sopenharmony_ci if (!err || err == -ENOMEM) 115562306a36Sopenharmony_ci err = -EIO; 115662306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to apply mst fixups " 115762306a36Sopenharmony_ci "(inode 0x%lx, attribute type 0x%x, " 115862306a36Sopenharmony_ci "page index 0x%lx, page offset 0x%x)!" 115962306a36Sopenharmony_ci " Unmount and run chkdsk.", vi->i_ino, 116062306a36Sopenharmony_ci ni->type, page->index, ofs); 116162306a36Sopenharmony_ci /* 116262306a36Sopenharmony_ci * Mark all the buffers in this record clean as we do 116362306a36Sopenharmony_ci * not want to write corrupt data to disk. 116462306a36Sopenharmony_ci */ 116562306a36Sopenharmony_ci do { 116662306a36Sopenharmony_ci clear_buffer_dirty(bhs[i]); 116762306a36Sopenharmony_ci bhs[i] = NULL; 116862306a36Sopenharmony_ci } while (++i % bhs_per_rec); 116962306a36Sopenharmony_ci continue; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci nr_recs++; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci /* If no records are to be written out, we are done. */ 117462306a36Sopenharmony_ci if (!nr_recs) 117562306a36Sopenharmony_ci goto unm_done; 117662306a36Sopenharmony_ci flush_dcache_page(page); 117762306a36Sopenharmony_ci /* Lock buffers and start synchronous write i/o on them. */ 117862306a36Sopenharmony_ci for (i = 0; i < nr_bhs; i++) { 117962306a36Sopenharmony_ci tbh = bhs[i]; 118062306a36Sopenharmony_ci if (!tbh) 118162306a36Sopenharmony_ci continue; 118262306a36Sopenharmony_ci if (!trylock_buffer(tbh)) 118362306a36Sopenharmony_ci BUG(); 118462306a36Sopenharmony_ci /* The buffer dirty state is now irrelevant, just clean it. */ 118562306a36Sopenharmony_ci clear_buffer_dirty(tbh); 118662306a36Sopenharmony_ci BUG_ON(!buffer_uptodate(tbh)); 118762306a36Sopenharmony_ci BUG_ON(!buffer_mapped(tbh)); 118862306a36Sopenharmony_ci get_bh(tbh); 118962306a36Sopenharmony_ci tbh->b_end_io = end_buffer_write_sync; 119062306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, tbh); 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci /* Synchronize the mft mirror now if not @sync. */ 119362306a36Sopenharmony_ci if (is_mft && !sync) 119462306a36Sopenharmony_ci goto do_mirror; 119562306a36Sopenharmony_cido_wait: 119662306a36Sopenharmony_ci /* Wait on i/o completion of buffers. */ 119762306a36Sopenharmony_ci for (i = 0; i < nr_bhs; i++) { 119862306a36Sopenharmony_ci tbh = bhs[i]; 119962306a36Sopenharmony_ci if (!tbh) 120062306a36Sopenharmony_ci continue; 120162306a36Sopenharmony_ci wait_on_buffer(tbh); 120262306a36Sopenharmony_ci if (unlikely(!buffer_uptodate(tbh))) { 120362306a36Sopenharmony_ci ntfs_error(vol->sb, "I/O error while writing ntfs " 120462306a36Sopenharmony_ci "record buffer (inode 0x%lx, " 120562306a36Sopenharmony_ci "attribute type 0x%x, page index " 120662306a36Sopenharmony_ci "0x%lx, page offset 0x%lx)! Unmount " 120762306a36Sopenharmony_ci "and run chkdsk.", vi->i_ino, ni->type, 120862306a36Sopenharmony_ci page->index, bh_offset(tbh)); 120962306a36Sopenharmony_ci if (!err || err == -ENOMEM) 121062306a36Sopenharmony_ci err = -EIO; 121162306a36Sopenharmony_ci /* 121262306a36Sopenharmony_ci * Set the buffer uptodate so the page and buffer 121362306a36Sopenharmony_ci * states do not become out of sync. 121462306a36Sopenharmony_ci */ 121562306a36Sopenharmony_ci set_buffer_uptodate(tbh); 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci /* If @sync, now synchronize the mft mirror. */ 121962306a36Sopenharmony_ci if (is_mft && sync) { 122062306a36Sopenharmony_cido_mirror: 122162306a36Sopenharmony_ci for (i = 0; i < nr_bhs; i++) { 122262306a36Sopenharmony_ci unsigned long mft_no; 122362306a36Sopenharmony_ci unsigned int ofs; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* 122662306a36Sopenharmony_ci * Skip buffers which are not at the beginning of 122762306a36Sopenharmony_ci * records. 122862306a36Sopenharmony_ci */ 122962306a36Sopenharmony_ci if (i % bhs_per_rec) 123062306a36Sopenharmony_ci continue; 123162306a36Sopenharmony_ci tbh = bhs[i]; 123262306a36Sopenharmony_ci /* Skip removed buffers (and hence records). */ 123362306a36Sopenharmony_ci if (!tbh) 123462306a36Sopenharmony_ci continue; 123562306a36Sopenharmony_ci ofs = bh_offset(tbh); 123662306a36Sopenharmony_ci /* Get the mft record number. */ 123762306a36Sopenharmony_ci mft_no = (((s64)page->index << PAGE_SHIFT) + ofs) 123862306a36Sopenharmony_ci >> rec_size_bits; 123962306a36Sopenharmony_ci if (mft_no < vol->mftmirr_size) 124062306a36Sopenharmony_ci ntfs_sync_mft_mirror(vol, mft_no, 124162306a36Sopenharmony_ci (MFT_RECORD*)(kaddr + ofs), 124262306a36Sopenharmony_ci sync); 124362306a36Sopenharmony_ci } 124462306a36Sopenharmony_ci if (!sync) 124562306a36Sopenharmony_ci goto do_wait; 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci /* Remove the mst protection fixups again. */ 124862306a36Sopenharmony_ci for (i = 0; i < nr_bhs; i++) { 124962306a36Sopenharmony_ci if (!(i % bhs_per_rec)) { 125062306a36Sopenharmony_ci tbh = bhs[i]; 125162306a36Sopenharmony_ci if (!tbh) 125262306a36Sopenharmony_ci continue; 125362306a36Sopenharmony_ci post_write_mst_fixup((NTFS_RECORD*)(kaddr + 125462306a36Sopenharmony_ci bh_offset(tbh))); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci flush_dcache_page(page); 125862306a36Sopenharmony_ciunm_done: 125962306a36Sopenharmony_ci /* Unlock any locked inodes. */ 126062306a36Sopenharmony_ci while (nr_locked_nis-- > 0) { 126162306a36Sopenharmony_ci ntfs_inode *tni, *base_tni; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci tni = locked_nis[nr_locked_nis]; 126462306a36Sopenharmony_ci /* Get the base inode. */ 126562306a36Sopenharmony_ci mutex_lock(&tni->extent_lock); 126662306a36Sopenharmony_ci if (tni->nr_extents >= 0) 126762306a36Sopenharmony_ci base_tni = tni; 126862306a36Sopenharmony_ci else { 126962306a36Sopenharmony_ci base_tni = tni->ext.base_ntfs_ino; 127062306a36Sopenharmony_ci BUG_ON(!base_tni); 127162306a36Sopenharmony_ci } 127262306a36Sopenharmony_ci mutex_unlock(&tni->extent_lock); 127362306a36Sopenharmony_ci ntfs_debug("Unlocking %s inode 0x%lx.", 127462306a36Sopenharmony_ci tni == base_tni ? "base" : "extent", 127562306a36Sopenharmony_ci tni->mft_no); 127662306a36Sopenharmony_ci mutex_unlock(&tni->mrec_lock); 127762306a36Sopenharmony_ci atomic_dec(&tni->count); 127862306a36Sopenharmony_ci iput(VFS_I(base_tni)); 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci SetPageUptodate(page); 128162306a36Sopenharmony_ci kunmap(page); 128262306a36Sopenharmony_cidone: 128362306a36Sopenharmony_ci if (unlikely(err && err != -ENOMEM)) { 128462306a36Sopenharmony_ci /* 128562306a36Sopenharmony_ci * Set page error if there is only one ntfs record in the page. 128662306a36Sopenharmony_ci * Otherwise we would loose per-record granularity. 128762306a36Sopenharmony_ci */ 128862306a36Sopenharmony_ci if (ni->itype.index.block_size == PAGE_SIZE) 128962306a36Sopenharmony_ci SetPageError(page); 129062306a36Sopenharmony_ci NVolSetErrors(vol); 129162306a36Sopenharmony_ci } 129262306a36Sopenharmony_ci if (page_is_dirty) { 129362306a36Sopenharmony_ci ntfs_debug("Page still contains one or more dirty ntfs " 129462306a36Sopenharmony_ci "records. Redirtying the page starting at " 129562306a36Sopenharmony_ci "record 0x%lx.", page->index << 129662306a36Sopenharmony_ci (PAGE_SHIFT - rec_size_bits)); 129762306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 129862306a36Sopenharmony_ci unlock_page(page); 129962306a36Sopenharmony_ci } else { 130062306a36Sopenharmony_ci /* 130162306a36Sopenharmony_ci * Keep the VM happy. This must be done otherwise the 130262306a36Sopenharmony_ci * radix-tree tag PAGECACHE_TAG_DIRTY remains set even though 130362306a36Sopenharmony_ci * the page is clean. 130462306a36Sopenharmony_ci */ 130562306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 130662306a36Sopenharmony_ci set_page_writeback(page); 130762306a36Sopenharmony_ci unlock_page(page); 130862306a36Sopenharmony_ci end_page_writeback(page); 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci if (likely(!err)) 131162306a36Sopenharmony_ci ntfs_debug("Done."); 131262306a36Sopenharmony_ci return err; 131362306a36Sopenharmony_ci} 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci/** 131662306a36Sopenharmony_ci * ntfs_writepage - write a @page to the backing store 131762306a36Sopenharmony_ci * @page: page cache page to write out 131862306a36Sopenharmony_ci * @wbc: writeback control structure 131962306a36Sopenharmony_ci * 132062306a36Sopenharmony_ci * This is called from the VM when it wants to have a dirty ntfs page cache 132162306a36Sopenharmony_ci * page cleaned. The VM has already locked the page and marked it clean. 132262306a36Sopenharmony_ci * 132362306a36Sopenharmony_ci * For non-resident attributes, ntfs_writepage() writes the @page by calling 132462306a36Sopenharmony_ci * the ntfs version of the generic block_write_full_page() function, 132562306a36Sopenharmony_ci * ntfs_write_block(), which in turn if necessary creates and writes the 132662306a36Sopenharmony_ci * buffers associated with the page asynchronously. 132762306a36Sopenharmony_ci * 132862306a36Sopenharmony_ci * For resident attributes, OTOH, ntfs_writepage() writes the @page by copying 132962306a36Sopenharmony_ci * the data to the mft record (which at this stage is most likely in memory). 133062306a36Sopenharmony_ci * The mft record is then marked dirty and written out asynchronously via the 133162306a36Sopenharmony_ci * vfs inode dirty code path for the inode the mft record belongs to or via the 133262306a36Sopenharmony_ci * vm page dirty code path for the page the mft record is in. 133362306a36Sopenharmony_ci * 133462306a36Sopenharmony_ci * Based on ntfs_read_folio() and fs/buffer.c::block_write_full_page(). 133562306a36Sopenharmony_ci * 133662306a36Sopenharmony_ci * Return 0 on success and -errno on error. 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_cistatic int ntfs_writepage(struct page *page, struct writeback_control *wbc) 133962306a36Sopenharmony_ci{ 134062306a36Sopenharmony_ci loff_t i_size; 134162306a36Sopenharmony_ci struct inode *vi = page->mapping->host; 134262306a36Sopenharmony_ci ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi); 134362306a36Sopenharmony_ci char *addr; 134462306a36Sopenharmony_ci ntfs_attr_search_ctx *ctx = NULL; 134562306a36Sopenharmony_ci MFT_RECORD *m = NULL; 134662306a36Sopenharmony_ci u32 attr_len; 134762306a36Sopenharmony_ci int err; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ciretry_writepage: 135062306a36Sopenharmony_ci BUG_ON(!PageLocked(page)); 135162306a36Sopenharmony_ci i_size = i_size_read(vi); 135262306a36Sopenharmony_ci /* Is the page fully outside i_size? (truncate in progress) */ 135362306a36Sopenharmony_ci if (unlikely(page->index >= (i_size + PAGE_SIZE - 1) >> 135462306a36Sopenharmony_ci PAGE_SHIFT)) { 135562306a36Sopenharmony_ci struct folio *folio = page_folio(page); 135662306a36Sopenharmony_ci /* 135762306a36Sopenharmony_ci * The page may have dirty, unmapped buffers. Make them 135862306a36Sopenharmony_ci * freeable here, so the page does not leak. 135962306a36Sopenharmony_ci */ 136062306a36Sopenharmony_ci block_invalidate_folio(folio, 0, folio_size(folio)); 136162306a36Sopenharmony_ci folio_unlock(folio); 136262306a36Sopenharmony_ci ntfs_debug("Write outside i_size - truncated?"); 136362306a36Sopenharmony_ci return 0; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci /* 136662306a36Sopenharmony_ci * Only $DATA attributes can be encrypted and only unnamed $DATA 136762306a36Sopenharmony_ci * attributes can be compressed. Index root can have the flags set but 136862306a36Sopenharmony_ci * this means to create compressed/encrypted files, not that the 136962306a36Sopenharmony_ci * attribute is compressed/encrypted. Note we need to check for 137062306a36Sopenharmony_ci * AT_INDEX_ALLOCATION since this is the type of both directory and 137162306a36Sopenharmony_ci * index inodes. 137262306a36Sopenharmony_ci */ 137362306a36Sopenharmony_ci if (ni->type != AT_INDEX_ALLOCATION) { 137462306a36Sopenharmony_ci /* If file is encrypted, deny access, just like NT4. */ 137562306a36Sopenharmony_ci if (NInoEncrypted(ni)) { 137662306a36Sopenharmony_ci unlock_page(page); 137762306a36Sopenharmony_ci BUG_ON(ni->type != AT_DATA); 137862306a36Sopenharmony_ci ntfs_debug("Denying write access to encrypted file."); 137962306a36Sopenharmony_ci return -EACCES; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci /* Compressed data streams are handled in compress.c. */ 138262306a36Sopenharmony_ci if (NInoNonResident(ni) && NInoCompressed(ni)) { 138362306a36Sopenharmony_ci BUG_ON(ni->type != AT_DATA); 138462306a36Sopenharmony_ci BUG_ON(ni->name_len); 138562306a36Sopenharmony_ci // TODO: Implement and replace this with 138662306a36Sopenharmony_ci // return ntfs_write_compressed_block(page); 138762306a36Sopenharmony_ci unlock_page(page); 138862306a36Sopenharmony_ci ntfs_error(vi->i_sb, "Writing to compressed files is " 138962306a36Sopenharmony_ci "not supported yet. Sorry."); 139062306a36Sopenharmony_ci return -EOPNOTSUPP; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci // TODO: Implement and remove this check. 139362306a36Sopenharmony_ci if (NInoNonResident(ni) && NInoSparse(ni)) { 139462306a36Sopenharmony_ci unlock_page(page); 139562306a36Sopenharmony_ci ntfs_error(vi->i_sb, "Writing to sparse files is not " 139662306a36Sopenharmony_ci "supported yet. Sorry."); 139762306a36Sopenharmony_ci return -EOPNOTSUPP; 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci } 140062306a36Sopenharmony_ci /* NInoNonResident() == NInoIndexAllocPresent() */ 140162306a36Sopenharmony_ci if (NInoNonResident(ni)) { 140262306a36Sopenharmony_ci /* We have to zero every time due to mmap-at-end-of-file. */ 140362306a36Sopenharmony_ci if (page->index >= (i_size >> PAGE_SHIFT)) { 140462306a36Sopenharmony_ci /* The page straddles i_size. */ 140562306a36Sopenharmony_ci unsigned int ofs = i_size & ~PAGE_MASK; 140662306a36Sopenharmony_ci zero_user_segment(page, ofs, PAGE_SIZE); 140762306a36Sopenharmony_ci } 140862306a36Sopenharmony_ci /* Handle mst protected attributes. */ 140962306a36Sopenharmony_ci if (NInoMstProtected(ni)) 141062306a36Sopenharmony_ci return ntfs_write_mst_block(page, wbc); 141162306a36Sopenharmony_ci /* Normal, non-resident data stream. */ 141262306a36Sopenharmony_ci return ntfs_write_block(page, wbc); 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ci /* 141562306a36Sopenharmony_ci * Attribute is resident, implying it is not compressed, encrypted, or 141662306a36Sopenharmony_ci * mst protected. This also means the attribute is smaller than an mft 141762306a36Sopenharmony_ci * record and hence smaller than a page, so can simply return error on 141862306a36Sopenharmony_ci * any pages with index above 0. Note the attribute can actually be 141962306a36Sopenharmony_ci * marked compressed but if it is resident the actual data is not 142062306a36Sopenharmony_ci * compressed so we are ok to ignore the compressed flag here. 142162306a36Sopenharmony_ci */ 142262306a36Sopenharmony_ci BUG_ON(page_has_buffers(page)); 142362306a36Sopenharmony_ci BUG_ON(!PageUptodate(page)); 142462306a36Sopenharmony_ci if (unlikely(page->index > 0)) { 142562306a36Sopenharmony_ci ntfs_error(vi->i_sb, "BUG()! page->index (0x%lx) > 0. " 142662306a36Sopenharmony_ci "Aborting write.", page->index); 142762306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 142862306a36Sopenharmony_ci set_page_writeback(page); 142962306a36Sopenharmony_ci unlock_page(page); 143062306a36Sopenharmony_ci end_page_writeback(page); 143162306a36Sopenharmony_ci return -EIO; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci if (!NInoAttr(ni)) 143462306a36Sopenharmony_ci base_ni = ni; 143562306a36Sopenharmony_ci else 143662306a36Sopenharmony_ci base_ni = ni->ext.base_ntfs_ino; 143762306a36Sopenharmony_ci /* Map, pin, and lock the mft record. */ 143862306a36Sopenharmony_ci m = map_mft_record(base_ni); 143962306a36Sopenharmony_ci if (IS_ERR(m)) { 144062306a36Sopenharmony_ci err = PTR_ERR(m); 144162306a36Sopenharmony_ci m = NULL; 144262306a36Sopenharmony_ci ctx = NULL; 144362306a36Sopenharmony_ci goto err_out; 144462306a36Sopenharmony_ci } 144562306a36Sopenharmony_ci /* 144662306a36Sopenharmony_ci * If a parallel write made the attribute non-resident, drop the mft 144762306a36Sopenharmony_ci * record and retry the writepage. 144862306a36Sopenharmony_ci */ 144962306a36Sopenharmony_ci if (unlikely(NInoNonResident(ni))) { 145062306a36Sopenharmony_ci unmap_mft_record(base_ni); 145162306a36Sopenharmony_ci goto retry_writepage; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci ctx = ntfs_attr_get_search_ctx(base_ni, m); 145462306a36Sopenharmony_ci if (unlikely(!ctx)) { 145562306a36Sopenharmony_ci err = -ENOMEM; 145662306a36Sopenharmony_ci goto err_out; 145762306a36Sopenharmony_ci } 145862306a36Sopenharmony_ci err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, 145962306a36Sopenharmony_ci CASE_SENSITIVE, 0, NULL, 0, ctx); 146062306a36Sopenharmony_ci if (unlikely(err)) 146162306a36Sopenharmony_ci goto err_out; 146262306a36Sopenharmony_ci /* 146362306a36Sopenharmony_ci * Keep the VM happy. This must be done otherwise the radix-tree tag 146462306a36Sopenharmony_ci * PAGECACHE_TAG_DIRTY remains set even though the page is clean. 146562306a36Sopenharmony_ci */ 146662306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 146762306a36Sopenharmony_ci set_page_writeback(page); 146862306a36Sopenharmony_ci unlock_page(page); 146962306a36Sopenharmony_ci attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); 147062306a36Sopenharmony_ci i_size = i_size_read(vi); 147162306a36Sopenharmony_ci if (unlikely(attr_len > i_size)) { 147262306a36Sopenharmony_ci /* Race with shrinking truncate or a failed truncate. */ 147362306a36Sopenharmony_ci attr_len = i_size; 147462306a36Sopenharmony_ci /* 147562306a36Sopenharmony_ci * If the truncate failed, fix it up now. If a concurrent 147662306a36Sopenharmony_ci * truncate, we do its job, so it does not have to do anything. 147762306a36Sopenharmony_ci */ 147862306a36Sopenharmony_ci err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, 147962306a36Sopenharmony_ci attr_len); 148062306a36Sopenharmony_ci /* Shrinking cannot fail. */ 148162306a36Sopenharmony_ci BUG_ON(err); 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci addr = kmap_atomic(page); 148462306a36Sopenharmony_ci /* Copy the data from the page to the mft record. */ 148562306a36Sopenharmony_ci memcpy((u8*)ctx->attr + 148662306a36Sopenharmony_ci le16_to_cpu(ctx->attr->data.resident.value_offset), 148762306a36Sopenharmony_ci addr, attr_len); 148862306a36Sopenharmony_ci /* Zero out of bounds area in the page cache page. */ 148962306a36Sopenharmony_ci memset(addr + attr_len, 0, PAGE_SIZE - attr_len); 149062306a36Sopenharmony_ci kunmap_atomic(addr); 149162306a36Sopenharmony_ci flush_dcache_page(page); 149262306a36Sopenharmony_ci flush_dcache_mft_record_page(ctx->ntfs_ino); 149362306a36Sopenharmony_ci /* We are done with the page. */ 149462306a36Sopenharmony_ci end_page_writeback(page); 149562306a36Sopenharmony_ci /* Finally, mark the mft record dirty, so it gets written back. */ 149662306a36Sopenharmony_ci mark_mft_record_dirty(ctx->ntfs_ino); 149762306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 149862306a36Sopenharmony_ci unmap_mft_record(base_ni); 149962306a36Sopenharmony_ci return 0; 150062306a36Sopenharmony_cierr_out: 150162306a36Sopenharmony_ci if (err == -ENOMEM) { 150262306a36Sopenharmony_ci ntfs_warning(vi->i_sb, "Error allocating memory. Redirtying " 150362306a36Sopenharmony_ci "page so we try again later."); 150462306a36Sopenharmony_ci /* 150562306a36Sopenharmony_ci * Put the page back on mapping->dirty_pages, but leave its 150662306a36Sopenharmony_ci * buffers' dirty state as-is. 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 150962306a36Sopenharmony_ci err = 0; 151062306a36Sopenharmony_ci } else { 151162306a36Sopenharmony_ci ntfs_error(vi->i_sb, "Resident attribute write failed with " 151262306a36Sopenharmony_ci "error %i.", err); 151362306a36Sopenharmony_ci SetPageError(page); 151462306a36Sopenharmony_ci NVolSetErrors(ni->vol); 151562306a36Sopenharmony_ci } 151662306a36Sopenharmony_ci unlock_page(page); 151762306a36Sopenharmony_ci if (ctx) 151862306a36Sopenharmony_ci ntfs_attr_put_search_ctx(ctx); 151962306a36Sopenharmony_ci if (m) 152062306a36Sopenharmony_ci unmap_mft_record(base_ni); 152162306a36Sopenharmony_ci return err; 152262306a36Sopenharmony_ci} 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci#endif /* NTFS_RW */ 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci/** 152762306a36Sopenharmony_ci * ntfs_bmap - map logical file block to physical device block 152862306a36Sopenharmony_ci * @mapping: address space mapping to which the block to be mapped belongs 152962306a36Sopenharmony_ci * @block: logical block to map to its physical device block 153062306a36Sopenharmony_ci * 153162306a36Sopenharmony_ci * For regular, non-resident files (i.e. not compressed and not encrypted), map 153262306a36Sopenharmony_ci * the logical @block belonging to the file described by the address space 153362306a36Sopenharmony_ci * mapping @mapping to its physical device block. 153462306a36Sopenharmony_ci * 153562306a36Sopenharmony_ci * The size of the block is equal to the @s_blocksize field of the super block 153662306a36Sopenharmony_ci * of the mounted file system which is guaranteed to be smaller than or equal 153762306a36Sopenharmony_ci * to the cluster size thus the block is guaranteed to fit entirely inside the 153862306a36Sopenharmony_ci * cluster which means we do not need to care how many contiguous bytes are 153962306a36Sopenharmony_ci * available after the beginning of the block. 154062306a36Sopenharmony_ci * 154162306a36Sopenharmony_ci * Return the physical device block if the mapping succeeded or 0 if the block 154262306a36Sopenharmony_ci * is sparse or there was an error. 154362306a36Sopenharmony_ci * 154462306a36Sopenharmony_ci * Note: This is a problem if someone tries to run bmap() on $Boot system file 154562306a36Sopenharmony_ci * as that really is in block zero but there is nothing we can do. bmap() is 154662306a36Sopenharmony_ci * just broken in that respect (just like it cannot distinguish sparse from 154762306a36Sopenharmony_ci * not available or error). 154862306a36Sopenharmony_ci */ 154962306a36Sopenharmony_cistatic sector_t ntfs_bmap(struct address_space *mapping, sector_t block) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci s64 ofs, size; 155262306a36Sopenharmony_ci loff_t i_size; 155362306a36Sopenharmony_ci LCN lcn; 155462306a36Sopenharmony_ci unsigned long blocksize, flags; 155562306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(mapping->host); 155662306a36Sopenharmony_ci ntfs_volume *vol = ni->vol; 155762306a36Sopenharmony_ci unsigned delta; 155862306a36Sopenharmony_ci unsigned char blocksize_bits, cluster_size_shift; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci ntfs_debug("Entering for mft_no 0x%lx, logical block 0x%llx.", 156162306a36Sopenharmony_ci ni->mft_no, (unsigned long long)block); 156262306a36Sopenharmony_ci if (ni->type != AT_DATA || !NInoNonResident(ni) || NInoEncrypted(ni)) { 156362306a36Sopenharmony_ci ntfs_error(vol->sb, "BMAP does not make sense for %s " 156462306a36Sopenharmony_ci "attributes, returning 0.", 156562306a36Sopenharmony_ci (ni->type != AT_DATA) ? "non-data" : 156662306a36Sopenharmony_ci (!NInoNonResident(ni) ? "resident" : 156762306a36Sopenharmony_ci "encrypted")); 156862306a36Sopenharmony_ci return 0; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci /* None of these can happen. */ 157162306a36Sopenharmony_ci BUG_ON(NInoCompressed(ni)); 157262306a36Sopenharmony_ci BUG_ON(NInoMstProtected(ni)); 157362306a36Sopenharmony_ci blocksize = vol->sb->s_blocksize; 157462306a36Sopenharmony_ci blocksize_bits = vol->sb->s_blocksize_bits; 157562306a36Sopenharmony_ci ofs = (s64)block << blocksize_bits; 157662306a36Sopenharmony_ci read_lock_irqsave(&ni->size_lock, flags); 157762306a36Sopenharmony_ci size = ni->initialized_size; 157862306a36Sopenharmony_ci i_size = i_size_read(VFS_I(ni)); 157962306a36Sopenharmony_ci read_unlock_irqrestore(&ni->size_lock, flags); 158062306a36Sopenharmony_ci /* 158162306a36Sopenharmony_ci * If the offset is outside the initialized size or the block straddles 158262306a36Sopenharmony_ci * the initialized size then pretend it is a hole unless the 158362306a36Sopenharmony_ci * initialized size equals the file size. 158462306a36Sopenharmony_ci */ 158562306a36Sopenharmony_ci if (unlikely(ofs >= size || (ofs + blocksize > size && size < i_size))) 158662306a36Sopenharmony_ci goto hole; 158762306a36Sopenharmony_ci cluster_size_shift = vol->cluster_size_bits; 158862306a36Sopenharmony_ci down_read(&ni->runlist.lock); 158962306a36Sopenharmony_ci lcn = ntfs_attr_vcn_to_lcn_nolock(ni, ofs >> cluster_size_shift, false); 159062306a36Sopenharmony_ci up_read(&ni->runlist.lock); 159162306a36Sopenharmony_ci if (unlikely(lcn < LCN_HOLE)) { 159262306a36Sopenharmony_ci /* 159362306a36Sopenharmony_ci * Step down to an integer to avoid gcc doing a long long 159462306a36Sopenharmony_ci * comparision in the switch when we know @lcn is between 159562306a36Sopenharmony_ci * LCN_HOLE and LCN_EIO (i.e. -1 to -5). 159662306a36Sopenharmony_ci * 159762306a36Sopenharmony_ci * Otherwise older gcc (at least on some architectures) will 159862306a36Sopenharmony_ci * try to use __cmpdi2() which is of course not available in 159962306a36Sopenharmony_ci * the kernel. 160062306a36Sopenharmony_ci */ 160162306a36Sopenharmony_ci switch ((int)lcn) { 160262306a36Sopenharmony_ci case LCN_ENOENT: 160362306a36Sopenharmony_ci /* 160462306a36Sopenharmony_ci * If the offset is out of bounds then pretend it is a 160562306a36Sopenharmony_ci * hole. 160662306a36Sopenharmony_ci */ 160762306a36Sopenharmony_ci goto hole; 160862306a36Sopenharmony_ci case LCN_ENOMEM: 160962306a36Sopenharmony_ci ntfs_error(vol->sb, "Not enough memory to complete " 161062306a36Sopenharmony_ci "mapping for inode 0x%lx. " 161162306a36Sopenharmony_ci "Returning 0.", ni->mft_no); 161262306a36Sopenharmony_ci break; 161362306a36Sopenharmony_ci default: 161462306a36Sopenharmony_ci ntfs_error(vol->sb, "Failed to complete mapping for " 161562306a36Sopenharmony_ci "inode 0x%lx. Run chkdsk. " 161662306a36Sopenharmony_ci "Returning 0.", ni->mft_no); 161762306a36Sopenharmony_ci break; 161862306a36Sopenharmony_ci } 161962306a36Sopenharmony_ci return 0; 162062306a36Sopenharmony_ci } 162162306a36Sopenharmony_ci if (lcn < 0) { 162262306a36Sopenharmony_ci /* It is a hole. */ 162362306a36Sopenharmony_cihole: 162462306a36Sopenharmony_ci ntfs_debug("Done (returning hole)."); 162562306a36Sopenharmony_ci return 0; 162662306a36Sopenharmony_ci } 162762306a36Sopenharmony_ci /* 162862306a36Sopenharmony_ci * The block is really allocated and fullfils all our criteria. 162962306a36Sopenharmony_ci * Convert the cluster to units of block size and return the result. 163062306a36Sopenharmony_ci */ 163162306a36Sopenharmony_ci delta = ofs & vol->cluster_size_mask; 163262306a36Sopenharmony_ci if (unlikely(sizeof(block) < sizeof(lcn))) { 163362306a36Sopenharmony_ci block = lcn = ((lcn << cluster_size_shift) + delta) >> 163462306a36Sopenharmony_ci blocksize_bits; 163562306a36Sopenharmony_ci /* If the block number was truncated return 0. */ 163662306a36Sopenharmony_ci if (unlikely(block != lcn)) { 163762306a36Sopenharmony_ci ntfs_error(vol->sb, "Physical block 0x%llx is too " 163862306a36Sopenharmony_ci "large to be returned, returning 0.", 163962306a36Sopenharmony_ci (long long)lcn); 164062306a36Sopenharmony_ci return 0; 164162306a36Sopenharmony_ci } 164262306a36Sopenharmony_ci } else 164362306a36Sopenharmony_ci block = ((lcn << cluster_size_shift) + delta) >> 164462306a36Sopenharmony_ci blocksize_bits; 164562306a36Sopenharmony_ci ntfs_debug("Done (returning block 0x%llx).", (unsigned long long)lcn); 164662306a36Sopenharmony_ci return block; 164762306a36Sopenharmony_ci} 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci/* 165062306a36Sopenharmony_ci * ntfs_normal_aops - address space operations for normal inodes and attributes 165162306a36Sopenharmony_ci * 165262306a36Sopenharmony_ci * Note these are not used for compressed or mst protected inodes and 165362306a36Sopenharmony_ci * attributes. 165462306a36Sopenharmony_ci */ 165562306a36Sopenharmony_ciconst struct address_space_operations ntfs_normal_aops = { 165662306a36Sopenharmony_ci .read_folio = ntfs_read_folio, 165762306a36Sopenharmony_ci#ifdef NTFS_RW 165862306a36Sopenharmony_ci .writepage = ntfs_writepage, 165962306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 166062306a36Sopenharmony_ci#endif /* NTFS_RW */ 166162306a36Sopenharmony_ci .bmap = ntfs_bmap, 166262306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 166362306a36Sopenharmony_ci .is_partially_uptodate = block_is_partially_uptodate, 166462306a36Sopenharmony_ci .error_remove_page = generic_error_remove_page, 166562306a36Sopenharmony_ci}; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci/* 166862306a36Sopenharmony_ci * ntfs_compressed_aops - address space operations for compressed inodes 166962306a36Sopenharmony_ci */ 167062306a36Sopenharmony_ciconst struct address_space_operations ntfs_compressed_aops = { 167162306a36Sopenharmony_ci .read_folio = ntfs_read_folio, 167262306a36Sopenharmony_ci#ifdef NTFS_RW 167362306a36Sopenharmony_ci .writepage = ntfs_writepage, 167462306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 167562306a36Sopenharmony_ci#endif /* NTFS_RW */ 167662306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 167762306a36Sopenharmony_ci .is_partially_uptodate = block_is_partially_uptodate, 167862306a36Sopenharmony_ci .error_remove_page = generic_error_remove_page, 167962306a36Sopenharmony_ci}; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci/* 168262306a36Sopenharmony_ci * ntfs_mst_aops - general address space operations for mst protecteed inodes 168362306a36Sopenharmony_ci * and attributes 168462306a36Sopenharmony_ci */ 168562306a36Sopenharmony_ciconst struct address_space_operations ntfs_mst_aops = { 168662306a36Sopenharmony_ci .read_folio = ntfs_read_folio, /* Fill page with data. */ 168762306a36Sopenharmony_ci#ifdef NTFS_RW 168862306a36Sopenharmony_ci .writepage = ntfs_writepage, /* Write dirty page to disk. */ 168962306a36Sopenharmony_ci .dirty_folio = filemap_dirty_folio, 169062306a36Sopenharmony_ci#endif /* NTFS_RW */ 169162306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 169262306a36Sopenharmony_ci .is_partially_uptodate = block_is_partially_uptodate, 169362306a36Sopenharmony_ci .error_remove_page = generic_error_remove_page, 169462306a36Sopenharmony_ci}; 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci#ifdef NTFS_RW 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci/** 169962306a36Sopenharmony_ci * mark_ntfs_record_dirty - mark an ntfs record dirty 170062306a36Sopenharmony_ci * @page: page containing the ntfs record to mark dirty 170162306a36Sopenharmony_ci * @ofs: byte offset within @page at which the ntfs record begins 170262306a36Sopenharmony_ci * 170362306a36Sopenharmony_ci * Set the buffers and the page in which the ntfs record is located dirty. 170462306a36Sopenharmony_ci * 170562306a36Sopenharmony_ci * The latter also marks the vfs inode the ntfs record belongs to dirty 170662306a36Sopenharmony_ci * (I_DIRTY_PAGES only). 170762306a36Sopenharmony_ci * 170862306a36Sopenharmony_ci * If the page does not have buffers, we create them and set them uptodate. 170962306a36Sopenharmony_ci * The page may not be locked which is why we need to handle the buffers under 171062306a36Sopenharmony_ci * the mapping->private_lock. Once the buffers are marked dirty we no longer 171162306a36Sopenharmony_ci * need the lock since try_to_free_buffers() does not free dirty buffers. 171262306a36Sopenharmony_ci */ 171362306a36Sopenharmony_civoid mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) { 171462306a36Sopenharmony_ci struct address_space *mapping = page->mapping; 171562306a36Sopenharmony_ci ntfs_inode *ni = NTFS_I(mapping->host); 171662306a36Sopenharmony_ci struct buffer_head *bh, *head, *buffers_to_free = NULL; 171762306a36Sopenharmony_ci unsigned int end, bh_size, bh_ofs; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci BUG_ON(!PageUptodate(page)); 172062306a36Sopenharmony_ci end = ofs + ni->itype.index.block_size; 172162306a36Sopenharmony_ci bh_size = VFS_I(ni)->i_sb->s_blocksize; 172262306a36Sopenharmony_ci spin_lock(&mapping->private_lock); 172362306a36Sopenharmony_ci if (unlikely(!page_has_buffers(page))) { 172462306a36Sopenharmony_ci spin_unlock(&mapping->private_lock); 172562306a36Sopenharmony_ci bh = head = alloc_page_buffers(page, bh_size, true); 172662306a36Sopenharmony_ci spin_lock(&mapping->private_lock); 172762306a36Sopenharmony_ci if (likely(!page_has_buffers(page))) { 172862306a36Sopenharmony_ci struct buffer_head *tail; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci do { 173162306a36Sopenharmony_ci set_buffer_uptodate(bh); 173262306a36Sopenharmony_ci tail = bh; 173362306a36Sopenharmony_ci bh = bh->b_this_page; 173462306a36Sopenharmony_ci } while (bh); 173562306a36Sopenharmony_ci tail->b_this_page = head; 173662306a36Sopenharmony_ci attach_page_private(page, head); 173762306a36Sopenharmony_ci } else 173862306a36Sopenharmony_ci buffers_to_free = bh; 173962306a36Sopenharmony_ci } 174062306a36Sopenharmony_ci bh = head = page_buffers(page); 174162306a36Sopenharmony_ci BUG_ON(!bh); 174262306a36Sopenharmony_ci do { 174362306a36Sopenharmony_ci bh_ofs = bh_offset(bh); 174462306a36Sopenharmony_ci if (bh_ofs + bh_size <= ofs) 174562306a36Sopenharmony_ci continue; 174662306a36Sopenharmony_ci if (unlikely(bh_ofs >= end)) 174762306a36Sopenharmony_ci break; 174862306a36Sopenharmony_ci set_buffer_dirty(bh); 174962306a36Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 175062306a36Sopenharmony_ci spin_unlock(&mapping->private_lock); 175162306a36Sopenharmony_ci filemap_dirty_folio(mapping, page_folio(page)); 175262306a36Sopenharmony_ci if (unlikely(buffers_to_free)) { 175362306a36Sopenharmony_ci do { 175462306a36Sopenharmony_ci bh = buffers_to_free->b_this_page; 175562306a36Sopenharmony_ci free_buffer_head(buffers_to_free); 175662306a36Sopenharmony_ci buffers_to_free = bh; 175762306a36Sopenharmony_ci } while (buffers_to_free); 175862306a36Sopenharmony_ci } 175962306a36Sopenharmony_ci} 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci#endif /* NTFS_RW */ 1762