11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * aops.c - NTFS kernel address space operations and page cache handling.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	    Part of the Linux-NTFS project.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov * Copyright (c) 2001-2007 Anton Altaparmakov
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002 Richard Russon
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program/include file is free software; you can redistribute it and/or
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License as published
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the Free Software Foundation; either version 2 of the License, or
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program/include file is distributed in the hope that it will be
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program (in the main directory of the Linux-NTFS
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * distribution in the file COPYING); if not, write to the Free Software
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
2578264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov#include <linux/fs.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/swap.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/writeback.h>
32b4012a9895b3e28e3bff3aa534d58c7827af6d4fAndrew Morton#include <linux/bit_spinlock.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "aops.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "attrib.h"
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "debug.h"
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "inode.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mft.h"
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "runlist.h"
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "types.h"
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ntfs.h"
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_end_buffer_async_read - async io completion for reading attributes
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @bh:		buffer head on which io is completed
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @uptodate:	whether @bh is now uptodate or not
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Asynchronous I/O completion handler for reading pages belonging to the
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attribute address space of an inode.  The inodes can either be files or
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * directories or they can be fake inodes describing some attribute.
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If NInoMstProtected(), perform the post read mst fixups when all IO on the
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page has been completed and mark the page uptodate or set the error bit on
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the page.  To determine the size of the records that need fixing up, we
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cheat a little bit by setting the index_block_size in ntfs_inode to the ntfs
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * record size, and index_block_size_bits, to the log(base 2) of the ntfs
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * record size.
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
62e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	struct buffer_head *first, *tmp;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page;
64f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	struct inode *vi;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int page_uptodate = 1;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page = bh->b_page;
69f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	vi = page->mapping->host;
70f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	ni = NTFS_I(vi);
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (likely(uptodate)) {
73f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		loff_t i_size;
74f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		s64 file_ofs, init_size;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_buffer_uptodate(bh);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) +
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh_offset(bh);
8007a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov		read_lock_irqsave(&ni->size_lock, flags);
81f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		init_size = ni->initialized_size;
82f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		i_size = i_size_read(vi);
8307a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov		read_unlock_irqrestore(&ni->size_lock, flags);
84f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		if (unlikely(init_size > i_size)) {
85f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			/* Race with shrinking truncate. */
86f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			init_size = i_size;
87f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Check for the current buffer head overflowing. */
89f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		if (unlikely(file_ofs + bh->b_size > init_size)) {
90f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			int ofs;
91eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			void *kaddr;
92f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov
93f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			ofs = 0;
94f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			if (file_ofs < init_size)
95f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov				ofs = init_size - file_ofs;
96fa8609da993b04dc2dd762173a6d0ab1a192e256Andrew Morton			local_irq_save(flags);
97eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
98eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			memset(kaddr + bh_offset(bh) + ofs, 0,
99eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter					bh->b_size - ofs);
100eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			flush_dcache_page(page);
101eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
102fa8609da993b04dc2dd762173a6d0ab1a192e256Andrew Morton			local_irq_restore(flags);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_buffer_uptodate(bh);
106e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov		SetPageError(page);
107f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		ntfs_error(ni->vol->sb, "Buffer I/O error, logical block "
108f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov				"0x%llx.", (unsigned long long)bh->b_blocknr);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
110e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	first = page_buffers(page);
111e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	local_irq_save(flags);
112e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_buffer_async_read(bh);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_buffer(bh);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = bh;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!buffer_uptodate(tmp))
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			page_uptodate = 0;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (buffer_async_read(tmp)) {
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(buffer_locked(tmp)))
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto still_busy;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Async buffers must be locked. */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG();
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = tmp->b_this_page;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (tmp != bh);
127e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
128e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	local_irq_restore(flags);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If none of the buffers had errors then we can set the page uptodate,
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * but we first have to perform the post read mst fixups, if the
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * attribute is mst protected, i.e. if NInoMstProteced(ni) is true.
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note we ignore fixup errors as those are detected when
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * map_mft_record() is called which gives us per record granularity
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * rather than per page granularity.
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoMstProtected(ni)) {
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (likely(page_uptodate && !PageError(page)))
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageUptodate(page);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
141f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		u8 *kaddr;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int i, recs;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 rec_size;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rec_size = ni->itype.index.block_size;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		recs = PAGE_CACHE_SIZE / rec_size;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Should have been verified before we got here... */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!recs);
149fa8609da993b04dc2dd762173a6d0ab1a192e256Andrew Morton		local_irq_save(flags);
150f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < recs; i++)
152f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov			post_read_mst_fixup((NTFS_RECORD*)(kaddr +
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					i * rec_size), rec_size);
154f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
155fa8609da993b04dc2dd762173a6d0ab1a192e256Andrew Morton		local_irq_restore(flags);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_dcache_page(page);
157b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov		if (likely(page_uptodate && !PageError(page)))
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageUptodate(page);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstill_busy:
163e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
164e604635c8bea16f6177e6133eb3efbfb4a029ef6Anton Altaparmakov	local_irq_restore(flags);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_read_block - fill a @page of an address space with data
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page cache page to fill with data
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill the page @page of the address space belonging to the @page->host inode.
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We read each buffer asynchronously and when all buffers are read in, our io
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * completion handler ntfs_end_buffer_read_async(), if required, automatically
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * applies the mst fixups to the page before finally marking it uptodate and
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unlocking it.
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We only enforce allocated_size limit because i_size is checked for in
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generic_file_read().
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 on success and -errno on error.
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Contains an adapted version of fs/buffer.c::block_read_full_page().
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_read_block(struct page *page)
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
187f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	loff_t i_size;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VCN vcn;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LCN lcn;
190f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	s64 init_size;
191f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	struct inode *vi;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	runlist_element *rl;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sector_t iblock, lblock, zblock;
19707a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	unsigned long flags;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int blocksize, vcn_ofs;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, nr;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char blocksize_bits;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
202f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	vi = page->mapping->host;
203f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	ni = NTFS_I(vi);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vol = ni->vol;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* $MFT/$DATA must have its complete runlist in memory at all times. */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni));
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20978af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	blocksize = vol->sb->s_blocksize;
21078af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	blocksize_bits = vol->sb->s_blocksize_bits;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov	if (!page_has_buffers(page)) {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		create_empty_buffers(page, blocksize, 0);
214a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov		if (unlikely(!page_has_buffers(page))) {
215a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			unlock_page(page);
216a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			return -ENOMEM;
217a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov		}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
219a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov	bh = head = page_buffers(page);
220a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov	BUG_ON(!bh);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	/*
223f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * We may be racing with truncate.  To avoid some of the problems we
224f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * now take a snapshot of the various sizes and use those for the whole
225f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * of the function.  In case of an extending truncate it just means we
226f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * may leave some buffers unmapped which are now allocated.  This is
227f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * not a problem since these buffers will just get mapped when a write
228f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * occurs.  In case of a shrinking truncate, we will detect this later
229f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * on due to the runlist being incomplete and if the page is being
230f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * fully truncated, truncate will throw it away as soon as we unlock
231f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 * it so no need to worry what we do with it.
232f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	 */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
23407a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	read_lock_irqsave(&ni->size_lock, flags);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
236f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	init_size = ni->initialized_size;
237f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	i_size = i_size_read(vi);
23807a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	read_unlock_irqrestore(&ni->size_lock, flags);
239f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	if (unlikely(init_size > i_size)) {
240f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		/* Race with shrinking truncate. */
241f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		init_size = i_size;
242f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	}
243f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	zblock = (init_size + blocksize - 1) >> blocksize_bits;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Loop through all the buffers in the page. */
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rl = NULL;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nr = i = 0;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
249e3bf460f3eb86cdbc76725a0dac1f191e796676cNate Diller		int err = 0;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(buffer_uptodate(bh)))
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(buffer_mapped(bh))) {
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arr[nr++] = bh;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh->b_bdev = vol->sb->s_bdev;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Is the block within the allowed limits? */
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (iblock < lblock) {
260c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson			bool is_retry = false;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Convert iblock into corresponding vcn and offset. */
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vcn = (VCN)iblock << blocksize_bits >>
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vol->cluster_size_bits;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vcn_ofs = ((VCN)iblock << blocksize_bits) &
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vol->cluster_size_mask;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!rl) {
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslock_retry_remap:
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				down_read(&ni->runlist.lock);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rl = ni->runlist.rl;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(rl != NULL)) {
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Seek to element containing target vcn. */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				while (rl->length && rl[1].vcn <= vcn)
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					rl++;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lcn = LCN_RL_NOT_MAPPED;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Successful remap. */
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (lcn >= 0) {
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Setup buffer head to correct block. */
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh->b_blocknr = ((lcn << vol->cluster_size_bits)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						+ vcn_ofs) >> blocksize_bits;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				set_buffer_mapped(bh);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Only read initialized data blocks. */
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (iblock < zblock) {
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					arr[nr++] = bh;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Fully non-initialized data block, zero it. */
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto handle_zblock;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* It is a hole, need to zero it. */
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (lcn == LCN_HOLE)
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto handle_hole;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* If first try and runlist unmapped, map and retry. */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
298c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson				is_retry = true;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Attempt to map runlist, dropping lock for
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * the duration.
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up_read(&ni->runlist.lock);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = ntfs_map_runlist(ni, vcn);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (likely(!err))
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto lock_retry_remap;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rl = NULL;
3089f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov			} else if (!rl)
3099f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov				up_read(&ni->runlist.lock);
3108273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			/*
3118273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			 * If buffer is outside the runlist, treat it as a
3128273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			 * hole.  This can happen due to concurrent truncate
3138273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			 * for example.
3148273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			 */
3158273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			if (err == -ENOENT || lcn == LCN_ENOENT) {
3168273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov				err = 0;
3178273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov				goto handle_hole;
3188273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Hard error, zero out region. */
3208273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			if (!err)
3218273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov				err = -EIO;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bh->b_blocknr = -1;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageError(page);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(vol->sb, "Failed to read from inode 0x%lx, "
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"attribute type 0x%x, vcn 0x%llx, "
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"offset 0x%x because its location on "
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"disk could not be determined%s "
3288273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov					"(error code %i).", ni->mft_no,
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ni->type, (unsigned long long)vcn,
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vcn_ofs, is_retry ? " even after "
3318273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov					"retrying" : "", err);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Either iblock was outside lblock limits or
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ntfs_rl_vcn_to_lcn() returned error.  Just zero that portion
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * of the page and set the buffer uptodate.
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshandle_hole:
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh->b_blocknr = -1UL;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_buffer_mapped(bh);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshandle_zblock:
342eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter		zero_user(page, i * blocksize, blocksize);
3438273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		if (likely(!err))
3448273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			set_buffer_uptodate(bh);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (i++, iblock++, (bh = bh->b_this_page) != head);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Release the lock if we took it. */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rl)
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up_read(&ni->runlist.lock);
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check we have at least one buffer ready for i/o. */
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nr) {
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct buffer_head *tbh;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Lock the buffers. */
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < nr; i++) {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tbh = arr[i];
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lock_buffer(tbh);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tbh->b_end_io = ntfs_end_buffer_async_read;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_buffer_async_read(tbh);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Finally, start i/o on the buffers. */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < nr; i++) {
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tbh = arr[i];
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(!buffer_uptodate(tbh)))
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				submit_bh(READ, tbh);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_end_buffer_async_read(tbh, 1);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No i/o was scheduled on any of the buffers. */
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (likely(!PageError(page)))
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SetPageUptodate(page);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else /* Signal synchronous i/o error. */
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = -EIO;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nr;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_readpage - fill a @page of a @file with data from the device
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @file:	open file to which the page @page belongs or NULL
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page cache page to fill with data
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For non-resident attributes, ntfs_readpage() fills the @page of the open
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * file @file by calling the ntfs version of the generic block_read_full_page()
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function, ntfs_read_block(), which in turn creates and reads in the buffers
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * associated with the page asynchronously.
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For resident attributes, OTOH, ntfs_readpage() fills @page by copying the
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data from the mft record (which at this stage is most likely in memory) and
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fills the remainder with zeroes. Thus, in this case, I/O is synchronous, as
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * even if the mft record is not cached at this point in time, we need to wait
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for it to be read in before we can do the copy.
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 on success and -errno on error.
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_readpage(struct file *file, struct page *page)
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
401f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	loff_t i_size;
402f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	struct inode *vi;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni, *base_ni;
404bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	u8 *addr;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_search_ctx *ctx;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MFT_RECORD *mrec;
407b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov	unsigned long flags;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 attr_len;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakovretry_readpage:
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!PageLocked(page));
413ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov	vi = page->mapping->host;
414ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov	i_size = i_size_read(vi);
415ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov	/* Is the page fully outside i_size? (truncate in progress) */
416ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov	if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
417ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov			PAGE_CACHE_SHIFT)) {
418eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter		zero_user(page, 0, PAGE_CACHE_SIZE);
419ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov		ntfs_debug("Read outside i_size - truncated?");
420ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov		goto done;
421ebab89909e0dc716282d5e7f6e73a3155fe66d4aAnton Altaparmakov	}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This can potentially happen because we clear PageUptodate() during
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ntfs_writepage() of MstProtected() attributes.
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (PageUptodate(page)) {
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
430f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	ni = NTFS_I(vi);
431311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	/*
432311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * Only $DATA attributes can be encrypted and only unnamed $DATA
433311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * attributes can be compressed.  Index root can have the flags set but
434311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * this means to create compressed/encrypted files, not that the
4354e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * attribute is compressed/encrypted.  Note we need to check for
4364e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * AT_INDEX_ALLOCATION since this is the type of both directory and
4374e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * index inodes.
438311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 */
4394e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	if (ni->type != AT_INDEX_ALLOCATION) {
440311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		/* If attribute is encrypted, deny access, just like NT4. */
441311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		if (NInoEncrypted(ni)) {
442311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			BUG_ON(ni->type != AT_DATA);
443311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			err = -EACCES;
444311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			goto err_out;
445311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		}
446311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		/* Compressed data streams are handled in compress.c. */
447311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		if (NInoNonResident(ni) && NInoCompressed(ni)) {
448311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			BUG_ON(ni->type != AT_DATA);
449311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			BUG_ON(ni->name_len);
450311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov			return ntfs_read_compressed_block(page);
451311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		}
452311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* NInoNonResident() == NInoIndexAllocPresent() */
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (NInoNonResident(ni)) {
455311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov		/* Normal, non-resident data stream. */
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ntfs_read_block(page);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Attribute is resident, implying it is not compressed or encrypted.
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This also means the attribute is smaller than an mft record and
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * hence smaller than a page, so can simply zero out any pages with
462311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * index above 0.  Note the attribute can actually be marked compressed
463311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * but if it is resident the actual data is not compressed so we are
464311120eca0013083f5eb0aff13ffb8aa9fdd050cAnton Altaparmakov	 * ok to ignore the compressed flag here.
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
466b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov	if (unlikely(page->index > 0)) {
467eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter		zero_user(page, 0, PAGE_CACHE_SIZE);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto done;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoAttr(ni))
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_ni = ni;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_ni = ni->ext.base_ntfs_ino;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Map, pin, and lock the mft record. */
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mrec = map_mft_record(base_ni);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(mrec)) {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(mrec);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
480905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	/*
481905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 * If a parallel write made the attribute non-resident, drop the mft
482905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 * record and retry the readpage.
483905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 */
484905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	if (unlikely(NInoNonResident(ni))) {
485905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov		unmap_mft_record(base_ni);
486905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov		goto retry_readpage;
487905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ctx)) {
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_err_out;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			CASE_SENSITIVE, 0, NULL, 0, ctx);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err))
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto put_unm_err_out;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
498b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov	read_lock_irqsave(&ni->size_lock, flags);
499b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov	if (unlikely(attr_len > ni->initialized_size))
500b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov		attr_len = ni->initialized_size;
501f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	i_size = i_size_read(vi);
502b6ad6c52fe36ab35d0fe28c064f59de2ba670c2aAnton Altaparmakov	read_unlock_irqrestore(&ni->size_lock, flags);
503f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	if (unlikely(attr_len > i_size)) {
504f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		/* Race with shrinking truncate. */
505f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		attr_len = i_size;
506f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	}
507bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	addr = kmap_atomic(page, KM_USER0);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Copy the data to the page. */
509bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	memcpy(addr, (u8*)ctx->attr +
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le16_to_cpu(ctx->attr->data.resident.value_offset),
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			attr_len);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Zero the remainder of the page. */
513bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_dcache_page(page);
515bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	kunmap_atomic(addr, KM_USER0);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsput_unm_err_out:
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_put_search_ctx(ctx);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunm_err_out:
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unmap_mft_record(base_ni);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone:
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SetPageUptodate(page);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out:
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_write_block - write a @page to the backing store
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page cache page to write out
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wbc:	writeback control structure
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function is for writing pages belonging to non-resident, non-mst
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * protected attributes to their backing store.
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For a page with buffers, map and write the dirty buffers asynchronously
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under page writeback. For a page without buffers, create buffers for the
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page, then proceed as above.
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a page doesn't have buffers the page dirty state is definitive. If a page
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does have buffers, the page dirty state is just a hint, and the buffer dirty
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state is definitive. (A hint which has rules: dirty buffers against a clean
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page is illegal. Other combinations are legal and need to be handled. In
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular a dirty page containing clean buffers for example.)
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 on success and -errno on error.
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on ntfs_read_block() and __block_write_full_page().
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_write_block(struct page *page, struct writeback_control *wbc)
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VCN vcn;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LCN lcn;
55507a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	s64 initialized_size;
55607a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	loff_t i_size;
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sector_t block, dblock, iblock;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *vi;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	runlist_element *rl;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct buffer_head *bh, *head;
56307a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	unsigned long flags;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int blocksize, vcn_ofs;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
566c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson	bool need_end_writeback;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char blocksize_bits;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vi = page->mapping->host;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ni = NTFS_I(vi);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vol = ni->vol;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"0x%lx.", ni->mft_no, ni->type, page->index);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!NInoNonResident(ni));
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(NInoMstProtected(ni));
57878af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	blocksize = vol->sb->s_blocksize;
57978af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	blocksize_bits = vol->sb->s_blocksize_bits;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!page_has_buffers(page)) {
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!PageUptodate(page));
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		create_empty_buffers(page, blocksize,
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1 << BH_Uptodate) | (1 << BH_Dirty));
584a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov		if (unlikely(!page_has_buffers(page))) {
585a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			ntfs_warning(vol->sb, "Error allocating page "
586a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov					"buffers.  Redirtying page so we try "
587a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov					"again later.");
588a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			/*
589a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			 * Put the page back on mapping->dirty_pages, but leave
590a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			 * its buffers' dirty state as-is.
591a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			 */
592a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			redirty_page_for_writepage(wbc, page);
593a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			unlock_page(page);
594a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov			return 0;
595a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov		}
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bh = head = page_buffers(page);
598a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov	BUG_ON(!bh);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* NOTE: Different naming scheme to ntfs_read_block()! */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first block in the page. */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60507a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	read_lock_irqsave(&ni->size_lock, flags);
60607a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	i_size = i_size_read(vi);
60707a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	initialized_size = ni->initialized_size;
60807a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	read_unlock_irqrestore(&ni->size_lock, flags);
60907a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first out of bounds block for the data size. */
61107a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	dblock = (i_size + blocksize - 1) >> blocksize_bits;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The last (fully or partially) initialized block. */
61407a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	iblock = initialized_size >> blocksize_bits;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * here, and the (potentially unmapped) buffers may become dirty at
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * any time.  If a buffer becomes dirty here after we've inspected it
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * then we just miss that fact, and the page stays dirty.
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Buffers outside i_size may be dirtied by __set_page_dirty_buffers;
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * handle that here by just cleaning them.
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Loop through all the buffers in the page, mapping all the dirty
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * buffers to disk addresses and handling any aliases from the
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * underlying block device's mapping.
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rl = NULL;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = 0;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
634c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson		bool is_retry = false;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(block >= dblock)) {
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Mapped buffers outside i_size will occur, because
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * this page can be outside i_size when there is a
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * truncate in progress. The contents of such buffers
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * were zeroed by ntfs_writepage().
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * FIXME: What about the small race window where
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ntfs_writepage() has not done any clearing because
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * the page was within i_size but before we get here,
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * vmtruncate() modifies i_size?
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clear_buffer_dirty(bh);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_buffer_uptodate(bh);
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Clean buffers are not written out, so no need to map them. */
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!buffer_dirty(bh))
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Make sure we have enough initialized size. */
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely((block >= iblock) &&
65907a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov				(initialized_size < i_size))) {
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If this page is fully outside initialized size, zero
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * out all pages between the current initialized size
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * and the current page. Just use ntfs_readpage() to do
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * the zeroing transparently.
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (block > iblock) {
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// TODO:
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// For each page do:
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// - read_cache_page()
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Again for each page do:
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// - wait_on_page_locked()
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// - Check (PageUptodate(page) &&
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				//			!PageError(page))
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Update initialized size in the attribute and
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// in the inode.
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Again, for each page do:
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				//	__set_page_dirty_buffers();
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// page_cache_release()
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// We don't need to wait on the writes.
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Update iblock.
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The current page straddles initialized size. Zero
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * all non-uptodate buffers and set them uptodate (and
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * dirty?). Note, there aren't any non-uptodate buffers
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * if the page is uptodate.
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * FIXME: For an uptodate page, the buffers may need to
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * be written out because they were not initialized on
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * disk before.
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!PageUptodate(page)) {
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// TODO:
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Zero any non-uptodate buffers up to i_size.
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// Set them uptodate and dirty.
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// TODO:
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Update initialized size in the attribute and in the
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// inode (up to i_size).
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Update iblock.
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// FIXME: This is inefficient. Try to batch the two
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// size changes to happen in one go.
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(vol->sb, "Writing beyond initialized size "
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"is not supported yet. Sorry.");
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -EOPNOTSUPP;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Do NOT set_buffer_new() BUT DO clear buffer range
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// outside write request range.
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// set_buffer_uptodate() on complete buffers as well as
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// set_buffer_dirty().
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No need to map buffers that are already mapped. */
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (buffer_mapped(bh))
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Unmapped, dirty buffer. Need to map it. */
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh->b_bdev = vol->sb->s_bdev;
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Convert block into corresponding vcn and offset. */
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vcn = (VCN)block << blocksize_bits;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vcn_ofs = vcn & vol->cluster_size_mask;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vcn >>= vol->cluster_size_bits;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!rl) {
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslock_retry_remap:
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			down_read(&ni->runlist.lock);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rl = ni->runlist.rl;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (likely(rl != NULL)) {
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Seek to element containing target vcn. */
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			while (rl->length && rl[1].vcn <= vcn)
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rl++;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lcn = LCN_RL_NOT_MAPPED;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Successful remap. */
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lcn >= 0) {
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Setup buffer head to point to correct block. */
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bh->b_blocknr = ((lcn << vol->cluster_size_bits) +
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vcn_ofs) >> blocksize_bits;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_buffer_mapped(bh);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* It is a hole, need to instantiate it. */
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lcn == LCN_HOLE) {
7458dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			u8 *kaddr;
7468dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			unsigned long *bpos, *bend;
7478dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov
7488dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			/* Check if the buffer is zero. */
7498dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			kaddr = kmap_atomic(page, KM_USER0);
7508dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			bpos = (unsigned long *)(kaddr + bh_offset(bh));
7518dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			bend = (unsigned long *)((u8*)bpos + blocksize);
7528dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			do {
7538dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				if (unlikely(*bpos))
7548dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov					break;
7558dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			} while (likely(++bpos < bend));
7568dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			kunmap_atomic(kaddr, KM_USER0);
7578dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			if (bpos == bend) {
7588dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				/*
7598dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				 * Buffer is zero and sparse, no need to write
7608dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				 * it.
7618dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				 */
7628dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				bh->b_blocknr = -1;
7638dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				clear_buffer_dirty(bh);
7648dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov				continue;
7658dcdebafb848415eae25924b00c4f0b9ec907da0Anton Altaparmakov			}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// TODO: Instantiate the hole.
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// clear_buffer_new(bh);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(vol->sb, "Writing into sparse regions is "
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"not supported yet. Sorry.");
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -EOPNOTSUPP;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If first try and runlist unmapped, map and retry. */
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
776c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson			is_retry = true;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Attempt to map runlist, dropping lock for
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * the duration.
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up_read(&ni->runlist.lock);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = ntfs_map_runlist(ni, vcn);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(!err))
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto lock_retry_remap;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rl = NULL;
7869f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov		} else if (!rl)
7879f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov			up_read(&ni->runlist.lock);
7888273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		/*
7898273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		 * If buffer is outside the runlist, truncate has cut it out
7908273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		 * of the runlist.  Just clean and clear the buffer and set it
7918273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		 * uptodate so it can get discarded by the VM.
7928273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		 */
7938273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		if (err == -ENOENT || lcn == LCN_ENOENT) {
7948273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			bh->b_blocknr = -1;
7958273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			clear_buffer_dirty(bh);
796eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			zero_user(page, bh_offset(bh), blocksize);
7978273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			set_buffer_uptodate(bh);
7988273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			err = 0;
7998273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			continue;
8008273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Failed to map the buffer, even after retrying. */
8028273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov		if (!err)
8038273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov			err = -EIO;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh->b_blocknr = -1;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(vol->sb, "Failed to write to inode 0x%lx, "
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"attribute type 0x%x, vcn 0x%llx, offset 0x%x "
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"because its location on disk could not be "
8088273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov				"determined%s (error code %i).", ni->mft_no,
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ni->type, (unsigned long long)vcn,
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vcn_ofs, is_retry ? " even after "
8118273d5d4c28a9fde68f830cc6ff61e37e8ae1dcaAnton Altaparmakov				"retrying" : "", err);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (block++, (bh = bh->b_this_page) != head);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Release the lock if we took it. */
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rl)
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up_read(&ni->runlist.lock);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* For the error case, need to reset bh to the beginning. */
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bh = head;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82254b02eb01c0172294e43e2b54d6815f65637c111Anton Altaparmakov	/* Just an optimization, so ->readpage() is not called later. */
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!PageUptodate(page))) {
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int uptodate = 1;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!buffer_uptodate(bh)) {
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				uptodate = 0;
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh = head;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while ((bh = bh->b_this_page) != head);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (uptodate)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageUptodate(page);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup all mapped, dirty buffers for async write i/o. */
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (buffer_mapped(bh) && buffer_dirty(bh)) {
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lock_buffer(bh);
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_clear_buffer_dirty(bh)) {
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG_ON(!buffer_uptodate(bh));
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mark_buffer_async_write(bh);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				unlock_buffer(bh);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (unlikely(err)) {
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * For the error case. The buffer may have been set
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * dirty during attachment to a dirty page.
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err != -ENOMEM)
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				clear_buffer_dirty(bh);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while ((bh = bh->b_this_page) != head);
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err)) {
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// TODO: Remove the -EOPNOTSUPP check later on...
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(err == -EOPNOTSUPP))
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = 0;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (err == -ENOMEM) {
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_warning(vol->sb, "Error allocating memory. "
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"Redirtying page so we try again "
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"later.");
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Put the page back on mapping->dirty_pages, but
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * leave its buffer's dirty state as-is.
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			redirty_page_for_writepage(wbc, page);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = 0;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageError(page);
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(PageWriteback(page));
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_page_writeback(page);	/* Keeps try_to_free_buffers() away. */
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
87654b02eb01c0172294e43e2b54d6815f65637c111Anton Altaparmakov	/* Submit the prepared buffers for i/o. */
877c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson	need_end_writeback = true;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct buffer_head *next = bh->b_this_page;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (buffer_async_write(bh)) {
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			submit_bh(WRITE, bh);
882c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson			need_end_writeback = false;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh = next;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (bh != head);
88654b02eb01c0172294e43e2b54d6815f65637c111Anton Altaparmakov	unlock_page(page);
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If no i/o was started, need to end_page_writeback(). */
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(need_end_writeback))
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end_page_writeback(page);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Done.");
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_write_mst_block - write a @page to the backing store
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page cache page to write out
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wbc:	writeback control structure
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function is for writing pages belonging to non-resident, mst protected
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attributes to their backing store.  The only supported attributes are index
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocation and $MFT/$DATA.  Both directory inodes and index inodes are
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * supported for the index allocation case.
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The page must remain locked for the duration of the write because we apply
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the mst fixups, write, and then undo the fixups, so if we were to unlock the
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page before undoing the fixups, any other user of the page will see the
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page contents as corrupt.
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We clear the page uptodate flag for the duration of the function to ensure
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exclusion for the $MFT/$DATA case against someone mapping an mft record we
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are about to apply the mst fixups to.
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 on success and -errno on error.
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on ntfs_write_block(), ntfs_mft_writepage(), and
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write_mft_record_nolock().
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_write_mst_block(struct page *page,
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct writeback_control *wbc)
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sector_t block, dblock, rec_block;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *vi = page->mapping->host;
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni = NTFS_I(vi);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_volume *vol = ni->vol;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 *kaddr;
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int rec_size = ni->itype.index.block_size;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *locked_nis[PAGE_CACHE_SIZE / rec_size];
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct buffer_head *bh, *head, *tbh, *rec_start_bh;
931d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	runlist_element *rl;
933d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	int i, nr_locked_nis, nr_recs, nr_bhs, max_bhs, bhs_per_rec, err, err2;
934d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	unsigned bh_size, rec_size_bits;
935c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson	bool sync, is_mft, page_is_dirty, rec_is_dirty;
936d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	unsigned char bh_size_bits;
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, page index "
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"0x%lx.", vi->i_ino, ni->type, page->index);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!NInoNonResident(ni));
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!NInoMstProtected(ni));
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	is_mft = (S_ISREG(vi->i_mode) && !vi->i_ino);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * NOTE: ntfs_write_mst_block() would be called for $MFTMirr if a page
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * in its page cache were to be marked dirty.  However this should
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * never happen with the current driver and considering we do not
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * handle this case here we do want to BUG(), at least for now.
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) ||
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION)));
95178af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	bh_size = vol->sb->s_blocksize;
95278af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	bh_size_bits = vol->sb->s_blocksize_bits;
953d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	max_bhs = PAGE_CACHE_SIZE / bh_size;
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!max_bhs);
955d53ee3222459f347cb18985a845864bc81a44eafAnton Altaparmakov	BUG_ON(max_bhs > MAX_BUF_PER_PAGE);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Were we called for sync purposes? */
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sync = (wbc->sync_mode == WB_SYNC_ALL);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure we have mapped buffers. */
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bh = head = page_buffers(page);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!bh);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rec_size_bits = ni->itype.index.block_size_bits;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!(PAGE_CACHE_SIZE >> rec_size_bits));
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bhs_per_rec = rec_size >> bh_size_bits;
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!bhs_per_rec);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first block in the page. */
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rec_block = block = (sector_t)page->index <<
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(PAGE_CACHE_SHIFT - bh_size_bits);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The first out of bounds block for the data size. */
97407a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	dblock = (i_size_read(vi) + bh_size - 1) >> bh_size_bits;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rl = NULL;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0;
978c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson	page_is_dirty = rec_is_dirty = false;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rec_start_bh = NULL;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
981c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson		bool is_retry = false;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (likely(block < rec_block)) {
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (unlikely(block >= dblock)) {
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				clear_buffer_dirty(bh);
986946929d813a3bde095678526dd037ab9ac6efe35Anton Altaparmakov				set_buffer_uptodate(bh);
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * This block is not the first one in the record.  We
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ignore the buffer's dirty state because we could
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * have raced with a parallel mark_ntfs_record_dirty().
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!rec_is_dirty)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (unlikely(err2)) {
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (err2 != -ENOMEM)
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					clear_buffer_dirty(bh);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else /* if (block == rec_block) */ {
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG_ON(block > rec_block);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* This block is the first one in the record. */
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rec_block += bhs_per_rec;
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err2 = 0;
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (unlikely(block >= dblock)) {
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				clear_buffer_dirty(bh);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!buffer_dirty(bh)) {
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Clean records are not written out. */
1012c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson				rec_is_dirty = false;
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1015c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson			rec_is_dirty = true;
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rec_start_bh = bh;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Need to map the buffer if it is not mapped already. */
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(!buffer_mapped(bh))) {
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			VCN vcn;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			LCN lcn;
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int vcn_ofs;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1024481d0374217f3fefaf98efbd8d21d73c138dd928Anton Altaparmakov			bh->b_bdev = vol->sb->s_bdev;
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Obtain the vcn and offset of the current block. */
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vcn = (VCN)block << bh_size_bits;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vcn_ofs = vcn & vol->cluster_size_mask;
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vcn >>= vol->cluster_size_bits;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!rl) {
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslock_retry_remap:
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				down_read(&ni->runlist.lock);
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rl = ni->runlist.rl;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(rl != NULL)) {
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Seek to element containing target vcn. */
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				while (rl->length && rl[1].vcn <= vcn)
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					rl++;
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lcn = LCN_RL_NOT_MAPPED;
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Successful remap. */
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (likely(lcn >= 0)) {
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Setup buffer head to correct block. */
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh->b_blocknr = ((lcn <<
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						vol->cluster_size_bits) +
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						vcn_ofs) >> bh_size_bits;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				set_buffer_mapped(bh);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Remap failed.  Retry to map the runlist once
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * unless we are working on $MFT which always
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * has the whole of its runlist in memory.
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!is_mft && !is_retry &&
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						lcn == LCN_RL_NOT_MAPPED) {
1056c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson					is_retry = true;
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					/*
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 * Attempt to map runlist, dropping
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 * lock for the duration.
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 */
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					up_read(&ni->runlist.lock);
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					err2 = ntfs_map_runlist(ni, vcn);
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (likely(!err2))
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto lock_retry_remap;
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (err2 == -ENOMEM)
1066c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson						page_is_dirty = true;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					lcn = err2;
10689f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov				} else {
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					err2 = -EIO;
10709f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov					if (!rl)
10719f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov						up_read(&ni->runlist.lock);
10729f993fe4634b39ca4404ba278053b03f360ec08aAnton Altaparmakov				}
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Hard error.  Abort writing this record. */
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!err || err == -ENOMEM)
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					err = err2;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh->b_blocknr = -1;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_error(vol->sb, "Cannot write ntfs record "
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"0x%llx (inode 0x%lx, "
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"attribute type 0x%x) because "
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"its location on disk could "
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"not be determined (error "
10828907547d4b099e67762ea4891c127ea1f6dd1cb7Randy Dunlap						"code %lli).",
10838907547d4b099e67762ea4891c127ea1f6dd1cb7Randy Dunlap						(long long)block <<
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						bh_size_bits >>
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						vol->mft_record_size_bits,
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						ni->mft_no, ni->type,
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						(long long)lcn);
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * If this is not the first buffer, remove the
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * buffers in this record from the list of
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * buffers to write and clear their dirty bit
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * if not error -ENOMEM.
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (rec_start_bh != bh) {
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					while (bhs[--nr_bhs] != rec_start_bh)
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						;
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (err2 != -ENOMEM) {
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						do {
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							clear_buffer_dirty(
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								rec_start_bh);
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						} while ((rec_start_bh =
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								rec_start_bh->
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								b_this_page) !=
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								bh);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!buffer_uptodate(bh));
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(nr_bhs >= max_bhs);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bhs[nr_bhs++] = bh;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (block++, (bh = bh->b_this_page) != head);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(rl))
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up_read(&ni->runlist.lock);
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If there were no dirty buffers, we are done. */
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!nr_bhs)
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto done;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Map the page so we can access its contents. */
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kaddr = kmap(page);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear the page uptodate flag whilst the mst fixups are applied. */
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!PageUptodate(page));
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ClearPageUptodate(page);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < nr_bhs; i++) {
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int ofs;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Skip buffers which are not at the beginning of records. */
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i % bhs_per_rec)
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tbh = bhs[i];
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ofs = bh_offset(tbh);
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (is_mft) {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_inode *tni;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long mft_no;
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Get the mft record number. */
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mft_no = (((s64)page->index << PAGE_CACHE_SHIFT) + ofs)
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					>> rec_size_bits;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Check whether to write this mft record. */
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tni = NULL;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!ntfs_may_write_mft_record(vol, mft_no,
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(MFT_RECORD*)(kaddr + ofs), &tni)) {
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * The record should not be written.  This
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * means we need to redirty the page before
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * returning.
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
1148c49c31115067bc7c9a51ffdc735a515151dfa3ebRichard Knutsson				page_is_dirty = true;
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Remove the buffers in this mft record from
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * the list of buffers to write.
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				do {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					bhs[i] = NULL;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} while (++i % bhs_per_rec);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The record should be written.  If a locked ntfs
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * inode was returned, add it to the array of locked
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ntfs inodes.
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tni)
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				locked_nis[nr_locked_nis++] = tni;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Apply the mst protection fixups. */
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err2 = pre_write_mst_fixup((NTFS_RECORD*)(kaddr + ofs),
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rec_size);
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(err2)) {
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!err || err == -ENOMEM)
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -EIO;
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(vol->sb, "Failed to apply mst fixups "
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"(inode 0x%lx, attribute type 0x%x, "
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"page index 0x%lx, page offset 0x%x)!"
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"  Unmount and run chkdsk.", vi->i_ino,
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ni->type, page->index, ofs);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Mark all the buffers in this record clean as we do
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * not want to write corrupt data to disk.
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do {
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				clear_buffer_dirty(bhs[i]);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bhs[i] = NULL;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} while (++i % bhs_per_rec);
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr_recs++;
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If no records are to be written out, we are done. */
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!nr_recs)
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unm_done;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_dcache_page(page);
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Lock buffers and start synchronous write i/o on them. */
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < nr_bhs; i++) {
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tbh = bhs[i];
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!tbh)
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
1198ca5de404ff036a29b25e9a83f6919c9f606c5841Nick Piggin		if (!trylock_buffer(tbh))
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG();
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The buffer dirty state is now irrelevant, just clean it. */
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_buffer_dirty(tbh);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!buffer_uptodate(tbh));
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(!buffer_mapped(tbh));
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_bh(tbh);
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tbh->b_end_io = end_buffer_write_sync;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		submit_bh(WRITE, tbh);
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Synchronize the mft mirror now if not @sync. */
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_mft && !sync)
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto do_mirror;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_wait:
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wait on i/o completion of buffers. */
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < nr_bhs; i++) {
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tbh = bhs[i];
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!tbh)
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_on_buffer(tbh);
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(!buffer_uptodate(tbh))) {
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ntfs_error(vol->sb, "I/O error while writing ntfs "
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"record buffer (inode 0x%lx, "
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"attribute type 0x%x, page index "
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"0x%lx, page offset 0x%lx)!  Unmount "
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"and run chkdsk.", vi->i_ino, ni->type,
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					page->index, bh_offset(tbh));
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!err || err == -ENOMEM)
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -EIO;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Set the buffer uptodate so the page and buffer
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * states do not become out of sync.
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_buffer_uptodate(tbh);
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If @sync, now synchronize the mft mirror. */
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_mft && sync) {
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_mirror:
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < nr_bhs; i++) {
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long mft_no;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int ofs;
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Skip buffers which are not at the beginning of
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * records.
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (i % bhs_per_rec)
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tbh = bhs[i];
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Skip removed buffers (and hence records). */
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!tbh)
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ofs = bh_offset(tbh);
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Get the mft record number. */
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mft_no = (((s64)page->index << PAGE_CACHE_SHIFT) + ofs)
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					>> rec_size_bits;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mft_no < vol->mftmirr_size)
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ntfs_sync_mft_mirror(vol, mft_no,
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						(MFT_RECORD*)(kaddr + ofs),
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						sync);
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!sync)
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto do_wait;
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove the mst protection fixups again. */
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < nr_bhs; i++) {
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(i % bhs_per_rec)) {
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tbh = bhs[i];
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!tbh)
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			post_write_mst_fixup((NTFS_RECORD*)(kaddr +
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					bh_offset(tbh)));
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_dcache_page(page);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunm_done:
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Unlock any locked inodes. */
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (nr_locked_nis-- > 0) {
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_inode *tni, *base_tni;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tni = locked_nis[nr_locked_nis];
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Get the base inode. */
12814e5e529ad684f1b3fba957f5dd4eb7c2b534ee92Ingo Molnar		mutex_lock(&tni->extent_lock);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tni->nr_extents >= 0)
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			base_tni = tni;
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			base_tni = tni->ext.base_ntfs_ino;
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG_ON(!base_tni);
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12884e5e529ad684f1b3fba957f5dd4eb7c2b534ee92Ingo Molnar		mutex_unlock(&tni->extent_lock);
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Unlocking %s inode 0x%lx.",
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tni == base_tni ? "base" : "extent",
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tni->mft_no);
12924e5e529ad684f1b3fba957f5dd4eb7c2b534ee92Ingo Molnar		mutex_unlock(&tni->mrec_lock);
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_dec(&tni->count);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iput(VFS_I(base_tni));
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SetPageUptodate(page);
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(page);
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone:
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err && err != -ENOMEM)) {
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Set page error if there is only one ntfs record in the page.
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Otherwise we would loose per-record granularity.
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ni->itype.index.block_size == PAGE_CACHE_SIZE)
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageError(page);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NVolSetErrors(vol);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (page_is_dirty) {
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Page still contains one or more dirty ntfs "
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"records.  Redirtying the page starting at "
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"record 0x%lx.", page->index <<
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(PAGE_CACHE_SHIFT - rec_size_bits));
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		redirty_page_for_writepage(wbc, page);
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Keep the VM happy.  This must be done otherwise the
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * radix-tree tag PAGECACHE_TAG_DIRTY remains set even though
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the page is clean.
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(PageWriteback(page));
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_page_writeback(page);
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end_page_writeback(page);
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (likely(!err))
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Done.");
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_writepage - write a @page to the backing store
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page cache page to write out
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @wbc:	writeback control structure
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is called from the VM when it wants to have a dirty ntfs page cache
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * page cleaned.  The VM has already locked the page and marked it clean.
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For non-resident attributes, ntfs_writepage() writes the @page by calling
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the ntfs version of the generic block_write_full_page() function,
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_write_block(), which in turn if necessary creates and writes the
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffers associated with the page asynchronously.
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For resident attributes, OTOH, ntfs_writepage() writes the @page by copying
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the data to the mft record (which at this stage is most likely in memory).
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The mft record is then marked dirty and written out asynchronously via the
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vfs inode dirty code path for the inode the mft record belongs to or via the
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vm page dirty code path for the page the mft record is in.
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on ntfs_readpage() and fs/buffer.c::block_write_full_page().
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return 0 on success and -errno on error.
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ntfs_writepage(struct page *page, struct writeback_control *wbc)
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	loff_t i_size;
1357149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov	struct inode *vi = page->mapping->host;
1358149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov	ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi);
1359bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	char *addr;
1360149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov	ntfs_attr_search_ctx *ctx = NULL;
1361149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov	MFT_RECORD *m = NULL;
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 attr_len;
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1365905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakovretry_writepage:
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!PageLocked(page));
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i_size = i_size_read(vi);
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Is the page fully outside i_size? (truncate in progress) */
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PAGE_CACHE_SHIFT)) {
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The page may have dirty, unmapped buffers.  Make them
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * freeable here, so the page does not leak.
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		block_invalidatepage(page, 0);
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_debug("Write outside i_size - truncated?");
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1380bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	/*
1381bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * Only $DATA attributes can be encrypted and only unnamed $DATA
1382bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * attributes can be compressed.  Index root can have the flags set but
1383bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * this means to create compressed/encrypted files, not that the
13844e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * attribute is compressed/encrypted.  Note we need to check for
13854e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * AT_INDEX_ALLOCATION since this is the type of both directory and
13864e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	 * index inodes.
1387bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 */
13884e64c88693fde1b1cbaa4cfecad43a0c3fad354eAnton Altaparmakov	if (ni->type != AT_INDEX_ALLOCATION) {
1389bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		/* If file is encrypted, deny access, just like NT4. */
1390bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		if (NInoEncrypted(ni)) {
1391bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			unlock_page(page);
1392bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			BUG_ON(ni->type != AT_DATA);
13937d0ffdb279105d9a87b447758ce4a634496abfd1Anton Altaparmakov			ntfs_debug("Denying write access to encrypted file.");
1394bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			return -EACCES;
1395bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		}
1396bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		/* Compressed data streams are handled in compress.c. */
1397bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		if (NInoNonResident(ni) && NInoCompressed(ni)) {
1398bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			BUG_ON(ni->type != AT_DATA);
1399bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			BUG_ON(ni->name_len);
1400bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			// TODO: Implement and replace this with
1401bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			// return ntfs_write_compressed_block(page);
1402bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			unlock_page(page);
1403bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			ntfs_error(vi->i_sb, "Writing to compressed files is "
1404bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov					"not supported yet.  Sorry.");
1405bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			return -EOPNOTSUPP;
1406bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		}
1407bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		// TODO: Implement and remove this check.
1408bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		if (NInoNonResident(ni) && NInoSparse(ni)) {
1409bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			unlock_page(page);
1410bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			ntfs_error(vi->i_sb, "Writing to sparse files is not "
1411bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov					"supported yet.  Sorry.");
1412bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov			return -EOPNOTSUPP;
1413bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		}
1414bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	}
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* NInoNonResident() == NInoIndexAllocPresent() */
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (NInoNonResident(ni)) {
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We have to zero every time due to mmap-at-end-of-file. */
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) {
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* The page straddles i_size. */
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int ofs = i_size & ~PAGE_CACHE_MASK;
1421eebd2aa355692afaf9906f62118620f1a1c19dbbChristoph Lameter			zero_user_segment(page, ofs, PAGE_CACHE_SIZE);
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Handle mst protected attributes. */
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NInoMstProtected(ni))
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ntfs_write_mst_block(page, wbc);
1426bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov		/* Normal, non-resident data stream. */
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ntfs_write_block(page, wbc);
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1430bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * Attribute is resident, implying it is not compressed, encrypted, or
1431bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * mst protected.  This also means the attribute is smaller than an mft
1432bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * record and hence smaller than a page, so can simply return error on
1433bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * any pages with index above 0.  Note the attribute can actually be
1434bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * marked compressed but if it is resident the actual data is not
1435bd45fdd209ca49c5010ac9af469c41ae6dd3f145Anton Altaparmakov	 * compressed so we are ok to ignore the compressed flag here.
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(page_has_buffers(page));
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!PageUptodate(page));
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(page->index > 0)) {
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(vi->i_sb, "BUG()! page->index (0x%lx) > 0.  "
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"Aborting write.", page->index);
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG_ON(PageWriteback(page));
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_page_writeback(page);
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end_page_writeback(page);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!NInoAttr(ni))
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_ni = ni;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_ni = ni->ext.base_ntfs_ino;
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Map, pin, and lock the mft record. */
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	m = map_mft_record(base_ni);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(m)) {
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(m);
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		m = NULL;
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctx = NULL;
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1460905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	/*
1461905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 * If a parallel write made the attribute non-resident, drop the mft
1462905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 * record and retry the writepage.
1463905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	 */
1464905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	if (unlikely(NInoNonResident(ni))) {
1465905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov		unmap_mft_record(base_ni);
1466905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov		goto retry_writepage;
1467905685f68fc72844b8c2689c39a5c6c35e840152Anton Altaparmakov	}
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx = ntfs_attr_get_search_ctx(base_ni, m);
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!ctx)) {
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			CASE_SENSITIVE, 0, NULL, 0, ctx);
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(err))
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Keep the VM happy.  This must be done otherwise the radix-tree tag
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * PAGECACHE_TAG_DIRTY remains set even though the page is clean.
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(PageWriteback(page));
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_page_writeback(page);
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
148507a4e2da7dd3c9345f84b2552872f9d38c257451Anton Altaparmakov	i_size = i_size_read(vi);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(attr_len > i_size)) {
1487f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		/* Race with shrinking truncate or a failed truncate. */
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		attr_len = i_size;
1489f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		/*
1490f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		 * If the truncate failed, fix it up now.  If a concurrent
1491f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		 * truncate, we do its job, so it does not have to do anything.
1492f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		 */
1493f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
1494f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov				attr_len);
1495f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		/* Shrinking cannot fail. */
1496f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov		BUG_ON(err);
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1498bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	addr = kmap_atomic(page, KM_USER0);
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Copy the data from the page to the mft record. */
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy((u8*)ctx->attr +
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			le16_to_cpu(ctx->attr->data.resident.value_offset),
1502bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov			addr, attr_len);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Zero out of bounds area in the page cache page. */
1504bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
1505bfab36e81611e60573b84eb4e4b4c8d8545b2320Anton Altaparmakov	kunmap_atomic(addr, KM_USER0);
1506f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	flush_dcache_page(page);
15077d0ffdb279105d9a87b447758ce4a634496abfd1Anton Altaparmakov	flush_dcache_mft_record_page(ctx->ntfs_ino);
1508f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	/* We are done with the page. */
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	end_page_writeback(page);
1510f6098cf449b81c14a51e48dd22ae47d03126a1deAnton Altaparmakov	/* Finally, mark the mft record dirty, so it gets written back. */
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mark_mft_record_dirty(ctx->ntfs_ino);
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_attr_put_search_ctx(ctx);
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unmap_mft_record(base_ni);
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out:
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err == -ENOMEM) {
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_warning(vi->i_sb, "Error allocating memory. Redirtying "
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"page so we try again later.");
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Put the page back on mapping->dirty_pages, but leave its
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * buffers' dirty state as-is.
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		redirty_page_for_writepage(wbc, page);
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = 0;
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_error(vi->i_sb, "Resident attribute write failed with "
1527149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov				"error %i.", err);
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SetPageError(page);
1529149f0c5200188a43f1fc11ca2fb14d8183013d10Anton Altaparmakov		NVolSetErrors(ni->vol);
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ctx)
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ntfs_attr_put_search_ctx(ctx);
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (m)
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unmap_mft_record(base_ni);
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* NTFS_RW */
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_aops - general address space operations for inodes and attributes
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1544f5e54d6e53a20cef45af7499e86164f0e0d16bb2Christoph Hellwigconst struct address_space_operations ntfs_aops = {
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.readpage	= ntfs_readpage,	/* Fill page with data. */
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.writepage	= ntfs_writepage,	/* Write dirty page to disk. */
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NTFS_RW */
154978264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov	.migratepage	= buffer_migrate_page,	/* Move a page cache page from
155078264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov						   one physical page to an
155178264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov						   other. */
1552aa261f549d7652258331ebb12795f3bc4395d213Andi Kleen	.error_remove_page = generic_error_remove_page,
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ntfs_mst_aops - general address space operations for mst protecteed inodes
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		   and attributes
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1559f5e54d6e53a20cef45af7499e86164f0e0d16bb2Christoph Hellwigconst struct address_space_operations ntfs_mst_aops = {
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.readpage	= ntfs_readpage,	/* Fill page with data. */
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.writepage	= ntfs_writepage,	/* Write dirty page to disk. */
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_page_dirty	= __set_page_dirty_nobuffers,	/* Set the page dirty
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   without touching the buffers
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   belonging to the page. */
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NTFS_RW */
156778264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov	.migratepage	= buffer_migrate_page,	/* Move a page cache page from
156878264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov						   one physical page to an
156978264bd9c239237fe356c32d08abf8e52a2d8737Anton Altaparmakov						   other. */
1570aa261f549d7652258331ebb12795f3bc4395d213Andi Kleen	.error_remove_page = generic_error_remove_page,
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NTFS_RW
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mark_ntfs_record_dirty - mark an ntfs record dirty
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @page:	page containing the ntfs record to mark dirty
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ofs:	byte offset within @page at which the ntfs record begins
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the buffers and the page in which the ntfs record is located dirty.
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The latter also marks the vfs inode the ntfs record belongs to dirty
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (I_DIRTY_PAGES only).
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the page does not have buffers, we create them and set them uptodate.
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The page may not be locked which is why we need to handle the buffers under
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the mapping->private_lock.  Once the buffers are marked dirty we no longer
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need the lock since try_to_free_buffers() does not free dirty buffers.
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) {
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct address_space *mapping = page->mapping;
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ntfs_inode *ni = NTFS_I(mapping->host);
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct buffer_head *bh, *head, *buffers_to_free = NULL;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int end, bh_size, bh_ofs;
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(!PageUptodate(page));
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	end = ofs + ni->itype.index.block_size;
159878af34f03d33d2ba179c9d35685860170b94a285Anton Altaparmakov	bh_size = VFS_I(ni)->i_sb->s_blocksize;
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&mapping->private_lock);
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(!page_has_buffers(page))) {
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&mapping->private_lock);
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh = head = alloc_page_buffers(page, bh_size, 1);
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock(&mapping->private_lock);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (likely(!page_has_buffers(page))) {
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct buffer_head *tail;
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			do {
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				set_buffer_uptodate(bh);
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tail = bh;
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bh = bh->b_this_page;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} while (bh);
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tail->b_this_page = head;
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			attach_page_buffers(page, head);
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			buffers_to_free = bh;
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bh = head = page_buffers(page);
1618a01ac532b519dc0e0b4d8bc4e12373e4e4cd1b1aAnton Altaparmakov	BUG_ON(!bh);
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bh_ofs = bh_offset(bh);
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (bh_ofs + bh_size <= ofs)
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unlikely(bh_ofs >= end))
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_buffer_dirty(bh);
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while ((bh = bh->b_this_page) != head);
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&mapping->private_lock);
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__set_page_dirty_nobuffers(page);
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(buffers_to_free)) {
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do {
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bh = buffers_to_free->b_this_page;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_buffer_head(buffers_to_free);
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			buffers_to_free = bh;
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (buffers_to_free);
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* NTFS_RW */
1639