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