18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/**
38c2ecf20Sopenharmony_ci * aops.c - NTFS kernel address space operations and page cache handling.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc.
68c2ecf20Sopenharmony_ci * Copyright (c) 2002 Richard Russon
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/errno.h>
108c2ecf20Sopenharmony_ci#include <linux/fs.h>
118c2ecf20Sopenharmony_ci#include <linux/gfp.h>
128c2ecf20Sopenharmony_ci#include <linux/mm.h>
138c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
148c2ecf20Sopenharmony_ci#include <linux/swap.h>
158c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
168c2ecf20Sopenharmony_ci#include <linux/writeback.h>
178c2ecf20Sopenharmony_ci#include <linux/bit_spinlock.h>
188c2ecf20Sopenharmony_ci#include <linux/bio.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "aops.h"
218c2ecf20Sopenharmony_ci#include "attrib.h"
228c2ecf20Sopenharmony_ci#include "debug.h"
238c2ecf20Sopenharmony_ci#include "inode.h"
248c2ecf20Sopenharmony_ci#include "mft.h"
258c2ecf20Sopenharmony_ci#include "runlist.h"
268c2ecf20Sopenharmony_ci#include "types.h"
278c2ecf20Sopenharmony_ci#include "ntfs.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/**
308c2ecf20Sopenharmony_ci * ntfs_end_buffer_async_read - async io completion for reading attributes
318c2ecf20Sopenharmony_ci * @bh:		buffer head on which io is completed
328c2ecf20Sopenharmony_ci * @uptodate:	whether @bh is now uptodate or not
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Asynchronous I/O completion handler for reading pages belonging to the
358c2ecf20Sopenharmony_ci * attribute address space of an inode.  The inodes can either be files or
368c2ecf20Sopenharmony_ci * directories or they can be fake inodes describing some attribute.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * If NInoMstProtected(), perform the post read mst fixups when all IO on the
398c2ecf20Sopenharmony_ci * page has been completed and mark the page uptodate or set the error bit on
408c2ecf20Sopenharmony_ci * the page.  To determine the size of the records that need fixing up, we
418c2ecf20Sopenharmony_ci * cheat a little bit by setting the index_block_size in ntfs_inode to the ntfs
428c2ecf20Sopenharmony_ci * record size, and index_block_size_bits, to the log(base 2) of the ntfs
438c2ecf20Sopenharmony_ci * record size.
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_cistatic void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	unsigned long flags;
488c2ecf20Sopenharmony_ci	struct buffer_head *first, *tmp;
498c2ecf20Sopenharmony_ci	struct page *page;
508c2ecf20Sopenharmony_ci	struct inode *vi;
518c2ecf20Sopenharmony_ci	ntfs_inode *ni;
528c2ecf20Sopenharmony_ci	int page_uptodate = 1;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	page = bh->b_page;
558c2ecf20Sopenharmony_ci	vi = page->mapping->host;
568c2ecf20Sopenharmony_ci	ni = NTFS_I(vi);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (likely(uptodate)) {
598c2ecf20Sopenharmony_ci		loff_t i_size;
608c2ecf20Sopenharmony_ci		s64 file_ofs, init_size;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci		set_buffer_uptodate(bh);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		file_ofs = ((s64)page->index << PAGE_SHIFT) +
658c2ecf20Sopenharmony_ci				bh_offset(bh);
668c2ecf20Sopenharmony_ci		read_lock_irqsave(&ni->size_lock, flags);
678c2ecf20Sopenharmony_ci		init_size = ni->initialized_size;
688c2ecf20Sopenharmony_ci		i_size = i_size_read(vi);
698c2ecf20Sopenharmony_ci		read_unlock_irqrestore(&ni->size_lock, flags);
708c2ecf20Sopenharmony_ci		if (unlikely(init_size > i_size)) {
718c2ecf20Sopenharmony_ci			/* Race with shrinking truncate. */
728c2ecf20Sopenharmony_ci			init_size = i_size;
738c2ecf20Sopenharmony_ci		}
748c2ecf20Sopenharmony_ci		/* Check for the current buffer head overflowing. */
758c2ecf20Sopenharmony_ci		if (unlikely(file_ofs + bh->b_size > init_size)) {
768c2ecf20Sopenharmony_ci			int ofs;
778c2ecf20Sopenharmony_ci			void *kaddr;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci			ofs = 0;
808c2ecf20Sopenharmony_ci			if (file_ofs < init_size)
818c2ecf20Sopenharmony_ci				ofs = init_size - file_ofs;
828c2ecf20Sopenharmony_ci			kaddr = kmap_atomic(page);
838c2ecf20Sopenharmony_ci			memset(kaddr + bh_offset(bh) + ofs, 0,
848c2ecf20Sopenharmony_ci					bh->b_size - ofs);
858c2ecf20Sopenharmony_ci			flush_dcache_page(page);
868c2ecf20Sopenharmony_ci			kunmap_atomic(kaddr);
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci	} else {
898c2ecf20Sopenharmony_ci		clear_buffer_uptodate(bh);
908c2ecf20Sopenharmony_ci		SetPageError(page);
918c2ecf20Sopenharmony_ci		ntfs_error(ni->vol->sb, "Buffer I/O error, logical block "
928c2ecf20Sopenharmony_ci				"0x%llx.", (unsigned long long)bh->b_blocknr);
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci	first = page_buffers(page);
958c2ecf20Sopenharmony_ci	spin_lock_irqsave(&first->b_uptodate_lock, flags);
968c2ecf20Sopenharmony_ci	clear_buffer_async_read(bh);
978c2ecf20Sopenharmony_ci	unlock_buffer(bh);
988c2ecf20Sopenharmony_ci	tmp = bh;
998c2ecf20Sopenharmony_ci	do {
1008c2ecf20Sopenharmony_ci		if (!buffer_uptodate(tmp))
1018c2ecf20Sopenharmony_ci			page_uptodate = 0;
1028c2ecf20Sopenharmony_ci		if (buffer_async_read(tmp)) {
1038c2ecf20Sopenharmony_ci			if (likely(buffer_locked(tmp)))
1048c2ecf20Sopenharmony_ci				goto still_busy;
1058c2ecf20Sopenharmony_ci			/* Async buffers must be locked. */
1068c2ecf20Sopenharmony_ci			BUG();
1078c2ecf20Sopenharmony_ci		}
1088c2ecf20Sopenharmony_ci		tmp = tmp->b_this_page;
1098c2ecf20Sopenharmony_ci	} while (tmp != bh);
1108c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
1118c2ecf20Sopenharmony_ci	/*
1128c2ecf20Sopenharmony_ci	 * If none of the buffers had errors then we can set the page uptodate,
1138c2ecf20Sopenharmony_ci	 * but we first have to perform the post read mst fixups, if the
1148c2ecf20Sopenharmony_ci	 * attribute is mst protected, i.e. if NInoMstProteced(ni) is true.
1158c2ecf20Sopenharmony_ci	 * Note we ignore fixup errors as those are detected when
1168c2ecf20Sopenharmony_ci	 * map_mft_record() is called which gives us per record granularity
1178c2ecf20Sopenharmony_ci	 * rather than per page granularity.
1188c2ecf20Sopenharmony_ci	 */
1198c2ecf20Sopenharmony_ci	if (!NInoMstProtected(ni)) {
1208c2ecf20Sopenharmony_ci		if (likely(page_uptodate && !PageError(page)))
1218c2ecf20Sopenharmony_ci			SetPageUptodate(page);
1228c2ecf20Sopenharmony_ci	} else {
1238c2ecf20Sopenharmony_ci		u8 *kaddr;
1248c2ecf20Sopenharmony_ci		unsigned int i, recs;
1258c2ecf20Sopenharmony_ci		u32 rec_size;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci		rec_size = ni->itype.index.block_size;
1288c2ecf20Sopenharmony_ci		recs = PAGE_SIZE / rec_size;
1298c2ecf20Sopenharmony_ci		/* Should have been verified before we got here... */
1308c2ecf20Sopenharmony_ci		BUG_ON(!recs);
1318c2ecf20Sopenharmony_ci		kaddr = kmap_atomic(page);
1328c2ecf20Sopenharmony_ci		for (i = 0; i < recs; i++)
1338c2ecf20Sopenharmony_ci			post_read_mst_fixup((NTFS_RECORD*)(kaddr +
1348c2ecf20Sopenharmony_ci					i * rec_size), rec_size);
1358c2ecf20Sopenharmony_ci		kunmap_atomic(kaddr);
1368c2ecf20Sopenharmony_ci		flush_dcache_page(page);
1378c2ecf20Sopenharmony_ci		if (likely(page_uptodate && !PageError(page)))
1388c2ecf20Sopenharmony_ci			SetPageUptodate(page);
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci	unlock_page(page);
1418c2ecf20Sopenharmony_ci	return;
1428c2ecf20Sopenharmony_cistill_busy:
1438c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
1448c2ecf20Sopenharmony_ci	return;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci/**
1488c2ecf20Sopenharmony_ci * ntfs_read_block - fill a @page of an address space with data
1498c2ecf20Sopenharmony_ci * @page:	page cache page to fill with data
1508c2ecf20Sopenharmony_ci *
1518c2ecf20Sopenharmony_ci * Fill the page @page of the address space belonging to the @page->host inode.
1528c2ecf20Sopenharmony_ci * We read each buffer asynchronously and when all buffers are read in, our io
1538c2ecf20Sopenharmony_ci * completion handler ntfs_end_buffer_read_async(), if required, automatically
1548c2ecf20Sopenharmony_ci * applies the mst fixups to the page before finally marking it uptodate and
1558c2ecf20Sopenharmony_ci * unlocking it.
1568c2ecf20Sopenharmony_ci *
1578c2ecf20Sopenharmony_ci * We only enforce allocated_size limit because i_size is checked for in
1588c2ecf20Sopenharmony_ci * generic_file_read().
1598c2ecf20Sopenharmony_ci *
1608c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
1618c2ecf20Sopenharmony_ci *
1628c2ecf20Sopenharmony_ci * Contains an adapted version of fs/buffer.c::block_read_full_page().
1638c2ecf20Sopenharmony_ci */
1648c2ecf20Sopenharmony_cistatic int ntfs_read_block(struct page *page)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	loff_t i_size;
1678c2ecf20Sopenharmony_ci	VCN vcn;
1688c2ecf20Sopenharmony_ci	LCN lcn;
1698c2ecf20Sopenharmony_ci	s64 init_size;
1708c2ecf20Sopenharmony_ci	struct inode *vi;
1718c2ecf20Sopenharmony_ci	ntfs_inode *ni;
1728c2ecf20Sopenharmony_ci	ntfs_volume *vol;
1738c2ecf20Sopenharmony_ci	runlist_element *rl;
1748c2ecf20Sopenharmony_ci	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
1758c2ecf20Sopenharmony_ci	sector_t iblock, lblock, zblock;
1768c2ecf20Sopenharmony_ci	unsigned long flags;
1778c2ecf20Sopenharmony_ci	unsigned int blocksize, vcn_ofs;
1788c2ecf20Sopenharmony_ci	int i, nr;
1798c2ecf20Sopenharmony_ci	unsigned char blocksize_bits;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	vi = page->mapping->host;
1828c2ecf20Sopenharmony_ci	ni = NTFS_I(vi);
1838c2ecf20Sopenharmony_ci	vol = ni->vol;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	/* $MFT/$DATA must have its complete runlist in memory at all times. */
1868c2ecf20Sopenharmony_ci	BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni));
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	blocksize = vol->sb->s_blocksize;
1898c2ecf20Sopenharmony_ci	blocksize_bits = vol->sb->s_blocksize_bits;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (!page_has_buffers(page)) {
1928c2ecf20Sopenharmony_ci		create_empty_buffers(page, blocksize, 0);
1938c2ecf20Sopenharmony_ci		if (unlikely(!page_has_buffers(page))) {
1948c2ecf20Sopenharmony_ci			unlock_page(page);
1958c2ecf20Sopenharmony_ci			return -ENOMEM;
1968c2ecf20Sopenharmony_ci		}
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci	bh = head = page_buffers(page);
1998c2ecf20Sopenharmony_ci	BUG_ON(!bh);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/*
2028c2ecf20Sopenharmony_ci	 * We may be racing with truncate.  To avoid some of the problems we
2038c2ecf20Sopenharmony_ci	 * now take a snapshot of the various sizes and use those for the whole
2048c2ecf20Sopenharmony_ci	 * of the function.  In case of an extending truncate it just means we
2058c2ecf20Sopenharmony_ci	 * may leave some buffers unmapped which are now allocated.  This is
2068c2ecf20Sopenharmony_ci	 * not a problem since these buffers will just get mapped when a write
2078c2ecf20Sopenharmony_ci	 * occurs.  In case of a shrinking truncate, we will detect this later
2088c2ecf20Sopenharmony_ci	 * on due to the runlist being incomplete and if the page is being
2098c2ecf20Sopenharmony_ci	 * fully truncated, truncate will throw it away as soon as we unlock
2108c2ecf20Sopenharmony_ci	 * it so no need to worry what we do with it.
2118c2ecf20Sopenharmony_ci	 */
2128c2ecf20Sopenharmony_ci	iblock = (s64)page->index << (PAGE_SHIFT - blocksize_bits);
2138c2ecf20Sopenharmony_ci	read_lock_irqsave(&ni->size_lock, flags);
2148c2ecf20Sopenharmony_ci	lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
2158c2ecf20Sopenharmony_ci	init_size = ni->initialized_size;
2168c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
2178c2ecf20Sopenharmony_ci	read_unlock_irqrestore(&ni->size_lock, flags);
2188c2ecf20Sopenharmony_ci	if (unlikely(init_size > i_size)) {
2198c2ecf20Sopenharmony_ci		/* Race with shrinking truncate. */
2208c2ecf20Sopenharmony_ci		init_size = i_size;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci	zblock = (init_size + blocksize - 1) >> blocksize_bits;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Loop through all the buffers in the page. */
2258c2ecf20Sopenharmony_ci	rl = NULL;
2268c2ecf20Sopenharmony_ci	nr = i = 0;
2278c2ecf20Sopenharmony_ci	do {
2288c2ecf20Sopenharmony_ci		int err = 0;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci		if (unlikely(buffer_uptodate(bh)))
2318c2ecf20Sopenharmony_ci			continue;
2328c2ecf20Sopenharmony_ci		if (unlikely(buffer_mapped(bh))) {
2338c2ecf20Sopenharmony_ci			arr[nr++] = bh;
2348c2ecf20Sopenharmony_ci			continue;
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci		bh->b_bdev = vol->sb->s_bdev;
2378c2ecf20Sopenharmony_ci		/* Is the block within the allowed limits? */
2388c2ecf20Sopenharmony_ci		if (iblock < lblock) {
2398c2ecf20Sopenharmony_ci			bool is_retry = false;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci			/* Convert iblock into corresponding vcn and offset. */
2428c2ecf20Sopenharmony_ci			vcn = (VCN)iblock << blocksize_bits >>
2438c2ecf20Sopenharmony_ci					vol->cluster_size_bits;
2448c2ecf20Sopenharmony_ci			vcn_ofs = ((VCN)iblock << blocksize_bits) &
2458c2ecf20Sopenharmony_ci					vol->cluster_size_mask;
2468c2ecf20Sopenharmony_ci			if (!rl) {
2478c2ecf20Sopenharmony_cilock_retry_remap:
2488c2ecf20Sopenharmony_ci				down_read(&ni->runlist.lock);
2498c2ecf20Sopenharmony_ci				rl = ni->runlist.rl;
2508c2ecf20Sopenharmony_ci			}
2518c2ecf20Sopenharmony_ci			if (likely(rl != NULL)) {
2528c2ecf20Sopenharmony_ci				/* Seek to element containing target vcn. */
2538c2ecf20Sopenharmony_ci				while (rl->length && rl[1].vcn <= vcn)
2548c2ecf20Sopenharmony_ci					rl++;
2558c2ecf20Sopenharmony_ci				lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
2568c2ecf20Sopenharmony_ci			} else
2578c2ecf20Sopenharmony_ci				lcn = LCN_RL_NOT_MAPPED;
2588c2ecf20Sopenharmony_ci			/* Successful remap. */
2598c2ecf20Sopenharmony_ci			if (lcn >= 0) {
2608c2ecf20Sopenharmony_ci				/* Setup buffer head to correct block. */
2618c2ecf20Sopenharmony_ci				bh->b_blocknr = ((lcn << vol->cluster_size_bits)
2628c2ecf20Sopenharmony_ci						+ vcn_ofs) >> blocksize_bits;
2638c2ecf20Sopenharmony_ci				set_buffer_mapped(bh);
2648c2ecf20Sopenharmony_ci				/* Only read initialized data blocks. */
2658c2ecf20Sopenharmony_ci				if (iblock < zblock) {
2668c2ecf20Sopenharmony_ci					arr[nr++] = bh;
2678c2ecf20Sopenharmony_ci					continue;
2688c2ecf20Sopenharmony_ci				}
2698c2ecf20Sopenharmony_ci				/* Fully non-initialized data block, zero it. */
2708c2ecf20Sopenharmony_ci				goto handle_zblock;
2718c2ecf20Sopenharmony_ci			}
2728c2ecf20Sopenharmony_ci			/* It is a hole, need to zero it. */
2738c2ecf20Sopenharmony_ci			if (lcn == LCN_HOLE)
2748c2ecf20Sopenharmony_ci				goto handle_hole;
2758c2ecf20Sopenharmony_ci			/* If first try and runlist unmapped, map and retry. */
2768c2ecf20Sopenharmony_ci			if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
2778c2ecf20Sopenharmony_ci				is_retry = true;
2788c2ecf20Sopenharmony_ci				/*
2798c2ecf20Sopenharmony_ci				 * Attempt to map runlist, dropping lock for
2808c2ecf20Sopenharmony_ci				 * the duration.
2818c2ecf20Sopenharmony_ci				 */
2828c2ecf20Sopenharmony_ci				up_read(&ni->runlist.lock);
2838c2ecf20Sopenharmony_ci				err = ntfs_map_runlist(ni, vcn);
2848c2ecf20Sopenharmony_ci				if (likely(!err))
2858c2ecf20Sopenharmony_ci					goto lock_retry_remap;
2868c2ecf20Sopenharmony_ci				rl = NULL;
2878c2ecf20Sopenharmony_ci			} else if (!rl)
2888c2ecf20Sopenharmony_ci				up_read(&ni->runlist.lock);
2898c2ecf20Sopenharmony_ci			/*
2908c2ecf20Sopenharmony_ci			 * If buffer is outside the runlist, treat it as a
2918c2ecf20Sopenharmony_ci			 * hole.  This can happen due to concurrent truncate
2928c2ecf20Sopenharmony_ci			 * for example.
2938c2ecf20Sopenharmony_ci			 */
2948c2ecf20Sopenharmony_ci			if (err == -ENOENT || lcn == LCN_ENOENT) {
2958c2ecf20Sopenharmony_ci				err = 0;
2968c2ecf20Sopenharmony_ci				goto handle_hole;
2978c2ecf20Sopenharmony_ci			}
2988c2ecf20Sopenharmony_ci			/* Hard error, zero out region. */
2998c2ecf20Sopenharmony_ci			if (!err)
3008c2ecf20Sopenharmony_ci				err = -EIO;
3018c2ecf20Sopenharmony_ci			bh->b_blocknr = -1;
3028c2ecf20Sopenharmony_ci			SetPageError(page);
3038c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Failed to read from inode 0x%lx, "
3048c2ecf20Sopenharmony_ci					"attribute type 0x%x, vcn 0x%llx, "
3058c2ecf20Sopenharmony_ci					"offset 0x%x because its location on "
3068c2ecf20Sopenharmony_ci					"disk could not be determined%s "
3078c2ecf20Sopenharmony_ci					"(error code %i).", ni->mft_no,
3088c2ecf20Sopenharmony_ci					ni->type, (unsigned long long)vcn,
3098c2ecf20Sopenharmony_ci					vcn_ofs, is_retry ? " even after "
3108c2ecf20Sopenharmony_ci					"retrying" : "", err);
3118c2ecf20Sopenharmony_ci		}
3128c2ecf20Sopenharmony_ci		/*
3138c2ecf20Sopenharmony_ci		 * Either iblock was outside lblock limits or
3148c2ecf20Sopenharmony_ci		 * ntfs_rl_vcn_to_lcn() returned error.  Just zero that portion
3158c2ecf20Sopenharmony_ci		 * of the page and set the buffer uptodate.
3168c2ecf20Sopenharmony_ci		 */
3178c2ecf20Sopenharmony_cihandle_hole:
3188c2ecf20Sopenharmony_ci		bh->b_blocknr = -1UL;
3198c2ecf20Sopenharmony_ci		clear_buffer_mapped(bh);
3208c2ecf20Sopenharmony_cihandle_zblock:
3218c2ecf20Sopenharmony_ci		zero_user(page, i * blocksize, blocksize);
3228c2ecf20Sopenharmony_ci		if (likely(!err))
3238c2ecf20Sopenharmony_ci			set_buffer_uptodate(bh);
3248c2ecf20Sopenharmony_ci	} while (i++, iblock++, (bh = bh->b_this_page) != head);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* Release the lock if we took it. */
3278c2ecf20Sopenharmony_ci	if (rl)
3288c2ecf20Sopenharmony_ci		up_read(&ni->runlist.lock);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* Check we have at least one buffer ready for i/o. */
3318c2ecf20Sopenharmony_ci	if (nr) {
3328c2ecf20Sopenharmony_ci		struct buffer_head *tbh;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		/* Lock the buffers. */
3358c2ecf20Sopenharmony_ci		for (i = 0; i < nr; i++) {
3368c2ecf20Sopenharmony_ci			tbh = arr[i];
3378c2ecf20Sopenharmony_ci			lock_buffer(tbh);
3388c2ecf20Sopenharmony_ci			tbh->b_end_io = ntfs_end_buffer_async_read;
3398c2ecf20Sopenharmony_ci			set_buffer_async_read(tbh);
3408c2ecf20Sopenharmony_ci		}
3418c2ecf20Sopenharmony_ci		/* Finally, start i/o on the buffers. */
3428c2ecf20Sopenharmony_ci		for (i = 0; i < nr; i++) {
3438c2ecf20Sopenharmony_ci			tbh = arr[i];
3448c2ecf20Sopenharmony_ci			if (likely(!buffer_uptodate(tbh)))
3458c2ecf20Sopenharmony_ci				submit_bh(REQ_OP_READ, 0, tbh);
3468c2ecf20Sopenharmony_ci			else
3478c2ecf20Sopenharmony_ci				ntfs_end_buffer_async_read(tbh, 1);
3488c2ecf20Sopenharmony_ci		}
3498c2ecf20Sopenharmony_ci		return 0;
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci	/* No i/o was scheduled on any of the buffers. */
3528c2ecf20Sopenharmony_ci	if (likely(!PageError(page)))
3538c2ecf20Sopenharmony_ci		SetPageUptodate(page);
3548c2ecf20Sopenharmony_ci	else /* Signal synchronous i/o error. */
3558c2ecf20Sopenharmony_ci		nr = -EIO;
3568c2ecf20Sopenharmony_ci	unlock_page(page);
3578c2ecf20Sopenharmony_ci	return nr;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci/**
3618c2ecf20Sopenharmony_ci * ntfs_readpage - fill a @page of a @file with data from the device
3628c2ecf20Sopenharmony_ci * @file:	open file to which the page @page belongs or NULL
3638c2ecf20Sopenharmony_ci * @page:	page cache page to fill with data
3648c2ecf20Sopenharmony_ci *
3658c2ecf20Sopenharmony_ci * For non-resident attributes, ntfs_readpage() fills the @page of the open
3668c2ecf20Sopenharmony_ci * file @file by calling the ntfs version of the generic block_read_full_page()
3678c2ecf20Sopenharmony_ci * function, ntfs_read_block(), which in turn creates and reads in the buffers
3688c2ecf20Sopenharmony_ci * associated with the page asynchronously.
3698c2ecf20Sopenharmony_ci *
3708c2ecf20Sopenharmony_ci * For resident attributes, OTOH, ntfs_readpage() fills @page by copying the
3718c2ecf20Sopenharmony_ci * data from the mft record (which at this stage is most likely in memory) and
3728c2ecf20Sopenharmony_ci * fills the remainder with zeroes. Thus, in this case, I/O is synchronous, as
3738c2ecf20Sopenharmony_ci * even if the mft record is not cached at this point in time, we need to wait
3748c2ecf20Sopenharmony_ci * for it to be read in before we can do the copy.
3758c2ecf20Sopenharmony_ci *
3768c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
3778c2ecf20Sopenharmony_ci */
3788c2ecf20Sopenharmony_cistatic int ntfs_readpage(struct file *file, struct page *page)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	loff_t i_size;
3818c2ecf20Sopenharmony_ci	struct inode *vi;
3828c2ecf20Sopenharmony_ci	ntfs_inode *ni, *base_ni;
3838c2ecf20Sopenharmony_ci	u8 *addr;
3848c2ecf20Sopenharmony_ci	ntfs_attr_search_ctx *ctx;
3858c2ecf20Sopenharmony_ci	MFT_RECORD *mrec;
3868c2ecf20Sopenharmony_ci	unsigned long flags;
3878c2ecf20Sopenharmony_ci	u32 attr_len;
3888c2ecf20Sopenharmony_ci	int err = 0;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ciretry_readpage:
3918c2ecf20Sopenharmony_ci	BUG_ON(!PageLocked(page));
3928c2ecf20Sopenharmony_ci	vi = page->mapping->host;
3938c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
3948c2ecf20Sopenharmony_ci	/* Is the page fully outside i_size? (truncate in progress) */
3958c2ecf20Sopenharmony_ci	if (unlikely(page->index >= (i_size + PAGE_SIZE - 1) >>
3968c2ecf20Sopenharmony_ci			PAGE_SHIFT)) {
3978c2ecf20Sopenharmony_ci		zero_user(page, 0, PAGE_SIZE);
3988c2ecf20Sopenharmony_ci		ntfs_debug("Read outside i_size - truncated?");
3998c2ecf20Sopenharmony_ci		goto done;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci	/*
4028c2ecf20Sopenharmony_ci	 * This can potentially happen because we clear PageUptodate() during
4038c2ecf20Sopenharmony_ci	 * ntfs_writepage() of MstProtected() attributes.
4048c2ecf20Sopenharmony_ci	 */
4058c2ecf20Sopenharmony_ci	if (PageUptodate(page)) {
4068c2ecf20Sopenharmony_ci		unlock_page(page);
4078c2ecf20Sopenharmony_ci		return 0;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci	ni = NTFS_I(vi);
4108c2ecf20Sopenharmony_ci	/*
4118c2ecf20Sopenharmony_ci	 * Only $DATA attributes can be encrypted and only unnamed $DATA
4128c2ecf20Sopenharmony_ci	 * attributes can be compressed.  Index root can have the flags set but
4138c2ecf20Sopenharmony_ci	 * this means to create compressed/encrypted files, not that the
4148c2ecf20Sopenharmony_ci	 * attribute is compressed/encrypted.  Note we need to check for
4158c2ecf20Sopenharmony_ci	 * AT_INDEX_ALLOCATION since this is the type of both directory and
4168c2ecf20Sopenharmony_ci	 * index inodes.
4178c2ecf20Sopenharmony_ci	 */
4188c2ecf20Sopenharmony_ci	if (ni->type != AT_INDEX_ALLOCATION) {
4198c2ecf20Sopenharmony_ci		/* If attribute is encrypted, deny access, just like NT4. */
4208c2ecf20Sopenharmony_ci		if (NInoEncrypted(ni)) {
4218c2ecf20Sopenharmony_ci			BUG_ON(ni->type != AT_DATA);
4228c2ecf20Sopenharmony_ci			err = -EACCES;
4238c2ecf20Sopenharmony_ci			goto err_out;
4248c2ecf20Sopenharmony_ci		}
4258c2ecf20Sopenharmony_ci		/* Compressed data streams are handled in compress.c. */
4268c2ecf20Sopenharmony_ci		if (NInoNonResident(ni) && NInoCompressed(ni)) {
4278c2ecf20Sopenharmony_ci			BUG_ON(ni->type != AT_DATA);
4288c2ecf20Sopenharmony_ci			BUG_ON(ni->name_len);
4298c2ecf20Sopenharmony_ci			return ntfs_read_compressed_block(page);
4308c2ecf20Sopenharmony_ci		}
4318c2ecf20Sopenharmony_ci	}
4328c2ecf20Sopenharmony_ci	/* NInoNonResident() == NInoIndexAllocPresent() */
4338c2ecf20Sopenharmony_ci	if (NInoNonResident(ni)) {
4348c2ecf20Sopenharmony_ci		/* Normal, non-resident data stream. */
4358c2ecf20Sopenharmony_ci		return ntfs_read_block(page);
4368c2ecf20Sopenharmony_ci	}
4378c2ecf20Sopenharmony_ci	/*
4388c2ecf20Sopenharmony_ci	 * Attribute is resident, implying it is not compressed or encrypted.
4398c2ecf20Sopenharmony_ci	 * This also means the attribute is smaller than an mft record and
4408c2ecf20Sopenharmony_ci	 * hence smaller than a page, so can simply zero out any pages with
4418c2ecf20Sopenharmony_ci	 * index above 0.  Note the attribute can actually be marked compressed
4428c2ecf20Sopenharmony_ci	 * but if it is resident the actual data is not compressed so we are
4438c2ecf20Sopenharmony_ci	 * ok to ignore the compressed flag here.
4448c2ecf20Sopenharmony_ci	 */
4458c2ecf20Sopenharmony_ci	if (unlikely(page->index > 0)) {
4468c2ecf20Sopenharmony_ci		zero_user(page, 0, PAGE_SIZE);
4478c2ecf20Sopenharmony_ci		goto done;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci	if (!NInoAttr(ni))
4508c2ecf20Sopenharmony_ci		base_ni = ni;
4518c2ecf20Sopenharmony_ci	else
4528c2ecf20Sopenharmony_ci		base_ni = ni->ext.base_ntfs_ino;
4538c2ecf20Sopenharmony_ci	/* Map, pin, and lock the mft record. */
4548c2ecf20Sopenharmony_ci	mrec = map_mft_record(base_ni);
4558c2ecf20Sopenharmony_ci	if (IS_ERR(mrec)) {
4568c2ecf20Sopenharmony_ci		err = PTR_ERR(mrec);
4578c2ecf20Sopenharmony_ci		goto err_out;
4588c2ecf20Sopenharmony_ci	}
4598c2ecf20Sopenharmony_ci	/*
4608c2ecf20Sopenharmony_ci	 * If a parallel write made the attribute non-resident, drop the mft
4618c2ecf20Sopenharmony_ci	 * record and retry the readpage.
4628c2ecf20Sopenharmony_ci	 */
4638c2ecf20Sopenharmony_ci	if (unlikely(NInoNonResident(ni))) {
4648c2ecf20Sopenharmony_ci		unmap_mft_record(base_ni);
4658c2ecf20Sopenharmony_ci		goto retry_readpage;
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
4688c2ecf20Sopenharmony_ci	if (unlikely(!ctx)) {
4698c2ecf20Sopenharmony_ci		err = -ENOMEM;
4708c2ecf20Sopenharmony_ci		goto unm_err_out;
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
4738c2ecf20Sopenharmony_ci			CASE_SENSITIVE, 0, NULL, 0, ctx);
4748c2ecf20Sopenharmony_ci	if (unlikely(err))
4758c2ecf20Sopenharmony_ci		goto put_unm_err_out;
4768c2ecf20Sopenharmony_ci	attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
4778c2ecf20Sopenharmony_ci	read_lock_irqsave(&ni->size_lock, flags);
4788c2ecf20Sopenharmony_ci	if (unlikely(attr_len > ni->initialized_size))
4798c2ecf20Sopenharmony_ci		attr_len = ni->initialized_size;
4808c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
4818c2ecf20Sopenharmony_ci	read_unlock_irqrestore(&ni->size_lock, flags);
4828c2ecf20Sopenharmony_ci	if (unlikely(attr_len > i_size)) {
4838c2ecf20Sopenharmony_ci		/* Race with shrinking truncate. */
4848c2ecf20Sopenharmony_ci		attr_len = i_size;
4858c2ecf20Sopenharmony_ci	}
4868c2ecf20Sopenharmony_ci	addr = kmap_atomic(page);
4878c2ecf20Sopenharmony_ci	/* Copy the data to the page. */
4888c2ecf20Sopenharmony_ci	memcpy(addr, (u8*)ctx->attr +
4898c2ecf20Sopenharmony_ci			le16_to_cpu(ctx->attr->data.resident.value_offset),
4908c2ecf20Sopenharmony_ci			attr_len);
4918c2ecf20Sopenharmony_ci	/* Zero the remainder of the page. */
4928c2ecf20Sopenharmony_ci	memset(addr + attr_len, 0, PAGE_SIZE - attr_len);
4938c2ecf20Sopenharmony_ci	flush_dcache_page(page);
4948c2ecf20Sopenharmony_ci	kunmap_atomic(addr);
4958c2ecf20Sopenharmony_ciput_unm_err_out:
4968c2ecf20Sopenharmony_ci	ntfs_attr_put_search_ctx(ctx);
4978c2ecf20Sopenharmony_ciunm_err_out:
4988c2ecf20Sopenharmony_ci	unmap_mft_record(base_ni);
4998c2ecf20Sopenharmony_cidone:
5008c2ecf20Sopenharmony_ci	SetPageUptodate(page);
5018c2ecf20Sopenharmony_cierr_out:
5028c2ecf20Sopenharmony_ci	unlock_page(page);
5038c2ecf20Sopenharmony_ci	return err;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci#ifdef NTFS_RW
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci/**
5098c2ecf20Sopenharmony_ci * ntfs_write_block - write a @page to the backing store
5108c2ecf20Sopenharmony_ci * @page:	page cache page to write out
5118c2ecf20Sopenharmony_ci * @wbc:	writeback control structure
5128c2ecf20Sopenharmony_ci *
5138c2ecf20Sopenharmony_ci * This function is for writing pages belonging to non-resident, non-mst
5148c2ecf20Sopenharmony_ci * protected attributes to their backing store.
5158c2ecf20Sopenharmony_ci *
5168c2ecf20Sopenharmony_ci * For a page with buffers, map and write the dirty buffers asynchronously
5178c2ecf20Sopenharmony_ci * under page writeback. For a page without buffers, create buffers for the
5188c2ecf20Sopenharmony_ci * page, then proceed as above.
5198c2ecf20Sopenharmony_ci *
5208c2ecf20Sopenharmony_ci * If a page doesn't have buffers the page dirty state is definitive. If a page
5218c2ecf20Sopenharmony_ci * does have buffers, the page dirty state is just a hint, and the buffer dirty
5228c2ecf20Sopenharmony_ci * state is definitive. (A hint which has rules: dirty buffers against a clean
5238c2ecf20Sopenharmony_ci * page is illegal. Other combinations are legal and need to be handled. In
5248c2ecf20Sopenharmony_ci * particular a dirty page containing clean buffers for example.)
5258c2ecf20Sopenharmony_ci *
5268c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
5278c2ecf20Sopenharmony_ci *
5288c2ecf20Sopenharmony_ci * Based on ntfs_read_block() and __block_write_full_page().
5298c2ecf20Sopenharmony_ci */
5308c2ecf20Sopenharmony_cistatic int ntfs_write_block(struct page *page, struct writeback_control *wbc)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	VCN vcn;
5338c2ecf20Sopenharmony_ci	LCN lcn;
5348c2ecf20Sopenharmony_ci	s64 initialized_size;
5358c2ecf20Sopenharmony_ci	loff_t i_size;
5368c2ecf20Sopenharmony_ci	sector_t block, dblock, iblock;
5378c2ecf20Sopenharmony_ci	struct inode *vi;
5388c2ecf20Sopenharmony_ci	ntfs_inode *ni;
5398c2ecf20Sopenharmony_ci	ntfs_volume *vol;
5408c2ecf20Sopenharmony_ci	runlist_element *rl;
5418c2ecf20Sopenharmony_ci	struct buffer_head *bh, *head;
5428c2ecf20Sopenharmony_ci	unsigned long flags;
5438c2ecf20Sopenharmony_ci	unsigned int blocksize, vcn_ofs;
5448c2ecf20Sopenharmony_ci	int err;
5458c2ecf20Sopenharmony_ci	bool need_end_writeback;
5468c2ecf20Sopenharmony_ci	unsigned char blocksize_bits;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	vi = page->mapping->host;
5498c2ecf20Sopenharmony_ci	ni = NTFS_I(vi);
5508c2ecf20Sopenharmony_ci	vol = ni->vol;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
5538c2ecf20Sopenharmony_ci			"0x%lx.", ni->mft_no, ni->type, page->index);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	BUG_ON(!NInoNonResident(ni));
5568c2ecf20Sopenharmony_ci	BUG_ON(NInoMstProtected(ni));
5578c2ecf20Sopenharmony_ci	blocksize = vol->sb->s_blocksize;
5588c2ecf20Sopenharmony_ci	blocksize_bits = vol->sb->s_blocksize_bits;
5598c2ecf20Sopenharmony_ci	if (!page_has_buffers(page)) {
5608c2ecf20Sopenharmony_ci		BUG_ON(!PageUptodate(page));
5618c2ecf20Sopenharmony_ci		create_empty_buffers(page, blocksize,
5628c2ecf20Sopenharmony_ci				(1 << BH_Uptodate) | (1 << BH_Dirty));
5638c2ecf20Sopenharmony_ci		if (unlikely(!page_has_buffers(page))) {
5648c2ecf20Sopenharmony_ci			ntfs_warning(vol->sb, "Error allocating page "
5658c2ecf20Sopenharmony_ci					"buffers.  Redirtying page so we try "
5668c2ecf20Sopenharmony_ci					"again later.");
5678c2ecf20Sopenharmony_ci			/*
5688c2ecf20Sopenharmony_ci			 * Put the page back on mapping->dirty_pages, but leave
5698c2ecf20Sopenharmony_ci			 * its buffers' dirty state as-is.
5708c2ecf20Sopenharmony_ci			 */
5718c2ecf20Sopenharmony_ci			redirty_page_for_writepage(wbc, page);
5728c2ecf20Sopenharmony_ci			unlock_page(page);
5738c2ecf20Sopenharmony_ci			return 0;
5748c2ecf20Sopenharmony_ci		}
5758c2ecf20Sopenharmony_ci	}
5768c2ecf20Sopenharmony_ci	bh = head = page_buffers(page);
5778c2ecf20Sopenharmony_ci	BUG_ON(!bh);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/* NOTE: Different naming scheme to ntfs_read_block()! */
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	/* The first block in the page. */
5828c2ecf20Sopenharmony_ci	block = (s64)page->index << (PAGE_SHIFT - blocksize_bits);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	read_lock_irqsave(&ni->size_lock, flags);
5858c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
5868c2ecf20Sopenharmony_ci	initialized_size = ni->initialized_size;
5878c2ecf20Sopenharmony_ci	read_unlock_irqrestore(&ni->size_lock, flags);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	/* The first out of bounds block for the data size. */
5908c2ecf20Sopenharmony_ci	dblock = (i_size + blocksize - 1) >> blocksize_bits;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	/* The last (fully or partially) initialized block. */
5938c2ecf20Sopenharmony_ci	iblock = initialized_size >> blocksize_bits;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	/*
5968c2ecf20Sopenharmony_ci	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers
5978c2ecf20Sopenharmony_ci	 * here, and the (potentially unmapped) buffers may become dirty at
5988c2ecf20Sopenharmony_ci	 * any time.  If a buffer becomes dirty here after we've inspected it
5998c2ecf20Sopenharmony_ci	 * then we just miss that fact, and the page stays dirty.
6008c2ecf20Sopenharmony_ci	 *
6018c2ecf20Sopenharmony_ci	 * Buffers outside i_size may be dirtied by __set_page_dirty_buffers;
6028c2ecf20Sopenharmony_ci	 * handle that here by just cleaning them.
6038c2ecf20Sopenharmony_ci	 */
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	/*
6068c2ecf20Sopenharmony_ci	 * Loop through all the buffers in the page, mapping all the dirty
6078c2ecf20Sopenharmony_ci	 * buffers to disk addresses and handling any aliases from the
6088c2ecf20Sopenharmony_ci	 * underlying block device's mapping.
6098c2ecf20Sopenharmony_ci	 */
6108c2ecf20Sopenharmony_ci	rl = NULL;
6118c2ecf20Sopenharmony_ci	err = 0;
6128c2ecf20Sopenharmony_ci	do {
6138c2ecf20Sopenharmony_ci		bool is_retry = false;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci		if (unlikely(block >= dblock)) {
6168c2ecf20Sopenharmony_ci			/*
6178c2ecf20Sopenharmony_ci			 * Mapped buffers outside i_size will occur, because
6188c2ecf20Sopenharmony_ci			 * this page can be outside i_size when there is a
6198c2ecf20Sopenharmony_ci			 * truncate in progress. The contents of such buffers
6208c2ecf20Sopenharmony_ci			 * were zeroed by ntfs_writepage().
6218c2ecf20Sopenharmony_ci			 *
6228c2ecf20Sopenharmony_ci			 * FIXME: What about the small race window where
6238c2ecf20Sopenharmony_ci			 * ntfs_writepage() has not done any clearing because
6248c2ecf20Sopenharmony_ci			 * the page was within i_size but before we get here,
6258c2ecf20Sopenharmony_ci			 * vmtruncate() modifies i_size?
6268c2ecf20Sopenharmony_ci			 */
6278c2ecf20Sopenharmony_ci			clear_buffer_dirty(bh);
6288c2ecf20Sopenharmony_ci			set_buffer_uptodate(bh);
6298c2ecf20Sopenharmony_ci			continue;
6308c2ecf20Sopenharmony_ci		}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci		/* Clean buffers are not written out, so no need to map them. */
6338c2ecf20Sopenharmony_ci		if (!buffer_dirty(bh))
6348c2ecf20Sopenharmony_ci			continue;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci		/* Make sure we have enough initialized size. */
6378c2ecf20Sopenharmony_ci		if (unlikely((block >= iblock) &&
6388c2ecf20Sopenharmony_ci				(initialized_size < i_size))) {
6398c2ecf20Sopenharmony_ci			/*
6408c2ecf20Sopenharmony_ci			 * If this page is fully outside initialized size, zero
6418c2ecf20Sopenharmony_ci			 * out all pages between the current initialized size
6428c2ecf20Sopenharmony_ci			 * and the current page. Just use ntfs_readpage() to do
6438c2ecf20Sopenharmony_ci			 * the zeroing transparently.
6448c2ecf20Sopenharmony_ci			 */
6458c2ecf20Sopenharmony_ci			if (block > iblock) {
6468c2ecf20Sopenharmony_ci				// TODO:
6478c2ecf20Sopenharmony_ci				// For each page do:
6488c2ecf20Sopenharmony_ci				// - read_cache_page()
6498c2ecf20Sopenharmony_ci				// Again for each page do:
6508c2ecf20Sopenharmony_ci				// - wait_on_page_locked()
6518c2ecf20Sopenharmony_ci				// - Check (PageUptodate(page) &&
6528c2ecf20Sopenharmony_ci				//			!PageError(page))
6538c2ecf20Sopenharmony_ci				// Update initialized size in the attribute and
6548c2ecf20Sopenharmony_ci				// in the inode.
6558c2ecf20Sopenharmony_ci				// Again, for each page do:
6568c2ecf20Sopenharmony_ci				//	__set_page_dirty_buffers();
6578c2ecf20Sopenharmony_ci				// put_page()
6588c2ecf20Sopenharmony_ci				// We don't need to wait on the writes.
6598c2ecf20Sopenharmony_ci				// Update iblock.
6608c2ecf20Sopenharmony_ci			}
6618c2ecf20Sopenharmony_ci			/*
6628c2ecf20Sopenharmony_ci			 * The current page straddles initialized size. Zero
6638c2ecf20Sopenharmony_ci			 * all non-uptodate buffers and set them uptodate (and
6648c2ecf20Sopenharmony_ci			 * dirty?). Note, there aren't any non-uptodate buffers
6658c2ecf20Sopenharmony_ci			 * if the page is uptodate.
6668c2ecf20Sopenharmony_ci			 * FIXME: For an uptodate page, the buffers may need to
6678c2ecf20Sopenharmony_ci			 * be written out because they were not initialized on
6688c2ecf20Sopenharmony_ci			 * disk before.
6698c2ecf20Sopenharmony_ci			 */
6708c2ecf20Sopenharmony_ci			if (!PageUptodate(page)) {
6718c2ecf20Sopenharmony_ci				// TODO:
6728c2ecf20Sopenharmony_ci				// Zero any non-uptodate buffers up to i_size.
6738c2ecf20Sopenharmony_ci				// Set them uptodate and dirty.
6748c2ecf20Sopenharmony_ci			}
6758c2ecf20Sopenharmony_ci			// TODO:
6768c2ecf20Sopenharmony_ci			// Update initialized size in the attribute and in the
6778c2ecf20Sopenharmony_ci			// inode (up to i_size).
6788c2ecf20Sopenharmony_ci			// Update iblock.
6798c2ecf20Sopenharmony_ci			// FIXME: This is inefficient. Try to batch the two
6808c2ecf20Sopenharmony_ci			// size changes to happen in one go.
6818c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Writing beyond initialized size "
6828c2ecf20Sopenharmony_ci					"is not supported yet. Sorry.");
6838c2ecf20Sopenharmony_ci			err = -EOPNOTSUPP;
6848c2ecf20Sopenharmony_ci			break;
6858c2ecf20Sopenharmony_ci			// Do NOT set_buffer_new() BUT DO clear buffer range
6868c2ecf20Sopenharmony_ci			// outside write request range.
6878c2ecf20Sopenharmony_ci			// set_buffer_uptodate() on complete buffers as well as
6888c2ecf20Sopenharmony_ci			// set_buffer_dirty().
6898c2ecf20Sopenharmony_ci		}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci		/* No need to map buffers that are already mapped. */
6928c2ecf20Sopenharmony_ci		if (buffer_mapped(bh))
6938c2ecf20Sopenharmony_ci			continue;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci		/* Unmapped, dirty buffer. Need to map it. */
6968c2ecf20Sopenharmony_ci		bh->b_bdev = vol->sb->s_bdev;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci		/* Convert block into corresponding vcn and offset. */
6998c2ecf20Sopenharmony_ci		vcn = (VCN)block << blocksize_bits;
7008c2ecf20Sopenharmony_ci		vcn_ofs = vcn & vol->cluster_size_mask;
7018c2ecf20Sopenharmony_ci		vcn >>= vol->cluster_size_bits;
7028c2ecf20Sopenharmony_ci		if (!rl) {
7038c2ecf20Sopenharmony_cilock_retry_remap:
7048c2ecf20Sopenharmony_ci			down_read(&ni->runlist.lock);
7058c2ecf20Sopenharmony_ci			rl = ni->runlist.rl;
7068c2ecf20Sopenharmony_ci		}
7078c2ecf20Sopenharmony_ci		if (likely(rl != NULL)) {
7088c2ecf20Sopenharmony_ci			/* Seek to element containing target vcn. */
7098c2ecf20Sopenharmony_ci			while (rl->length && rl[1].vcn <= vcn)
7108c2ecf20Sopenharmony_ci				rl++;
7118c2ecf20Sopenharmony_ci			lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
7128c2ecf20Sopenharmony_ci		} else
7138c2ecf20Sopenharmony_ci			lcn = LCN_RL_NOT_MAPPED;
7148c2ecf20Sopenharmony_ci		/* Successful remap. */
7158c2ecf20Sopenharmony_ci		if (lcn >= 0) {
7168c2ecf20Sopenharmony_ci			/* Setup buffer head to point to correct block. */
7178c2ecf20Sopenharmony_ci			bh->b_blocknr = ((lcn << vol->cluster_size_bits) +
7188c2ecf20Sopenharmony_ci					vcn_ofs) >> blocksize_bits;
7198c2ecf20Sopenharmony_ci			set_buffer_mapped(bh);
7208c2ecf20Sopenharmony_ci			continue;
7218c2ecf20Sopenharmony_ci		}
7228c2ecf20Sopenharmony_ci		/* It is a hole, need to instantiate it. */
7238c2ecf20Sopenharmony_ci		if (lcn == LCN_HOLE) {
7248c2ecf20Sopenharmony_ci			u8 *kaddr;
7258c2ecf20Sopenharmony_ci			unsigned long *bpos, *bend;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci			/* Check if the buffer is zero. */
7288c2ecf20Sopenharmony_ci			kaddr = kmap_atomic(page);
7298c2ecf20Sopenharmony_ci			bpos = (unsigned long *)(kaddr + bh_offset(bh));
7308c2ecf20Sopenharmony_ci			bend = (unsigned long *)((u8*)bpos + blocksize);
7318c2ecf20Sopenharmony_ci			do {
7328c2ecf20Sopenharmony_ci				if (unlikely(*bpos))
7338c2ecf20Sopenharmony_ci					break;
7348c2ecf20Sopenharmony_ci			} while (likely(++bpos < bend));
7358c2ecf20Sopenharmony_ci			kunmap_atomic(kaddr);
7368c2ecf20Sopenharmony_ci			if (bpos == bend) {
7378c2ecf20Sopenharmony_ci				/*
7388c2ecf20Sopenharmony_ci				 * Buffer is zero and sparse, no need to write
7398c2ecf20Sopenharmony_ci				 * it.
7408c2ecf20Sopenharmony_ci				 */
7418c2ecf20Sopenharmony_ci				bh->b_blocknr = -1;
7428c2ecf20Sopenharmony_ci				clear_buffer_dirty(bh);
7438c2ecf20Sopenharmony_ci				continue;
7448c2ecf20Sopenharmony_ci			}
7458c2ecf20Sopenharmony_ci			// TODO: Instantiate the hole.
7468c2ecf20Sopenharmony_ci			// clear_buffer_new(bh);
7478c2ecf20Sopenharmony_ci			// clean_bdev_bh_alias(bh);
7488c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Writing into sparse regions is "
7498c2ecf20Sopenharmony_ci					"not supported yet. Sorry.");
7508c2ecf20Sopenharmony_ci			err = -EOPNOTSUPP;
7518c2ecf20Sopenharmony_ci			break;
7528c2ecf20Sopenharmony_ci		}
7538c2ecf20Sopenharmony_ci		/* If first try and runlist unmapped, map and retry. */
7548c2ecf20Sopenharmony_ci		if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
7558c2ecf20Sopenharmony_ci			is_retry = true;
7568c2ecf20Sopenharmony_ci			/*
7578c2ecf20Sopenharmony_ci			 * Attempt to map runlist, dropping lock for
7588c2ecf20Sopenharmony_ci			 * the duration.
7598c2ecf20Sopenharmony_ci			 */
7608c2ecf20Sopenharmony_ci			up_read(&ni->runlist.lock);
7618c2ecf20Sopenharmony_ci			err = ntfs_map_runlist(ni, vcn);
7628c2ecf20Sopenharmony_ci			if (likely(!err))
7638c2ecf20Sopenharmony_ci				goto lock_retry_remap;
7648c2ecf20Sopenharmony_ci			rl = NULL;
7658c2ecf20Sopenharmony_ci		} else if (!rl)
7668c2ecf20Sopenharmony_ci			up_read(&ni->runlist.lock);
7678c2ecf20Sopenharmony_ci		/*
7688c2ecf20Sopenharmony_ci		 * If buffer is outside the runlist, truncate has cut it out
7698c2ecf20Sopenharmony_ci		 * of the runlist.  Just clean and clear the buffer and set it
7708c2ecf20Sopenharmony_ci		 * uptodate so it can get discarded by the VM.
7718c2ecf20Sopenharmony_ci		 */
7728c2ecf20Sopenharmony_ci		if (err == -ENOENT || lcn == LCN_ENOENT) {
7738c2ecf20Sopenharmony_ci			bh->b_blocknr = -1;
7748c2ecf20Sopenharmony_ci			clear_buffer_dirty(bh);
7758c2ecf20Sopenharmony_ci			zero_user(page, bh_offset(bh), blocksize);
7768c2ecf20Sopenharmony_ci			set_buffer_uptodate(bh);
7778c2ecf20Sopenharmony_ci			err = 0;
7788c2ecf20Sopenharmony_ci			continue;
7798c2ecf20Sopenharmony_ci		}
7808c2ecf20Sopenharmony_ci		/* Failed to map the buffer, even after retrying. */
7818c2ecf20Sopenharmony_ci		if (!err)
7828c2ecf20Sopenharmony_ci			err = -EIO;
7838c2ecf20Sopenharmony_ci		bh->b_blocknr = -1;
7848c2ecf20Sopenharmony_ci		ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
7858c2ecf20Sopenharmony_ci				"attribute type 0x%x, vcn 0x%llx, offset 0x%x "
7868c2ecf20Sopenharmony_ci				"because its location on disk could not be "
7878c2ecf20Sopenharmony_ci				"determined%s (error code %i).", ni->mft_no,
7888c2ecf20Sopenharmony_ci				ni->type, (unsigned long long)vcn,
7898c2ecf20Sopenharmony_ci				vcn_ofs, is_retry ? " even after "
7908c2ecf20Sopenharmony_ci				"retrying" : "", err);
7918c2ecf20Sopenharmony_ci		break;
7928c2ecf20Sopenharmony_ci	} while (block++, (bh = bh->b_this_page) != head);
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/* Release the lock if we took it. */
7958c2ecf20Sopenharmony_ci	if (rl)
7968c2ecf20Sopenharmony_ci		up_read(&ni->runlist.lock);
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* For the error case, need to reset bh to the beginning. */
7998c2ecf20Sopenharmony_ci	bh = head;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	/* Just an optimization, so ->readpage() is not called later. */
8028c2ecf20Sopenharmony_ci	if (unlikely(!PageUptodate(page))) {
8038c2ecf20Sopenharmony_ci		int uptodate = 1;
8048c2ecf20Sopenharmony_ci		do {
8058c2ecf20Sopenharmony_ci			if (!buffer_uptodate(bh)) {
8068c2ecf20Sopenharmony_ci				uptodate = 0;
8078c2ecf20Sopenharmony_ci				bh = head;
8088c2ecf20Sopenharmony_ci				break;
8098c2ecf20Sopenharmony_ci			}
8108c2ecf20Sopenharmony_ci		} while ((bh = bh->b_this_page) != head);
8118c2ecf20Sopenharmony_ci		if (uptodate)
8128c2ecf20Sopenharmony_ci			SetPageUptodate(page);
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* Setup all mapped, dirty buffers for async write i/o. */
8168c2ecf20Sopenharmony_ci	do {
8178c2ecf20Sopenharmony_ci		if (buffer_mapped(bh) && buffer_dirty(bh)) {
8188c2ecf20Sopenharmony_ci			lock_buffer(bh);
8198c2ecf20Sopenharmony_ci			if (test_clear_buffer_dirty(bh)) {
8208c2ecf20Sopenharmony_ci				BUG_ON(!buffer_uptodate(bh));
8218c2ecf20Sopenharmony_ci				mark_buffer_async_write(bh);
8228c2ecf20Sopenharmony_ci			} else
8238c2ecf20Sopenharmony_ci				unlock_buffer(bh);
8248c2ecf20Sopenharmony_ci		} else if (unlikely(err)) {
8258c2ecf20Sopenharmony_ci			/*
8268c2ecf20Sopenharmony_ci			 * For the error case. The buffer may have been set
8278c2ecf20Sopenharmony_ci			 * dirty during attachment to a dirty page.
8288c2ecf20Sopenharmony_ci			 */
8298c2ecf20Sopenharmony_ci			if (err != -ENOMEM)
8308c2ecf20Sopenharmony_ci				clear_buffer_dirty(bh);
8318c2ecf20Sopenharmony_ci		}
8328c2ecf20Sopenharmony_ci	} while ((bh = bh->b_this_page) != head);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	if (unlikely(err)) {
8358c2ecf20Sopenharmony_ci		// TODO: Remove the -EOPNOTSUPP check later on...
8368c2ecf20Sopenharmony_ci		if (unlikely(err == -EOPNOTSUPP))
8378c2ecf20Sopenharmony_ci			err = 0;
8388c2ecf20Sopenharmony_ci		else if (err == -ENOMEM) {
8398c2ecf20Sopenharmony_ci			ntfs_warning(vol->sb, "Error allocating memory. "
8408c2ecf20Sopenharmony_ci					"Redirtying page so we try again "
8418c2ecf20Sopenharmony_ci					"later.");
8428c2ecf20Sopenharmony_ci			/*
8438c2ecf20Sopenharmony_ci			 * Put the page back on mapping->dirty_pages, but
8448c2ecf20Sopenharmony_ci			 * leave its buffer's dirty state as-is.
8458c2ecf20Sopenharmony_ci			 */
8468c2ecf20Sopenharmony_ci			redirty_page_for_writepage(wbc, page);
8478c2ecf20Sopenharmony_ci			err = 0;
8488c2ecf20Sopenharmony_ci		} else
8498c2ecf20Sopenharmony_ci			SetPageError(page);
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	BUG_ON(PageWriteback(page));
8538c2ecf20Sopenharmony_ci	set_page_writeback(page);	/* Keeps try_to_free_buffers() away. */
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	/* Submit the prepared buffers for i/o. */
8568c2ecf20Sopenharmony_ci	need_end_writeback = true;
8578c2ecf20Sopenharmony_ci	do {
8588c2ecf20Sopenharmony_ci		struct buffer_head *next = bh->b_this_page;
8598c2ecf20Sopenharmony_ci		if (buffer_async_write(bh)) {
8608c2ecf20Sopenharmony_ci			submit_bh(REQ_OP_WRITE, 0, bh);
8618c2ecf20Sopenharmony_ci			need_end_writeback = false;
8628c2ecf20Sopenharmony_ci		}
8638c2ecf20Sopenharmony_ci		bh = next;
8648c2ecf20Sopenharmony_ci	} while (bh != head);
8658c2ecf20Sopenharmony_ci	unlock_page(page);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	/* If no i/o was started, need to end_page_writeback(). */
8688c2ecf20Sopenharmony_ci	if (unlikely(need_end_writeback))
8698c2ecf20Sopenharmony_ci		end_page_writeback(page);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	ntfs_debug("Done.");
8728c2ecf20Sopenharmony_ci	return err;
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci/**
8768c2ecf20Sopenharmony_ci * ntfs_write_mst_block - write a @page to the backing store
8778c2ecf20Sopenharmony_ci * @page:	page cache page to write out
8788c2ecf20Sopenharmony_ci * @wbc:	writeback control structure
8798c2ecf20Sopenharmony_ci *
8808c2ecf20Sopenharmony_ci * This function is for writing pages belonging to non-resident, mst protected
8818c2ecf20Sopenharmony_ci * attributes to their backing store.  The only supported attributes are index
8828c2ecf20Sopenharmony_ci * allocation and $MFT/$DATA.  Both directory inodes and index inodes are
8838c2ecf20Sopenharmony_ci * supported for the index allocation case.
8848c2ecf20Sopenharmony_ci *
8858c2ecf20Sopenharmony_ci * The page must remain locked for the duration of the write because we apply
8868c2ecf20Sopenharmony_ci * the mst fixups, write, and then undo the fixups, so if we were to unlock the
8878c2ecf20Sopenharmony_ci * page before undoing the fixups, any other user of the page will see the
8888c2ecf20Sopenharmony_ci * page contents as corrupt.
8898c2ecf20Sopenharmony_ci *
8908c2ecf20Sopenharmony_ci * We clear the page uptodate flag for the duration of the function to ensure
8918c2ecf20Sopenharmony_ci * exclusion for the $MFT/$DATA case against someone mapping an mft record we
8928c2ecf20Sopenharmony_ci * are about to apply the mst fixups to.
8938c2ecf20Sopenharmony_ci *
8948c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
8958c2ecf20Sopenharmony_ci *
8968c2ecf20Sopenharmony_ci * Based on ntfs_write_block(), ntfs_mft_writepage(), and
8978c2ecf20Sopenharmony_ci * write_mft_record_nolock().
8988c2ecf20Sopenharmony_ci */
8998c2ecf20Sopenharmony_cistatic int ntfs_write_mst_block(struct page *page,
9008c2ecf20Sopenharmony_ci		struct writeback_control *wbc)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	sector_t block, dblock, rec_block;
9038c2ecf20Sopenharmony_ci	struct inode *vi = page->mapping->host;
9048c2ecf20Sopenharmony_ci	ntfs_inode *ni = NTFS_I(vi);
9058c2ecf20Sopenharmony_ci	ntfs_volume *vol = ni->vol;
9068c2ecf20Sopenharmony_ci	u8 *kaddr;
9078c2ecf20Sopenharmony_ci	unsigned int rec_size = ni->itype.index.block_size;
9088c2ecf20Sopenharmony_ci	ntfs_inode *locked_nis[PAGE_SIZE / NTFS_BLOCK_SIZE];
9098c2ecf20Sopenharmony_ci	struct buffer_head *bh, *head, *tbh, *rec_start_bh;
9108c2ecf20Sopenharmony_ci	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
9118c2ecf20Sopenharmony_ci	runlist_element *rl;
9128c2ecf20Sopenharmony_ci	int i, nr_locked_nis, nr_recs, nr_bhs, max_bhs, bhs_per_rec, err, err2;
9138c2ecf20Sopenharmony_ci	unsigned bh_size, rec_size_bits;
9148c2ecf20Sopenharmony_ci	bool sync, is_mft, page_is_dirty, rec_is_dirty;
9158c2ecf20Sopenharmony_ci	unsigned char bh_size_bits;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	if (WARN_ON(rec_size < NTFS_BLOCK_SIZE))
9188c2ecf20Sopenharmony_ci		return -EINVAL;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
9218c2ecf20Sopenharmony_ci			"0x%lx.", vi->i_ino, ni->type, page->index);
9228c2ecf20Sopenharmony_ci	BUG_ON(!NInoNonResident(ni));
9238c2ecf20Sopenharmony_ci	BUG_ON(!NInoMstProtected(ni));
9248c2ecf20Sopenharmony_ci	is_mft = (S_ISREG(vi->i_mode) && !vi->i_ino);
9258c2ecf20Sopenharmony_ci	/*
9268c2ecf20Sopenharmony_ci	 * NOTE: ntfs_write_mst_block() would be called for $MFTMirr if a page
9278c2ecf20Sopenharmony_ci	 * in its page cache were to be marked dirty.  However this should
9288c2ecf20Sopenharmony_ci	 * never happen with the current driver and considering we do not
9298c2ecf20Sopenharmony_ci	 * handle this case here we do want to BUG(), at least for now.
9308c2ecf20Sopenharmony_ci	 */
9318c2ecf20Sopenharmony_ci	BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) ||
9328c2ecf20Sopenharmony_ci			(NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION)));
9338c2ecf20Sopenharmony_ci	bh_size = vol->sb->s_blocksize;
9348c2ecf20Sopenharmony_ci	bh_size_bits = vol->sb->s_blocksize_bits;
9358c2ecf20Sopenharmony_ci	max_bhs = PAGE_SIZE / bh_size;
9368c2ecf20Sopenharmony_ci	BUG_ON(!max_bhs);
9378c2ecf20Sopenharmony_ci	BUG_ON(max_bhs > MAX_BUF_PER_PAGE);
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	/* Were we called for sync purposes? */
9408c2ecf20Sopenharmony_ci	sync = (wbc->sync_mode == WB_SYNC_ALL);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	/* Make sure we have mapped buffers. */
9438c2ecf20Sopenharmony_ci	bh = head = page_buffers(page);
9448c2ecf20Sopenharmony_ci	BUG_ON(!bh);
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	rec_size_bits = ni->itype.index.block_size_bits;
9478c2ecf20Sopenharmony_ci	BUG_ON(!(PAGE_SIZE >> rec_size_bits));
9488c2ecf20Sopenharmony_ci	bhs_per_rec = rec_size >> bh_size_bits;
9498c2ecf20Sopenharmony_ci	BUG_ON(!bhs_per_rec);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	/* The first block in the page. */
9528c2ecf20Sopenharmony_ci	rec_block = block = (sector_t)page->index <<
9538c2ecf20Sopenharmony_ci			(PAGE_SHIFT - bh_size_bits);
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	/* The first out of bounds block for the data size. */
9568c2ecf20Sopenharmony_ci	dblock = (i_size_read(vi) + bh_size - 1) >> bh_size_bits;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	rl = NULL;
9598c2ecf20Sopenharmony_ci	err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0;
9608c2ecf20Sopenharmony_ci	page_is_dirty = rec_is_dirty = false;
9618c2ecf20Sopenharmony_ci	rec_start_bh = NULL;
9628c2ecf20Sopenharmony_ci	do {
9638c2ecf20Sopenharmony_ci		bool is_retry = false;
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci		if (likely(block < rec_block)) {
9668c2ecf20Sopenharmony_ci			if (unlikely(block >= dblock)) {
9678c2ecf20Sopenharmony_ci				clear_buffer_dirty(bh);
9688c2ecf20Sopenharmony_ci				set_buffer_uptodate(bh);
9698c2ecf20Sopenharmony_ci				continue;
9708c2ecf20Sopenharmony_ci			}
9718c2ecf20Sopenharmony_ci			/*
9728c2ecf20Sopenharmony_ci			 * This block is not the first one in the record.  We
9738c2ecf20Sopenharmony_ci			 * ignore the buffer's dirty state because we could
9748c2ecf20Sopenharmony_ci			 * have raced with a parallel mark_ntfs_record_dirty().
9758c2ecf20Sopenharmony_ci			 */
9768c2ecf20Sopenharmony_ci			if (!rec_is_dirty)
9778c2ecf20Sopenharmony_ci				continue;
9788c2ecf20Sopenharmony_ci			if (unlikely(err2)) {
9798c2ecf20Sopenharmony_ci				if (err2 != -ENOMEM)
9808c2ecf20Sopenharmony_ci					clear_buffer_dirty(bh);
9818c2ecf20Sopenharmony_ci				continue;
9828c2ecf20Sopenharmony_ci			}
9838c2ecf20Sopenharmony_ci		} else /* if (block == rec_block) */ {
9848c2ecf20Sopenharmony_ci			BUG_ON(block > rec_block);
9858c2ecf20Sopenharmony_ci			/* This block is the first one in the record. */
9868c2ecf20Sopenharmony_ci			rec_block += bhs_per_rec;
9878c2ecf20Sopenharmony_ci			err2 = 0;
9888c2ecf20Sopenharmony_ci			if (unlikely(block >= dblock)) {
9898c2ecf20Sopenharmony_ci				clear_buffer_dirty(bh);
9908c2ecf20Sopenharmony_ci				continue;
9918c2ecf20Sopenharmony_ci			}
9928c2ecf20Sopenharmony_ci			if (!buffer_dirty(bh)) {
9938c2ecf20Sopenharmony_ci				/* Clean records are not written out. */
9948c2ecf20Sopenharmony_ci				rec_is_dirty = false;
9958c2ecf20Sopenharmony_ci				continue;
9968c2ecf20Sopenharmony_ci			}
9978c2ecf20Sopenharmony_ci			rec_is_dirty = true;
9988c2ecf20Sopenharmony_ci			rec_start_bh = bh;
9998c2ecf20Sopenharmony_ci		}
10008c2ecf20Sopenharmony_ci		/* Need to map the buffer if it is not mapped already. */
10018c2ecf20Sopenharmony_ci		if (unlikely(!buffer_mapped(bh))) {
10028c2ecf20Sopenharmony_ci			VCN vcn;
10038c2ecf20Sopenharmony_ci			LCN lcn;
10048c2ecf20Sopenharmony_ci			unsigned int vcn_ofs;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci			bh->b_bdev = vol->sb->s_bdev;
10078c2ecf20Sopenharmony_ci			/* Obtain the vcn and offset of the current block. */
10088c2ecf20Sopenharmony_ci			vcn = (VCN)block << bh_size_bits;
10098c2ecf20Sopenharmony_ci			vcn_ofs = vcn & vol->cluster_size_mask;
10108c2ecf20Sopenharmony_ci			vcn >>= vol->cluster_size_bits;
10118c2ecf20Sopenharmony_ci			if (!rl) {
10128c2ecf20Sopenharmony_cilock_retry_remap:
10138c2ecf20Sopenharmony_ci				down_read(&ni->runlist.lock);
10148c2ecf20Sopenharmony_ci				rl = ni->runlist.rl;
10158c2ecf20Sopenharmony_ci			}
10168c2ecf20Sopenharmony_ci			if (likely(rl != NULL)) {
10178c2ecf20Sopenharmony_ci				/* Seek to element containing target vcn. */
10188c2ecf20Sopenharmony_ci				while (rl->length && rl[1].vcn <= vcn)
10198c2ecf20Sopenharmony_ci					rl++;
10208c2ecf20Sopenharmony_ci				lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
10218c2ecf20Sopenharmony_ci			} else
10228c2ecf20Sopenharmony_ci				lcn = LCN_RL_NOT_MAPPED;
10238c2ecf20Sopenharmony_ci			/* Successful remap. */
10248c2ecf20Sopenharmony_ci			if (likely(lcn >= 0)) {
10258c2ecf20Sopenharmony_ci				/* Setup buffer head to correct block. */
10268c2ecf20Sopenharmony_ci				bh->b_blocknr = ((lcn <<
10278c2ecf20Sopenharmony_ci						vol->cluster_size_bits) +
10288c2ecf20Sopenharmony_ci						vcn_ofs) >> bh_size_bits;
10298c2ecf20Sopenharmony_ci				set_buffer_mapped(bh);
10308c2ecf20Sopenharmony_ci			} else {
10318c2ecf20Sopenharmony_ci				/*
10328c2ecf20Sopenharmony_ci				 * Remap failed.  Retry to map the runlist once
10338c2ecf20Sopenharmony_ci				 * unless we are working on $MFT which always
10348c2ecf20Sopenharmony_ci				 * has the whole of its runlist in memory.
10358c2ecf20Sopenharmony_ci				 */
10368c2ecf20Sopenharmony_ci				if (!is_mft && !is_retry &&
10378c2ecf20Sopenharmony_ci						lcn == LCN_RL_NOT_MAPPED) {
10388c2ecf20Sopenharmony_ci					is_retry = true;
10398c2ecf20Sopenharmony_ci					/*
10408c2ecf20Sopenharmony_ci					 * Attempt to map runlist, dropping
10418c2ecf20Sopenharmony_ci					 * lock for the duration.
10428c2ecf20Sopenharmony_ci					 */
10438c2ecf20Sopenharmony_ci					up_read(&ni->runlist.lock);
10448c2ecf20Sopenharmony_ci					err2 = ntfs_map_runlist(ni, vcn);
10458c2ecf20Sopenharmony_ci					if (likely(!err2))
10468c2ecf20Sopenharmony_ci						goto lock_retry_remap;
10478c2ecf20Sopenharmony_ci					if (err2 == -ENOMEM)
10488c2ecf20Sopenharmony_ci						page_is_dirty = true;
10498c2ecf20Sopenharmony_ci					lcn = err2;
10508c2ecf20Sopenharmony_ci				} else {
10518c2ecf20Sopenharmony_ci					err2 = -EIO;
10528c2ecf20Sopenharmony_ci					if (!rl)
10538c2ecf20Sopenharmony_ci						up_read(&ni->runlist.lock);
10548c2ecf20Sopenharmony_ci				}
10558c2ecf20Sopenharmony_ci				/* Hard error.  Abort writing this record. */
10568c2ecf20Sopenharmony_ci				if (!err || err == -ENOMEM)
10578c2ecf20Sopenharmony_ci					err = err2;
10588c2ecf20Sopenharmony_ci				bh->b_blocknr = -1;
10598c2ecf20Sopenharmony_ci				ntfs_error(vol->sb, "Cannot write ntfs record "
10608c2ecf20Sopenharmony_ci						"0x%llx (inode 0x%lx, "
10618c2ecf20Sopenharmony_ci						"attribute type 0x%x) because "
10628c2ecf20Sopenharmony_ci						"its location on disk could "
10638c2ecf20Sopenharmony_ci						"not be determined (error "
10648c2ecf20Sopenharmony_ci						"code %lli).",
10658c2ecf20Sopenharmony_ci						(long long)block <<
10668c2ecf20Sopenharmony_ci						bh_size_bits >>
10678c2ecf20Sopenharmony_ci						vol->mft_record_size_bits,
10688c2ecf20Sopenharmony_ci						ni->mft_no, ni->type,
10698c2ecf20Sopenharmony_ci						(long long)lcn);
10708c2ecf20Sopenharmony_ci				/*
10718c2ecf20Sopenharmony_ci				 * If this is not the first buffer, remove the
10728c2ecf20Sopenharmony_ci				 * buffers in this record from the list of
10738c2ecf20Sopenharmony_ci				 * buffers to write and clear their dirty bit
10748c2ecf20Sopenharmony_ci				 * if not error -ENOMEM.
10758c2ecf20Sopenharmony_ci				 */
10768c2ecf20Sopenharmony_ci				if (rec_start_bh != bh) {
10778c2ecf20Sopenharmony_ci					while (bhs[--nr_bhs] != rec_start_bh)
10788c2ecf20Sopenharmony_ci						;
10798c2ecf20Sopenharmony_ci					if (err2 != -ENOMEM) {
10808c2ecf20Sopenharmony_ci						do {
10818c2ecf20Sopenharmony_ci							clear_buffer_dirty(
10828c2ecf20Sopenharmony_ci								rec_start_bh);
10838c2ecf20Sopenharmony_ci						} while ((rec_start_bh =
10848c2ecf20Sopenharmony_ci								rec_start_bh->
10858c2ecf20Sopenharmony_ci								b_this_page) !=
10868c2ecf20Sopenharmony_ci								bh);
10878c2ecf20Sopenharmony_ci					}
10888c2ecf20Sopenharmony_ci				}
10898c2ecf20Sopenharmony_ci				continue;
10908c2ecf20Sopenharmony_ci			}
10918c2ecf20Sopenharmony_ci		}
10928c2ecf20Sopenharmony_ci		BUG_ON(!buffer_uptodate(bh));
10938c2ecf20Sopenharmony_ci		BUG_ON(nr_bhs >= max_bhs);
10948c2ecf20Sopenharmony_ci		bhs[nr_bhs++] = bh;
10958c2ecf20Sopenharmony_ci	} while (block++, (bh = bh->b_this_page) != head);
10968c2ecf20Sopenharmony_ci	if (unlikely(rl))
10978c2ecf20Sopenharmony_ci		up_read(&ni->runlist.lock);
10988c2ecf20Sopenharmony_ci	/* If there were no dirty buffers, we are done. */
10998c2ecf20Sopenharmony_ci	if (!nr_bhs)
11008c2ecf20Sopenharmony_ci		goto done;
11018c2ecf20Sopenharmony_ci	/* Map the page so we can access its contents. */
11028c2ecf20Sopenharmony_ci	kaddr = kmap(page);
11038c2ecf20Sopenharmony_ci	/* Clear the page uptodate flag whilst the mst fixups are applied. */
11048c2ecf20Sopenharmony_ci	BUG_ON(!PageUptodate(page));
11058c2ecf20Sopenharmony_ci	ClearPageUptodate(page);
11068c2ecf20Sopenharmony_ci	for (i = 0; i < nr_bhs; i++) {
11078c2ecf20Sopenharmony_ci		unsigned int ofs;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci		/* Skip buffers which are not at the beginning of records. */
11108c2ecf20Sopenharmony_ci		if (i % bhs_per_rec)
11118c2ecf20Sopenharmony_ci			continue;
11128c2ecf20Sopenharmony_ci		tbh = bhs[i];
11138c2ecf20Sopenharmony_ci		ofs = bh_offset(tbh);
11148c2ecf20Sopenharmony_ci		if (is_mft) {
11158c2ecf20Sopenharmony_ci			ntfs_inode *tni;
11168c2ecf20Sopenharmony_ci			unsigned long mft_no;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci			/* Get the mft record number. */
11198c2ecf20Sopenharmony_ci			mft_no = (((s64)page->index << PAGE_SHIFT) + ofs)
11208c2ecf20Sopenharmony_ci					>> rec_size_bits;
11218c2ecf20Sopenharmony_ci			/* Check whether to write this mft record. */
11228c2ecf20Sopenharmony_ci			tni = NULL;
11238c2ecf20Sopenharmony_ci			if (!ntfs_may_write_mft_record(vol, mft_no,
11248c2ecf20Sopenharmony_ci					(MFT_RECORD*)(kaddr + ofs), &tni)) {
11258c2ecf20Sopenharmony_ci				/*
11268c2ecf20Sopenharmony_ci				 * The record should not be written.  This
11278c2ecf20Sopenharmony_ci				 * means we need to redirty the page before
11288c2ecf20Sopenharmony_ci				 * returning.
11298c2ecf20Sopenharmony_ci				 */
11308c2ecf20Sopenharmony_ci				page_is_dirty = true;
11318c2ecf20Sopenharmony_ci				/*
11328c2ecf20Sopenharmony_ci				 * Remove the buffers in this mft record from
11338c2ecf20Sopenharmony_ci				 * the list of buffers to write.
11348c2ecf20Sopenharmony_ci				 */
11358c2ecf20Sopenharmony_ci				do {
11368c2ecf20Sopenharmony_ci					bhs[i] = NULL;
11378c2ecf20Sopenharmony_ci				} while (++i % bhs_per_rec);
11388c2ecf20Sopenharmony_ci				continue;
11398c2ecf20Sopenharmony_ci			}
11408c2ecf20Sopenharmony_ci			/*
11418c2ecf20Sopenharmony_ci			 * The record should be written.  If a locked ntfs
11428c2ecf20Sopenharmony_ci			 * inode was returned, add it to the array of locked
11438c2ecf20Sopenharmony_ci			 * ntfs inodes.
11448c2ecf20Sopenharmony_ci			 */
11458c2ecf20Sopenharmony_ci			if (tni)
11468c2ecf20Sopenharmony_ci				locked_nis[nr_locked_nis++] = tni;
11478c2ecf20Sopenharmony_ci		}
11488c2ecf20Sopenharmony_ci		/* Apply the mst protection fixups. */
11498c2ecf20Sopenharmony_ci		err2 = pre_write_mst_fixup((NTFS_RECORD*)(kaddr + ofs),
11508c2ecf20Sopenharmony_ci				rec_size);
11518c2ecf20Sopenharmony_ci		if (unlikely(err2)) {
11528c2ecf20Sopenharmony_ci			if (!err || err == -ENOMEM)
11538c2ecf20Sopenharmony_ci				err = -EIO;
11548c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Failed to apply mst fixups "
11558c2ecf20Sopenharmony_ci					"(inode 0x%lx, attribute type 0x%x, "
11568c2ecf20Sopenharmony_ci					"page index 0x%lx, page offset 0x%x)!"
11578c2ecf20Sopenharmony_ci					"  Unmount and run chkdsk.", vi->i_ino,
11588c2ecf20Sopenharmony_ci					ni->type, page->index, ofs);
11598c2ecf20Sopenharmony_ci			/*
11608c2ecf20Sopenharmony_ci			 * Mark all the buffers in this record clean as we do
11618c2ecf20Sopenharmony_ci			 * not want to write corrupt data to disk.
11628c2ecf20Sopenharmony_ci			 */
11638c2ecf20Sopenharmony_ci			do {
11648c2ecf20Sopenharmony_ci				clear_buffer_dirty(bhs[i]);
11658c2ecf20Sopenharmony_ci				bhs[i] = NULL;
11668c2ecf20Sopenharmony_ci			} while (++i % bhs_per_rec);
11678c2ecf20Sopenharmony_ci			continue;
11688c2ecf20Sopenharmony_ci		}
11698c2ecf20Sopenharmony_ci		nr_recs++;
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci	/* If no records are to be written out, we are done. */
11728c2ecf20Sopenharmony_ci	if (!nr_recs)
11738c2ecf20Sopenharmony_ci		goto unm_done;
11748c2ecf20Sopenharmony_ci	flush_dcache_page(page);
11758c2ecf20Sopenharmony_ci	/* Lock buffers and start synchronous write i/o on them. */
11768c2ecf20Sopenharmony_ci	for (i = 0; i < nr_bhs; i++) {
11778c2ecf20Sopenharmony_ci		tbh = bhs[i];
11788c2ecf20Sopenharmony_ci		if (!tbh)
11798c2ecf20Sopenharmony_ci			continue;
11808c2ecf20Sopenharmony_ci		if (!trylock_buffer(tbh))
11818c2ecf20Sopenharmony_ci			BUG();
11828c2ecf20Sopenharmony_ci		/* The buffer dirty state is now irrelevant, just clean it. */
11838c2ecf20Sopenharmony_ci		clear_buffer_dirty(tbh);
11848c2ecf20Sopenharmony_ci		BUG_ON(!buffer_uptodate(tbh));
11858c2ecf20Sopenharmony_ci		BUG_ON(!buffer_mapped(tbh));
11868c2ecf20Sopenharmony_ci		get_bh(tbh);
11878c2ecf20Sopenharmony_ci		tbh->b_end_io = end_buffer_write_sync;
11888c2ecf20Sopenharmony_ci		submit_bh(REQ_OP_WRITE, 0, tbh);
11898c2ecf20Sopenharmony_ci	}
11908c2ecf20Sopenharmony_ci	/* Synchronize the mft mirror now if not @sync. */
11918c2ecf20Sopenharmony_ci	if (is_mft && !sync)
11928c2ecf20Sopenharmony_ci		goto do_mirror;
11938c2ecf20Sopenharmony_cido_wait:
11948c2ecf20Sopenharmony_ci	/* Wait on i/o completion of buffers. */
11958c2ecf20Sopenharmony_ci	for (i = 0; i < nr_bhs; i++) {
11968c2ecf20Sopenharmony_ci		tbh = bhs[i];
11978c2ecf20Sopenharmony_ci		if (!tbh)
11988c2ecf20Sopenharmony_ci			continue;
11998c2ecf20Sopenharmony_ci		wait_on_buffer(tbh);
12008c2ecf20Sopenharmony_ci		if (unlikely(!buffer_uptodate(tbh))) {
12018c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "I/O error while writing ntfs "
12028c2ecf20Sopenharmony_ci					"record buffer (inode 0x%lx, "
12038c2ecf20Sopenharmony_ci					"attribute type 0x%x, page index "
12048c2ecf20Sopenharmony_ci					"0x%lx, page offset 0x%lx)!  Unmount "
12058c2ecf20Sopenharmony_ci					"and run chkdsk.", vi->i_ino, ni->type,
12068c2ecf20Sopenharmony_ci					page->index, bh_offset(tbh));
12078c2ecf20Sopenharmony_ci			if (!err || err == -ENOMEM)
12088c2ecf20Sopenharmony_ci				err = -EIO;
12098c2ecf20Sopenharmony_ci			/*
12108c2ecf20Sopenharmony_ci			 * Set the buffer uptodate so the page and buffer
12118c2ecf20Sopenharmony_ci			 * states do not become out of sync.
12128c2ecf20Sopenharmony_ci			 */
12138c2ecf20Sopenharmony_ci			set_buffer_uptodate(tbh);
12148c2ecf20Sopenharmony_ci		}
12158c2ecf20Sopenharmony_ci	}
12168c2ecf20Sopenharmony_ci	/* If @sync, now synchronize the mft mirror. */
12178c2ecf20Sopenharmony_ci	if (is_mft && sync) {
12188c2ecf20Sopenharmony_cido_mirror:
12198c2ecf20Sopenharmony_ci		for (i = 0; i < nr_bhs; i++) {
12208c2ecf20Sopenharmony_ci			unsigned long mft_no;
12218c2ecf20Sopenharmony_ci			unsigned int ofs;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci			/*
12248c2ecf20Sopenharmony_ci			 * Skip buffers which are not at the beginning of
12258c2ecf20Sopenharmony_ci			 * records.
12268c2ecf20Sopenharmony_ci			 */
12278c2ecf20Sopenharmony_ci			if (i % bhs_per_rec)
12288c2ecf20Sopenharmony_ci				continue;
12298c2ecf20Sopenharmony_ci			tbh = bhs[i];
12308c2ecf20Sopenharmony_ci			/* Skip removed buffers (and hence records). */
12318c2ecf20Sopenharmony_ci			if (!tbh)
12328c2ecf20Sopenharmony_ci				continue;
12338c2ecf20Sopenharmony_ci			ofs = bh_offset(tbh);
12348c2ecf20Sopenharmony_ci			/* Get the mft record number. */
12358c2ecf20Sopenharmony_ci			mft_no = (((s64)page->index << PAGE_SHIFT) + ofs)
12368c2ecf20Sopenharmony_ci					>> rec_size_bits;
12378c2ecf20Sopenharmony_ci			if (mft_no < vol->mftmirr_size)
12388c2ecf20Sopenharmony_ci				ntfs_sync_mft_mirror(vol, mft_no,
12398c2ecf20Sopenharmony_ci						(MFT_RECORD*)(kaddr + ofs),
12408c2ecf20Sopenharmony_ci						sync);
12418c2ecf20Sopenharmony_ci		}
12428c2ecf20Sopenharmony_ci		if (!sync)
12438c2ecf20Sopenharmony_ci			goto do_wait;
12448c2ecf20Sopenharmony_ci	}
12458c2ecf20Sopenharmony_ci	/* Remove the mst protection fixups again. */
12468c2ecf20Sopenharmony_ci	for (i = 0; i < nr_bhs; i++) {
12478c2ecf20Sopenharmony_ci		if (!(i % bhs_per_rec)) {
12488c2ecf20Sopenharmony_ci			tbh = bhs[i];
12498c2ecf20Sopenharmony_ci			if (!tbh)
12508c2ecf20Sopenharmony_ci				continue;
12518c2ecf20Sopenharmony_ci			post_write_mst_fixup((NTFS_RECORD*)(kaddr +
12528c2ecf20Sopenharmony_ci					bh_offset(tbh)));
12538c2ecf20Sopenharmony_ci		}
12548c2ecf20Sopenharmony_ci	}
12558c2ecf20Sopenharmony_ci	flush_dcache_page(page);
12568c2ecf20Sopenharmony_ciunm_done:
12578c2ecf20Sopenharmony_ci	/* Unlock any locked inodes. */
12588c2ecf20Sopenharmony_ci	while (nr_locked_nis-- > 0) {
12598c2ecf20Sopenharmony_ci		ntfs_inode *tni, *base_tni;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci		tni = locked_nis[nr_locked_nis];
12628c2ecf20Sopenharmony_ci		/* Get the base inode. */
12638c2ecf20Sopenharmony_ci		mutex_lock(&tni->extent_lock);
12648c2ecf20Sopenharmony_ci		if (tni->nr_extents >= 0)
12658c2ecf20Sopenharmony_ci			base_tni = tni;
12668c2ecf20Sopenharmony_ci		else {
12678c2ecf20Sopenharmony_ci			base_tni = tni->ext.base_ntfs_ino;
12688c2ecf20Sopenharmony_ci			BUG_ON(!base_tni);
12698c2ecf20Sopenharmony_ci		}
12708c2ecf20Sopenharmony_ci		mutex_unlock(&tni->extent_lock);
12718c2ecf20Sopenharmony_ci		ntfs_debug("Unlocking %s inode 0x%lx.",
12728c2ecf20Sopenharmony_ci				tni == base_tni ? "base" : "extent",
12738c2ecf20Sopenharmony_ci				tni->mft_no);
12748c2ecf20Sopenharmony_ci		mutex_unlock(&tni->mrec_lock);
12758c2ecf20Sopenharmony_ci		atomic_dec(&tni->count);
12768c2ecf20Sopenharmony_ci		iput(VFS_I(base_tni));
12778c2ecf20Sopenharmony_ci	}
12788c2ecf20Sopenharmony_ci	SetPageUptodate(page);
12798c2ecf20Sopenharmony_ci	kunmap(page);
12808c2ecf20Sopenharmony_cidone:
12818c2ecf20Sopenharmony_ci	if (unlikely(err && err != -ENOMEM)) {
12828c2ecf20Sopenharmony_ci		/*
12838c2ecf20Sopenharmony_ci		 * Set page error if there is only one ntfs record in the page.
12848c2ecf20Sopenharmony_ci		 * Otherwise we would loose per-record granularity.
12858c2ecf20Sopenharmony_ci		 */
12868c2ecf20Sopenharmony_ci		if (ni->itype.index.block_size == PAGE_SIZE)
12878c2ecf20Sopenharmony_ci			SetPageError(page);
12888c2ecf20Sopenharmony_ci		NVolSetErrors(vol);
12898c2ecf20Sopenharmony_ci	}
12908c2ecf20Sopenharmony_ci	if (page_is_dirty) {
12918c2ecf20Sopenharmony_ci		ntfs_debug("Page still contains one or more dirty ntfs "
12928c2ecf20Sopenharmony_ci				"records.  Redirtying the page starting at "
12938c2ecf20Sopenharmony_ci				"record 0x%lx.", page->index <<
12948c2ecf20Sopenharmony_ci				(PAGE_SHIFT - rec_size_bits));
12958c2ecf20Sopenharmony_ci		redirty_page_for_writepage(wbc, page);
12968c2ecf20Sopenharmony_ci		unlock_page(page);
12978c2ecf20Sopenharmony_ci	} else {
12988c2ecf20Sopenharmony_ci		/*
12998c2ecf20Sopenharmony_ci		 * Keep the VM happy.  This must be done otherwise the
13008c2ecf20Sopenharmony_ci		 * radix-tree tag PAGECACHE_TAG_DIRTY remains set even though
13018c2ecf20Sopenharmony_ci		 * the page is clean.
13028c2ecf20Sopenharmony_ci		 */
13038c2ecf20Sopenharmony_ci		BUG_ON(PageWriteback(page));
13048c2ecf20Sopenharmony_ci		set_page_writeback(page);
13058c2ecf20Sopenharmony_ci		unlock_page(page);
13068c2ecf20Sopenharmony_ci		end_page_writeback(page);
13078c2ecf20Sopenharmony_ci	}
13088c2ecf20Sopenharmony_ci	if (likely(!err))
13098c2ecf20Sopenharmony_ci		ntfs_debug("Done.");
13108c2ecf20Sopenharmony_ci	return err;
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/**
13148c2ecf20Sopenharmony_ci * ntfs_writepage - write a @page to the backing store
13158c2ecf20Sopenharmony_ci * @page:	page cache page to write out
13168c2ecf20Sopenharmony_ci * @wbc:	writeback control structure
13178c2ecf20Sopenharmony_ci *
13188c2ecf20Sopenharmony_ci * This is called from the VM when it wants to have a dirty ntfs page cache
13198c2ecf20Sopenharmony_ci * page cleaned.  The VM has already locked the page and marked it clean.
13208c2ecf20Sopenharmony_ci *
13218c2ecf20Sopenharmony_ci * For non-resident attributes, ntfs_writepage() writes the @page by calling
13228c2ecf20Sopenharmony_ci * the ntfs version of the generic block_write_full_page() function,
13238c2ecf20Sopenharmony_ci * ntfs_write_block(), which in turn if necessary creates and writes the
13248c2ecf20Sopenharmony_ci * buffers associated with the page asynchronously.
13258c2ecf20Sopenharmony_ci *
13268c2ecf20Sopenharmony_ci * For resident attributes, OTOH, ntfs_writepage() writes the @page by copying
13278c2ecf20Sopenharmony_ci * the data to the mft record (which at this stage is most likely in memory).
13288c2ecf20Sopenharmony_ci * The mft record is then marked dirty and written out asynchronously via the
13298c2ecf20Sopenharmony_ci * vfs inode dirty code path for the inode the mft record belongs to or via the
13308c2ecf20Sopenharmony_ci * vm page dirty code path for the page the mft record is in.
13318c2ecf20Sopenharmony_ci *
13328c2ecf20Sopenharmony_ci * Based on ntfs_readpage() and fs/buffer.c::block_write_full_page().
13338c2ecf20Sopenharmony_ci *
13348c2ecf20Sopenharmony_ci * Return 0 on success and -errno on error.
13358c2ecf20Sopenharmony_ci */
13368c2ecf20Sopenharmony_cistatic int ntfs_writepage(struct page *page, struct writeback_control *wbc)
13378c2ecf20Sopenharmony_ci{
13388c2ecf20Sopenharmony_ci	loff_t i_size;
13398c2ecf20Sopenharmony_ci	struct inode *vi = page->mapping->host;
13408c2ecf20Sopenharmony_ci	ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi);
13418c2ecf20Sopenharmony_ci	char *addr;
13428c2ecf20Sopenharmony_ci	ntfs_attr_search_ctx *ctx = NULL;
13438c2ecf20Sopenharmony_ci	MFT_RECORD *m = NULL;
13448c2ecf20Sopenharmony_ci	u32 attr_len;
13458c2ecf20Sopenharmony_ci	int err;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ciretry_writepage:
13488c2ecf20Sopenharmony_ci	BUG_ON(!PageLocked(page));
13498c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
13508c2ecf20Sopenharmony_ci	/* Is the page fully outside i_size? (truncate in progress) */
13518c2ecf20Sopenharmony_ci	if (unlikely(page->index >= (i_size + PAGE_SIZE - 1) >>
13528c2ecf20Sopenharmony_ci			PAGE_SHIFT)) {
13538c2ecf20Sopenharmony_ci		/*
13548c2ecf20Sopenharmony_ci		 * The page may have dirty, unmapped buffers.  Make them
13558c2ecf20Sopenharmony_ci		 * freeable here, so the page does not leak.
13568c2ecf20Sopenharmony_ci		 */
13578c2ecf20Sopenharmony_ci		block_invalidatepage(page, 0, PAGE_SIZE);
13588c2ecf20Sopenharmony_ci		unlock_page(page);
13598c2ecf20Sopenharmony_ci		ntfs_debug("Write outside i_size - truncated?");
13608c2ecf20Sopenharmony_ci		return 0;
13618c2ecf20Sopenharmony_ci	}
13628c2ecf20Sopenharmony_ci	/*
13638c2ecf20Sopenharmony_ci	 * Only $DATA attributes can be encrypted and only unnamed $DATA
13648c2ecf20Sopenharmony_ci	 * attributes can be compressed.  Index root can have the flags set but
13658c2ecf20Sopenharmony_ci	 * this means to create compressed/encrypted files, not that the
13668c2ecf20Sopenharmony_ci	 * attribute is compressed/encrypted.  Note we need to check for
13678c2ecf20Sopenharmony_ci	 * AT_INDEX_ALLOCATION since this is the type of both directory and
13688c2ecf20Sopenharmony_ci	 * index inodes.
13698c2ecf20Sopenharmony_ci	 */
13708c2ecf20Sopenharmony_ci	if (ni->type != AT_INDEX_ALLOCATION) {
13718c2ecf20Sopenharmony_ci		/* If file is encrypted, deny access, just like NT4. */
13728c2ecf20Sopenharmony_ci		if (NInoEncrypted(ni)) {
13738c2ecf20Sopenharmony_ci			unlock_page(page);
13748c2ecf20Sopenharmony_ci			BUG_ON(ni->type != AT_DATA);
13758c2ecf20Sopenharmony_ci			ntfs_debug("Denying write access to encrypted file.");
13768c2ecf20Sopenharmony_ci			return -EACCES;
13778c2ecf20Sopenharmony_ci		}
13788c2ecf20Sopenharmony_ci		/* Compressed data streams are handled in compress.c. */
13798c2ecf20Sopenharmony_ci		if (NInoNonResident(ni) && NInoCompressed(ni)) {
13808c2ecf20Sopenharmony_ci			BUG_ON(ni->type != AT_DATA);
13818c2ecf20Sopenharmony_ci			BUG_ON(ni->name_len);
13828c2ecf20Sopenharmony_ci			// TODO: Implement and replace this with
13838c2ecf20Sopenharmony_ci			// return ntfs_write_compressed_block(page);
13848c2ecf20Sopenharmony_ci			unlock_page(page);
13858c2ecf20Sopenharmony_ci			ntfs_error(vi->i_sb, "Writing to compressed files is "
13868c2ecf20Sopenharmony_ci					"not supported yet.  Sorry.");
13878c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
13888c2ecf20Sopenharmony_ci		}
13898c2ecf20Sopenharmony_ci		// TODO: Implement and remove this check.
13908c2ecf20Sopenharmony_ci		if (NInoNonResident(ni) && NInoSparse(ni)) {
13918c2ecf20Sopenharmony_ci			unlock_page(page);
13928c2ecf20Sopenharmony_ci			ntfs_error(vi->i_sb, "Writing to sparse files is not "
13938c2ecf20Sopenharmony_ci					"supported yet.  Sorry.");
13948c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
13958c2ecf20Sopenharmony_ci		}
13968c2ecf20Sopenharmony_ci	}
13978c2ecf20Sopenharmony_ci	/* NInoNonResident() == NInoIndexAllocPresent() */
13988c2ecf20Sopenharmony_ci	if (NInoNonResident(ni)) {
13998c2ecf20Sopenharmony_ci		/* We have to zero every time due to mmap-at-end-of-file. */
14008c2ecf20Sopenharmony_ci		if (page->index >= (i_size >> PAGE_SHIFT)) {
14018c2ecf20Sopenharmony_ci			/* The page straddles i_size. */
14028c2ecf20Sopenharmony_ci			unsigned int ofs = i_size & ~PAGE_MASK;
14038c2ecf20Sopenharmony_ci			zero_user_segment(page, ofs, PAGE_SIZE);
14048c2ecf20Sopenharmony_ci		}
14058c2ecf20Sopenharmony_ci		/* Handle mst protected attributes. */
14068c2ecf20Sopenharmony_ci		if (NInoMstProtected(ni))
14078c2ecf20Sopenharmony_ci			return ntfs_write_mst_block(page, wbc);
14088c2ecf20Sopenharmony_ci		/* Normal, non-resident data stream. */
14098c2ecf20Sopenharmony_ci		return ntfs_write_block(page, wbc);
14108c2ecf20Sopenharmony_ci	}
14118c2ecf20Sopenharmony_ci	/*
14128c2ecf20Sopenharmony_ci	 * Attribute is resident, implying it is not compressed, encrypted, or
14138c2ecf20Sopenharmony_ci	 * mst protected.  This also means the attribute is smaller than an mft
14148c2ecf20Sopenharmony_ci	 * record and hence smaller than a page, so can simply return error on
14158c2ecf20Sopenharmony_ci	 * any pages with index above 0.  Note the attribute can actually be
14168c2ecf20Sopenharmony_ci	 * marked compressed but if it is resident the actual data is not
14178c2ecf20Sopenharmony_ci	 * compressed so we are ok to ignore the compressed flag here.
14188c2ecf20Sopenharmony_ci	 */
14198c2ecf20Sopenharmony_ci	BUG_ON(page_has_buffers(page));
14208c2ecf20Sopenharmony_ci	BUG_ON(!PageUptodate(page));
14218c2ecf20Sopenharmony_ci	if (unlikely(page->index > 0)) {
14228c2ecf20Sopenharmony_ci		ntfs_error(vi->i_sb, "BUG()! page->index (0x%lx) > 0.  "
14238c2ecf20Sopenharmony_ci				"Aborting write.", page->index);
14248c2ecf20Sopenharmony_ci		BUG_ON(PageWriteback(page));
14258c2ecf20Sopenharmony_ci		set_page_writeback(page);
14268c2ecf20Sopenharmony_ci		unlock_page(page);
14278c2ecf20Sopenharmony_ci		end_page_writeback(page);
14288c2ecf20Sopenharmony_ci		return -EIO;
14298c2ecf20Sopenharmony_ci	}
14308c2ecf20Sopenharmony_ci	if (!NInoAttr(ni))
14318c2ecf20Sopenharmony_ci		base_ni = ni;
14328c2ecf20Sopenharmony_ci	else
14338c2ecf20Sopenharmony_ci		base_ni = ni->ext.base_ntfs_ino;
14348c2ecf20Sopenharmony_ci	/* Map, pin, and lock the mft record. */
14358c2ecf20Sopenharmony_ci	m = map_mft_record(base_ni);
14368c2ecf20Sopenharmony_ci	if (IS_ERR(m)) {
14378c2ecf20Sopenharmony_ci		err = PTR_ERR(m);
14388c2ecf20Sopenharmony_ci		m = NULL;
14398c2ecf20Sopenharmony_ci		ctx = NULL;
14408c2ecf20Sopenharmony_ci		goto err_out;
14418c2ecf20Sopenharmony_ci	}
14428c2ecf20Sopenharmony_ci	/*
14438c2ecf20Sopenharmony_ci	 * If a parallel write made the attribute non-resident, drop the mft
14448c2ecf20Sopenharmony_ci	 * record and retry the writepage.
14458c2ecf20Sopenharmony_ci	 */
14468c2ecf20Sopenharmony_ci	if (unlikely(NInoNonResident(ni))) {
14478c2ecf20Sopenharmony_ci		unmap_mft_record(base_ni);
14488c2ecf20Sopenharmony_ci		goto retry_writepage;
14498c2ecf20Sopenharmony_ci	}
14508c2ecf20Sopenharmony_ci	ctx = ntfs_attr_get_search_ctx(base_ni, m);
14518c2ecf20Sopenharmony_ci	if (unlikely(!ctx)) {
14528c2ecf20Sopenharmony_ci		err = -ENOMEM;
14538c2ecf20Sopenharmony_ci		goto err_out;
14548c2ecf20Sopenharmony_ci	}
14558c2ecf20Sopenharmony_ci	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
14568c2ecf20Sopenharmony_ci			CASE_SENSITIVE, 0, NULL, 0, ctx);
14578c2ecf20Sopenharmony_ci	if (unlikely(err))
14588c2ecf20Sopenharmony_ci		goto err_out;
14598c2ecf20Sopenharmony_ci	/*
14608c2ecf20Sopenharmony_ci	 * Keep the VM happy.  This must be done otherwise the radix-tree tag
14618c2ecf20Sopenharmony_ci	 * PAGECACHE_TAG_DIRTY remains set even though the page is clean.
14628c2ecf20Sopenharmony_ci	 */
14638c2ecf20Sopenharmony_ci	BUG_ON(PageWriteback(page));
14648c2ecf20Sopenharmony_ci	set_page_writeback(page);
14658c2ecf20Sopenharmony_ci	unlock_page(page);
14668c2ecf20Sopenharmony_ci	attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
14678c2ecf20Sopenharmony_ci	i_size = i_size_read(vi);
14688c2ecf20Sopenharmony_ci	if (unlikely(attr_len > i_size)) {
14698c2ecf20Sopenharmony_ci		/* Race with shrinking truncate or a failed truncate. */
14708c2ecf20Sopenharmony_ci		attr_len = i_size;
14718c2ecf20Sopenharmony_ci		/*
14728c2ecf20Sopenharmony_ci		 * If the truncate failed, fix it up now.  If a concurrent
14738c2ecf20Sopenharmony_ci		 * truncate, we do its job, so it does not have to do anything.
14748c2ecf20Sopenharmony_ci		 */
14758c2ecf20Sopenharmony_ci		err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
14768c2ecf20Sopenharmony_ci				attr_len);
14778c2ecf20Sopenharmony_ci		/* Shrinking cannot fail. */
14788c2ecf20Sopenharmony_ci		BUG_ON(err);
14798c2ecf20Sopenharmony_ci	}
14808c2ecf20Sopenharmony_ci	addr = kmap_atomic(page);
14818c2ecf20Sopenharmony_ci	/* Copy the data from the page to the mft record. */
14828c2ecf20Sopenharmony_ci	memcpy((u8*)ctx->attr +
14838c2ecf20Sopenharmony_ci			le16_to_cpu(ctx->attr->data.resident.value_offset),
14848c2ecf20Sopenharmony_ci			addr, attr_len);
14858c2ecf20Sopenharmony_ci	/* Zero out of bounds area in the page cache page. */
14868c2ecf20Sopenharmony_ci	memset(addr + attr_len, 0, PAGE_SIZE - attr_len);
14878c2ecf20Sopenharmony_ci	kunmap_atomic(addr);
14888c2ecf20Sopenharmony_ci	flush_dcache_page(page);
14898c2ecf20Sopenharmony_ci	flush_dcache_mft_record_page(ctx->ntfs_ino);
14908c2ecf20Sopenharmony_ci	/* We are done with the page. */
14918c2ecf20Sopenharmony_ci	end_page_writeback(page);
14928c2ecf20Sopenharmony_ci	/* Finally, mark the mft record dirty, so it gets written back. */
14938c2ecf20Sopenharmony_ci	mark_mft_record_dirty(ctx->ntfs_ino);
14948c2ecf20Sopenharmony_ci	ntfs_attr_put_search_ctx(ctx);
14958c2ecf20Sopenharmony_ci	unmap_mft_record(base_ni);
14968c2ecf20Sopenharmony_ci	return 0;
14978c2ecf20Sopenharmony_cierr_out:
14988c2ecf20Sopenharmony_ci	if (err == -ENOMEM) {
14998c2ecf20Sopenharmony_ci		ntfs_warning(vi->i_sb, "Error allocating memory. Redirtying "
15008c2ecf20Sopenharmony_ci				"page so we try again later.");
15018c2ecf20Sopenharmony_ci		/*
15028c2ecf20Sopenharmony_ci		 * Put the page back on mapping->dirty_pages, but leave its
15038c2ecf20Sopenharmony_ci		 * buffers' dirty state as-is.
15048c2ecf20Sopenharmony_ci		 */
15058c2ecf20Sopenharmony_ci		redirty_page_for_writepage(wbc, page);
15068c2ecf20Sopenharmony_ci		err = 0;
15078c2ecf20Sopenharmony_ci	} else {
15088c2ecf20Sopenharmony_ci		ntfs_error(vi->i_sb, "Resident attribute write failed with "
15098c2ecf20Sopenharmony_ci				"error %i.", err);
15108c2ecf20Sopenharmony_ci		SetPageError(page);
15118c2ecf20Sopenharmony_ci		NVolSetErrors(ni->vol);
15128c2ecf20Sopenharmony_ci	}
15138c2ecf20Sopenharmony_ci	unlock_page(page);
15148c2ecf20Sopenharmony_ci	if (ctx)
15158c2ecf20Sopenharmony_ci		ntfs_attr_put_search_ctx(ctx);
15168c2ecf20Sopenharmony_ci	if (m)
15178c2ecf20Sopenharmony_ci		unmap_mft_record(base_ni);
15188c2ecf20Sopenharmony_ci	return err;
15198c2ecf20Sopenharmony_ci}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci#endif	/* NTFS_RW */
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci/**
15248c2ecf20Sopenharmony_ci * ntfs_bmap - map logical file block to physical device block
15258c2ecf20Sopenharmony_ci * @mapping:	address space mapping to which the block to be mapped belongs
15268c2ecf20Sopenharmony_ci * @block:	logical block to map to its physical device block
15278c2ecf20Sopenharmony_ci *
15288c2ecf20Sopenharmony_ci * For regular, non-resident files (i.e. not compressed and not encrypted), map
15298c2ecf20Sopenharmony_ci * the logical @block belonging to the file described by the address space
15308c2ecf20Sopenharmony_ci * mapping @mapping to its physical device block.
15318c2ecf20Sopenharmony_ci *
15328c2ecf20Sopenharmony_ci * The size of the block is equal to the @s_blocksize field of the super block
15338c2ecf20Sopenharmony_ci * of the mounted file system which is guaranteed to be smaller than or equal
15348c2ecf20Sopenharmony_ci * to the cluster size thus the block is guaranteed to fit entirely inside the
15358c2ecf20Sopenharmony_ci * cluster which means we do not need to care how many contiguous bytes are
15368c2ecf20Sopenharmony_ci * available after the beginning of the block.
15378c2ecf20Sopenharmony_ci *
15388c2ecf20Sopenharmony_ci * Return the physical device block if the mapping succeeded or 0 if the block
15398c2ecf20Sopenharmony_ci * is sparse or there was an error.
15408c2ecf20Sopenharmony_ci *
15418c2ecf20Sopenharmony_ci * Note: This is a problem if someone tries to run bmap() on $Boot system file
15428c2ecf20Sopenharmony_ci * as that really is in block zero but there is nothing we can do.  bmap() is
15438c2ecf20Sopenharmony_ci * just broken in that respect (just like it cannot distinguish sparse from
15448c2ecf20Sopenharmony_ci * not available or error).
15458c2ecf20Sopenharmony_ci */
15468c2ecf20Sopenharmony_cistatic sector_t ntfs_bmap(struct address_space *mapping, sector_t block)
15478c2ecf20Sopenharmony_ci{
15488c2ecf20Sopenharmony_ci	s64 ofs, size;
15498c2ecf20Sopenharmony_ci	loff_t i_size;
15508c2ecf20Sopenharmony_ci	LCN lcn;
15518c2ecf20Sopenharmony_ci	unsigned long blocksize, flags;
15528c2ecf20Sopenharmony_ci	ntfs_inode *ni = NTFS_I(mapping->host);
15538c2ecf20Sopenharmony_ci	ntfs_volume *vol = ni->vol;
15548c2ecf20Sopenharmony_ci	unsigned delta;
15558c2ecf20Sopenharmony_ci	unsigned char blocksize_bits, cluster_size_shift;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	ntfs_debug("Entering for mft_no 0x%lx, logical block 0x%llx.",
15588c2ecf20Sopenharmony_ci			ni->mft_no, (unsigned long long)block);
15598c2ecf20Sopenharmony_ci	if (ni->type != AT_DATA || !NInoNonResident(ni) || NInoEncrypted(ni)) {
15608c2ecf20Sopenharmony_ci		ntfs_error(vol->sb, "BMAP does not make sense for %s "
15618c2ecf20Sopenharmony_ci				"attributes, returning 0.",
15628c2ecf20Sopenharmony_ci				(ni->type != AT_DATA) ? "non-data" :
15638c2ecf20Sopenharmony_ci				(!NInoNonResident(ni) ? "resident" :
15648c2ecf20Sopenharmony_ci				"encrypted"));
15658c2ecf20Sopenharmony_ci		return 0;
15668c2ecf20Sopenharmony_ci	}
15678c2ecf20Sopenharmony_ci	/* None of these can happen. */
15688c2ecf20Sopenharmony_ci	BUG_ON(NInoCompressed(ni));
15698c2ecf20Sopenharmony_ci	BUG_ON(NInoMstProtected(ni));
15708c2ecf20Sopenharmony_ci	blocksize = vol->sb->s_blocksize;
15718c2ecf20Sopenharmony_ci	blocksize_bits = vol->sb->s_blocksize_bits;
15728c2ecf20Sopenharmony_ci	ofs = (s64)block << blocksize_bits;
15738c2ecf20Sopenharmony_ci	read_lock_irqsave(&ni->size_lock, flags);
15748c2ecf20Sopenharmony_ci	size = ni->initialized_size;
15758c2ecf20Sopenharmony_ci	i_size = i_size_read(VFS_I(ni));
15768c2ecf20Sopenharmony_ci	read_unlock_irqrestore(&ni->size_lock, flags);
15778c2ecf20Sopenharmony_ci	/*
15788c2ecf20Sopenharmony_ci	 * If the offset is outside the initialized size or the block straddles
15798c2ecf20Sopenharmony_ci	 * the initialized size then pretend it is a hole unless the
15808c2ecf20Sopenharmony_ci	 * initialized size equals the file size.
15818c2ecf20Sopenharmony_ci	 */
15828c2ecf20Sopenharmony_ci	if (unlikely(ofs >= size || (ofs + blocksize > size && size < i_size)))
15838c2ecf20Sopenharmony_ci		goto hole;
15848c2ecf20Sopenharmony_ci	cluster_size_shift = vol->cluster_size_bits;
15858c2ecf20Sopenharmony_ci	down_read(&ni->runlist.lock);
15868c2ecf20Sopenharmony_ci	lcn = ntfs_attr_vcn_to_lcn_nolock(ni, ofs >> cluster_size_shift, false);
15878c2ecf20Sopenharmony_ci	up_read(&ni->runlist.lock);
15888c2ecf20Sopenharmony_ci	if (unlikely(lcn < LCN_HOLE)) {
15898c2ecf20Sopenharmony_ci		/*
15908c2ecf20Sopenharmony_ci		 * Step down to an integer to avoid gcc doing a long long
15918c2ecf20Sopenharmony_ci		 * comparision in the switch when we know @lcn is between
15928c2ecf20Sopenharmony_ci		 * LCN_HOLE and LCN_EIO (i.e. -1 to -5).
15938c2ecf20Sopenharmony_ci		 *
15948c2ecf20Sopenharmony_ci		 * Otherwise older gcc (at least on some architectures) will
15958c2ecf20Sopenharmony_ci		 * try to use __cmpdi2() which is of course not available in
15968c2ecf20Sopenharmony_ci		 * the kernel.
15978c2ecf20Sopenharmony_ci		 */
15988c2ecf20Sopenharmony_ci		switch ((int)lcn) {
15998c2ecf20Sopenharmony_ci		case LCN_ENOENT:
16008c2ecf20Sopenharmony_ci			/*
16018c2ecf20Sopenharmony_ci			 * If the offset is out of bounds then pretend it is a
16028c2ecf20Sopenharmony_ci			 * hole.
16038c2ecf20Sopenharmony_ci			 */
16048c2ecf20Sopenharmony_ci			goto hole;
16058c2ecf20Sopenharmony_ci		case LCN_ENOMEM:
16068c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Not enough memory to complete "
16078c2ecf20Sopenharmony_ci					"mapping for inode 0x%lx.  "
16088c2ecf20Sopenharmony_ci					"Returning 0.", ni->mft_no);
16098c2ecf20Sopenharmony_ci			break;
16108c2ecf20Sopenharmony_ci		default:
16118c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Failed to complete mapping for "
16128c2ecf20Sopenharmony_ci					"inode 0x%lx.  Run chkdsk.  "
16138c2ecf20Sopenharmony_ci					"Returning 0.", ni->mft_no);
16148c2ecf20Sopenharmony_ci			break;
16158c2ecf20Sopenharmony_ci		}
16168c2ecf20Sopenharmony_ci		return 0;
16178c2ecf20Sopenharmony_ci	}
16188c2ecf20Sopenharmony_ci	if (lcn < 0) {
16198c2ecf20Sopenharmony_ci		/* It is a hole. */
16208c2ecf20Sopenharmony_cihole:
16218c2ecf20Sopenharmony_ci		ntfs_debug("Done (returning hole).");
16228c2ecf20Sopenharmony_ci		return 0;
16238c2ecf20Sopenharmony_ci	}
16248c2ecf20Sopenharmony_ci	/*
16258c2ecf20Sopenharmony_ci	 * The block is really allocated and fullfils all our criteria.
16268c2ecf20Sopenharmony_ci	 * Convert the cluster to units of block size and return the result.
16278c2ecf20Sopenharmony_ci	 */
16288c2ecf20Sopenharmony_ci	delta = ofs & vol->cluster_size_mask;
16298c2ecf20Sopenharmony_ci	if (unlikely(sizeof(block) < sizeof(lcn))) {
16308c2ecf20Sopenharmony_ci		block = lcn = ((lcn << cluster_size_shift) + delta) >>
16318c2ecf20Sopenharmony_ci				blocksize_bits;
16328c2ecf20Sopenharmony_ci		/* If the block number was truncated return 0. */
16338c2ecf20Sopenharmony_ci		if (unlikely(block != lcn)) {
16348c2ecf20Sopenharmony_ci			ntfs_error(vol->sb, "Physical block 0x%llx is too "
16358c2ecf20Sopenharmony_ci					"large to be returned, returning 0.",
16368c2ecf20Sopenharmony_ci					(long long)lcn);
16378c2ecf20Sopenharmony_ci			return 0;
16388c2ecf20Sopenharmony_ci		}
16398c2ecf20Sopenharmony_ci	} else
16408c2ecf20Sopenharmony_ci		block = ((lcn << cluster_size_shift) + delta) >>
16418c2ecf20Sopenharmony_ci				blocksize_bits;
16428c2ecf20Sopenharmony_ci	ntfs_debug("Done (returning block 0x%llx).", (unsigned long long)lcn);
16438c2ecf20Sopenharmony_ci	return block;
16448c2ecf20Sopenharmony_ci}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci/**
16478c2ecf20Sopenharmony_ci * ntfs_normal_aops - address space operations for normal inodes and attributes
16488c2ecf20Sopenharmony_ci *
16498c2ecf20Sopenharmony_ci * Note these are not used for compressed or mst protected inodes and
16508c2ecf20Sopenharmony_ci * attributes.
16518c2ecf20Sopenharmony_ci */
16528c2ecf20Sopenharmony_ciconst struct address_space_operations ntfs_normal_aops = {
16538c2ecf20Sopenharmony_ci	.readpage	= ntfs_readpage,
16548c2ecf20Sopenharmony_ci#ifdef NTFS_RW
16558c2ecf20Sopenharmony_ci	.writepage	= ntfs_writepage,
16568c2ecf20Sopenharmony_ci	.set_page_dirty	= __set_page_dirty_buffers,
16578c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
16588c2ecf20Sopenharmony_ci	.bmap		= ntfs_bmap,
16598c2ecf20Sopenharmony_ci	.migratepage	= buffer_migrate_page,
16608c2ecf20Sopenharmony_ci	.is_partially_uptodate = block_is_partially_uptodate,
16618c2ecf20Sopenharmony_ci	.error_remove_page = generic_error_remove_page,
16628c2ecf20Sopenharmony_ci};
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci/**
16658c2ecf20Sopenharmony_ci * ntfs_compressed_aops - address space operations for compressed inodes
16668c2ecf20Sopenharmony_ci */
16678c2ecf20Sopenharmony_ciconst struct address_space_operations ntfs_compressed_aops = {
16688c2ecf20Sopenharmony_ci	.readpage	= ntfs_readpage,
16698c2ecf20Sopenharmony_ci#ifdef NTFS_RW
16708c2ecf20Sopenharmony_ci	.writepage	= ntfs_writepage,
16718c2ecf20Sopenharmony_ci	.set_page_dirty	= __set_page_dirty_buffers,
16728c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
16738c2ecf20Sopenharmony_ci	.migratepage	= buffer_migrate_page,
16748c2ecf20Sopenharmony_ci	.is_partially_uptodate = block_is_partially_uptodate,
16758c2ecf20Sopenharmony_ci	.error_remove_page = generic_error_remove_page,
16768c2ecf20Sopenharmony_ci};
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci/**
16798c2ecf20Sopenharmony_ci * ntfs_mst_aops - general address space operations for mst protecteed inodes
16808c2ecf20Sopenharmony_ci *		   and attributes
16818c2ecf20Sopenharmony_ci */
16828c2ecf20Sopenharmony_ciconst struct address_space_operations ntfs_mst_aops = {
16838c2ecf20Sopenharmony_ci	.readpage	= ntfs_readpage,	/* Fill page with data. */
16848c2ecf20Sopenharmony_ci#ifdef NTFS_RW
16858c2ecf20Sopenharmony_ci	.writepage	= ntfs_writepage,	/* Write dirty page to disk. */
16868c2ecf20Sopenharmony_ci	.set_page_dirty	= __set_page_dirty_nobuffers,	/* Set the page dirty
16878c2ecf20Sopenharmony_ci						   without touching the buffers
16888c2ecf20Sopenharmony_ci						   belonging to the page. */
16898c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
16908c2ecf20Sopenharmony_ci	.migratepage	= buffer_migrate_page,
16918c2ecf20Sopenharmony_ci	.is_partially_uptodate	= block_is_partially_uptodate,
16928c2ecf20Sopenharmony_ci	.error_remove_page = generic_error_remove_page,
16938c2ecf20Sopenharmony_ci};
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci#ifdef NTFS_RW
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci/**
16988c2ecf20Sopenharmony_ci * mark_ntfs_record_dirty - mark an ntfs record dirty
16998c2ecf20Sopenharmony_ci * @page:	page containing the ntfs record to mark dirty
17008c2ecf20Sopenharmony_ci * @ofs:	byte offset within @page at which the ntfs record begins
17018c2ecf20Sopenharmony_ci *
17028c2ecf20Sopenharmony_ci * Set the buffers and the page in which the ntfs record is located dirty.
17038c2ecf20Sopenharmony_ci *
17048c2ecf20Sopenharmony_ci * The latter also marks the vfs inode the ntfs record belongs to dirty
17058c2ecf20Sopenharmony_ci * (I_DIRTY_PAGES only).
17068c2ecf20Sopenharmony_ci *
17078c2ecf20Sopenharmony_ci * If the page does not have buffers, we create them and set them uptodate.
17088c2ecf20Sopenharmony_ci * The page may not be locked which is why we need to handle the buffers under
17098c2ecf20Sopenharmony_ci * the mapping->private_lock.  Once the buffers are marked dirty we no longer
17108c2ecf20Sopenharmony_ci * need the lock since try_to_free_buffers() does not free dirty buffers.
17118c2ecf20Sopenharmony_ci */
17128c2ecf20Sopenharmony_civoid mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) {
17138c2ecf20Sopenharmony_ci	struct address_space *mapping = page->mapping;
17148c2ecf20Sopenharmony_ci	ntfs_inode *ni = NTFS_I(mapping->host);
17158c2ecf20Sopenharmony_ci	struct buffer_head *bh, *head, *buffers_to_free = NULL;
17168c2ecf20Sopenharmony_ci	unsigned int end, bh_size, bh_ofs;
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	BUG_ON(!PageUptodate(page));
17198c2ecf20Sopenharmony_ci	end = ofs + ni->itype.index.block_size;
17208c2ecf20Sopenharmony_ci	bh_size = VFS_I(ni)->i_sb->s_blocksize;
17218c2ecf20Sopenharmony_ci	spin_lock(&mapping->private_lock);
17228c2ecf20Sopenharmony_ci	if (unlikely(!page_has_buffers(page))) {
17238c2ecf20Sopenharmony_ci		spin_unlock(&mapping->private_lock);
17248c2ecf20Sopenharmony_ci		bh = head = alloc_page_buffers(page, bh_size, true);
17258c2ecf20Sopenharmony_ci		spin_lock(&mapping->private_lock);
17268c2ecf20Sopenharmony_ci		if (likely(!page_has_buffers(page))) {
17278c2ecf20Sopenharmony_ci			struct buffer_head *tail;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci			do {
17308c2ecf20Sopenharmony_ci				set_buffer_uptodate(bh);
17318c2ecf20Sopenharmony_ci				tail = bh;
17328c2ecf20Sopenharmony_ci				bh = bh->b_this_page;
17338c2ecf20Sopenharmony_ci			} while (bh);
17348c2ecf20Sopenharmony_ci			tail->b_this_page = head;
17358c2ecf20Sopenharmony_ci			attach_page_private(page, head);
17368c2ecf20Sopenharmony_ci		} else
17378c2ecf20Sopenharmony_ci			buffers_to_free = bh;
17388c2ecf20Sopenharmony_ci	}
17398c2ecf20Sopenharmony_ci	bh = head = page_buffers(page);
17408c2ecf20Sopenharmony_ci	BUG_ON(!bh);
17418c2ecf20Sopenharmony_ci	do {
17428c2ecf20Sopenharmony_ci		bh_ofs = bh_offset(bh);
17438c2ecf20Sopenharmony_ci		if (bh_ofs + bh_size <= ofs)
17448c2ecf20Sopenharmony_ci			continue;
17458c2ecf20Sopenharmony_ci		if (unlikely(bh_ofs >= end))
17468c2ecf20Sopenharmony_ci			break;
17478c2ecf20Sopenharmony_ci		set_buffer_dirty(bh);
17488c2ecf20Sopenharmony_ci	} while ((bh = bh->b_this_page) != head);
17498c2ecf20Sopenharmony_ci	spin_unlock(&mapping->private_lock);
17508c2ecf20Sopenharmony_ci	__set_page_dirty_nobuffers(page);
17518c2ecf20Sopenharmony_ci	if (unlikely(buffers_to_free)) {
17528c2ecf20Sopenharmony_ci		do {
17538c2ecf20Sopenharmony_ci			bh = buffers_to_free->b_this_page;
17548c2ecf20Sopenharmony_ci			free_buffer_head(buffers_to_free);
17558c2ecf20Sopenharmony_ci			buffers_to_free = bh;
17568c2ecf20Sopenharmony_ci		} while (buffers_to_free);
17578c2ecf20Sopenharmony_ci	}
17588c2ecf20Sopenharmony_ci}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci#endif /* NTFS_RW */
1761