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