]> git.neil.brown.name Git - history.git/commitdiff
NTFS: 2.0.12 - Initial cleanup of address space operations following 2.0.11 changes.
authorAnton Altaparmakov <aia21@cantab.net>
Wed, 26 Jun 2002 13:30:15 +0000 (14:30 +0100)
committerAnton Altaparmakov <aia21@cantab.net>
Wed, 26 Jun 2002 13:30:15 +0000 (14:30 +0100)
- Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and
  fs/ntfs/aops.c::end_buffer_read_file_async() into one function
  fs/ntfs/aops.c::end_buffer_read_attr_async() using NInoMstProtected()
  to determine whether to apply mst fixups or not.
- Above change allows merging fs/ntfs/aops.c::ntfs_file_read_block()
  and fs/ntfs/aops.c::ntfs_mst_readpage() into one function
  fs/ntfs/aops.c::ntfs_attr_read_block(). Also, create a tiny wrapper
  fs/ntfs/aops.c::ntfs_mst_readpage() to transform the parameters from
  the VFS readpage function prototype to the ntfs_attr_read_block()
  function prototype.

Documentation/filesystems/ntfs.txt
fs/ntfs/ChangeLog
fs/ntfs/Makefile
fs/ntfs/aops.c
fs/ntfs/mft.c

index 78cb98c2b438e02b07cb9a8acd8f8dce258b9749..b2ee0cd9a86318cba2b4a230f97f3faed08ffc2b 100644 (file)
@@ -247,6 +247,9 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.0.12:
+       - Internal cleanups in address space operations made possible by the
+         changes introduced in the previous release.
 2.0.11:
        - Internal updates and cleanups introducing the first step towards
          fake inode based attribute i/o.
index 1c7804c61ce179f6c453f9b657fa24d59e23599c..4e3d51fee2bd0e71fe12efce8865ef140117120f 100644 (file)
@@ -6,7 +6,7 @@ ToDo:
          user open()s a file with i_size > s_maxbytes? Should read_inode()
          truncate the visible i_size? Will the user just get -E2BIG (or
          whatever) on open()? Or will (s)he be able to open() but lseek() and
-         read() will fail when s_maxbytes is reached? -> Investigate this!
+         read() will fail when s_maxbytes is reached? -> Investigate this.
        - Implement/allow non-resident index bitmaps in dir.c::ntfs_readdir()
          and then also consider initialized_size w.r.t. the bitmaps, etc.
        - vcn_to_lcn() should somehow return the correct pointer within the
@@ -17,14 +17,28 @@ ToDo:
        - Consider if ntfs_file_read_compressed_block() shouldn't be coping
          with initialized_size < data_size. I don't think it can happen but
          it requires more careful consideration.
-       - CLEANUP: Modularise and reuse code in aops.c. At the moment we have
-         several copies of almost identicall functions and the functions are
-         quite big. Modularising them a bit, e.g. a-la get_block(), will make
-         them cleaner and make code reuse easier.
+       - CLEANUP: At the moment we have two copies of almost identical
+         functions in aops.c, can merge them once fake inode address space
+         based attribute i/o is further developed.
+       - CLEANUP: Modularising code in aops.c a bit, e.g. a-la get_block(),
+         will be cleaner and make code reuse easier.
        - Enable NFS exporting of NTFS.
        - Use iget5_locked() and friends instead of conventional iget().
        - Use fake inodes for address space i/o.
 
+2.0.12 - Initial cleanup of address space operations following 2.0.11 changes.
+
+       - Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and
+         fs/ntfs/aops.c::end_buffer_read_file_async() into one function
+         fs/ntfs/aops.c::end_buffer_read_attr_async() using NInoMstProtected()
+         to determine whether to apply mst fixups or not.
+       - Above change allows merging fs/ntfs/aops.c::ntfs_file_read_block()
+         and fs/ntfs/aops.c::ntfs_mst_readpage() into one function
+         fs/ntfs/aops.c::ntfs_attr_read_block(). Also, create a tiny wrapper
+         fs/ntfs/aops.c::ntfs_mst_readpage() to transform the parameters from
+         the VFS readpage function prototype to the ntfs_attr_read_block()
+         function prototype.
+
 2.0.11 - Initial preparations for fake inode based attribute i/o.
 
        - Move definition of ntfs_inode_state_bits to fs/ntfs/inode.h and
index f89830b3ff146223b3e79a7cfdae9400b46daec3..b6211f4d9e8d984499f399648d77533fce5a0f6f 100644 (file)
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
 ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
             mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.11\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.12\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 7c20a2949e96307f06f296acaaade9d3f8f1c5d5..fc5da336ac84c52afaec5b523d0cf75035ae2fd1 100644 (file)
@@ -3,7 +3,7 @@
  *         Part of the Linux-NTFS project.
  *
  * Copyright (c) 2001,2002 Anton Altaparmakov.
- * Copyright (C) 2002 Richard Russon.
+ * Copyright (c) 2002 Richard Russon.
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
 #include "ntfs.h"
 
 /**
- * end_buffer_read_file_async -
+ * end_buffer_read_attr_async - async io completion for reading attributes
+ * @bh:                buffer head on which io is completed
+ * @uptodate:  whether @bh is now uptodate or not
  *
- * Async io completion handler for accessing files. Adapted from
- * end_buffer_read_mst_async().
+ * Asynchronous I/O completion handler for reading pages belonging to the
+ * attribute address space of an inode. The inodes can either be files or
+ * directories or they can be fake inodes describing some attribute.
+ *
+ * If NInoMstProtected(), perform the post read mst fixups when all IO on the
+ * page has been completed and mark the page uptodate or set the error bit on
+ * the page. To determine the size of the records that need fixing up, we cheat
+ * a little bit by setting the index_block_size in ntfs_inode to the ntfs
+ * record size, and index_block_size_bits, to the log(base 2) of the ntfs
+ * record size.
  */
-static void end_buffer_read_file_async(struct buffer_head *bh, int uptodate)
+static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate)
 {
        static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
        unsigned long flags;
        struct buffer_head *tmp;
        struct page *page;
+       ntfs_inode *ni;
 
-       if (uptodate)
+       if (likely(uptodate))
                set_buffer_uptodate(bh);
        else
                clear_buffer_uptodate(bh);
 
        page = bh->b_page;
 
+       ni = NTFS_I(page->mapping->host);
+
        if (likely(uptodate)) {
                s64 file_ofs;
 
-               ntfs_inode *ni = NTFS_I(page->mapping->host);
-
                file_ofs = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
+               /* Check for the current buffer head overflowing. */
                if (file_ofs + bh->b_size > ni->initialized_size) {
                        char *addr;
                        int ofs = 0;
@@ -82,10 +94,47 @@ static void end_buffer_read_file_async(struct buffer_head *bh, int uptodate)
                        SetPageError(page);
                tmp = tmp->b_this_page;
        }
-
        spin_unlock_irqrestore(&page_uptodate_lock, flags);
-       if (!PageError(page))
-               SetPageUptodate(page);
+       /*
+        * If none of the buffers had errors then we can set the page uptodate,
+        * but we first have to perform the post read mst fixups, if the
+        * attribute is mst protected, i.e. if NInoMstProteced(ni) is true.
+        */
+       if (!NInoMstProtected(ni)) {
+               if (likely(!PageError(page)))
+                       SetPageUptodate(page);
+               unlock_page(page);
+               return;
+       } else {
+               char *addr;
+               unsigned int i, recs, nr_err;
+               u32 rec_size;
+
+               rec_size = ni->_IDM(index_block_size);
+               recs = PAGE_CACHE_SIZE / rec_size;
+               addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+               for (i = nr_err = 0; i < recs; i++) {
+                       if (likely(!post_read_mst_fixup((NTFS_RECORD*)(addr +
+                                       i * rec_size), rec_size)))
+                               continue;
+                       nr_err++;
+                       ntfs_error(ni->vol->sb, "post_read_mst_fixup() failed, "
+                                       "corrupt %s record 0x%Lx. Run chkdsk.",
+                                       ni->mft_no ? "index" : "mft",
+                                       (long long)(((s64)page->index <<
+                                       PAGE_CACHE_SHIFT >>
+                                       ni->_IDM(index_block_size_bits)) + i));
+               }
+               flush_dcache_page(page);
+               kunmap_atomic(addr, KM_BIO_SRC_IRQ);
+               if (likely(!nr_err && recs))
+                       SetPageUptodate(page);
+               else {
+                       ntfs_error(ni->vol->sb, "Setting page error, index "
+                                       "0x%lx.", page->index);
+                       SetPageError(page);
+               }
+       }
        unlock_page(page);
        return;
 still_busy:
@@ -94,11 +143,20 @@ still_busy:
 }
 
 /**
- * ntfs_file_read_block -
+ * ntfs_attr_read_block - fill a @page of an address space with data
+ * @page:      page cache page to fill with data
  *
- * NTFS version of block_read_full_page(). Adapted from ntfs_mst_readpage().
+ * Fill the page @page of the address space belonging to the @page->host inode.
+ * We read each buffer asynchronously and when all buffers are read in, our io
+ * completion handler end_buffer_read_attr_async(), if required, automatically
+ * applies the mst fixups to the page before finally marking it uptodate and
+ * unlocking it.
+ *
+ * Return 0 on success and -errno on error.
+ *
+ * Contains an adapted version of fs/buffer.c::block_read_full_page().
  */
-static int ntfs_file_read_block(struct page *page)
+static int ntfs_attr_read_block(struct page *page)
 {
        VCN vcn;
        LCN lcn;
@@ -119,7 +177,7 @@ static int ntfs_file_read_block(struct page *page)
        if (!page_has_buffers(page))
                create_empty_buffers(page, blocksize, 0);
        bh = head = page_buffers(page);
-       if (!bh)
+       if (unlikely(!bh))
                return -ENOMEM;
 
        blocks = PAGE_CACHE_SIZE >> blocksize_bits;
@@ -128,11 +186,9 @@ static int ntfs_file_read_block(struct page *page)
        zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
 
 #ifdef DEBUG
-       if (unlikely(!ni->mft_no)) {
-               ntfs_error(vol->sb, "NTFS: Attempt to access $MFT! This is a "
-                               "very serious bug! Denying access...");
-               return -EACCES;
-       }
+       if (unlikely(!ni->run_list.rl && !ni->mft_no))
+               panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
+                               "very serious bug! Cannot continue...");
 #endif
 
        /* Loop through all the buffers in the page. */
@@ -211,7 +267,7 @@ handle_zblock:
                for (i = 0; i < nr; i++) {
                        struct buffer_head *tbh = arr[i];
                        lock_buffer(tbh);
-                       tbh->b_end_io = end_buffer_read_file_async;
+                       tbh->b_end_io = end_buffer_read_attr_async;
                        set_buffer_async_read(tbh);
                }
                /* Finally, start i/o on the buffers. */
@@ -220,7 +276,7 @@ handle_zblock:
                return 0;
        }
        /* No i/o was scheduled on any of the buffers. */
-       if (!PageError(page))
+       if (likely(!PageError(page)))
                SetPageUptodate(page);
        else /* Signal synchronous i/o error. */
                nr = -EIO;
@@ -234,17 +290,17 @@ handle_zblock:
  * @page:      page cache page to fill with data
  *
  * For non-resident attributes, ntfs_file_readpage() fills the @page of the open
- * file @file by calling the generic block_read_full_page() function provided by
- * the kernel which in turn invokes our ntfs_file_get_block() callback in order
- * to create and read in the buffers associated with the page asynchronously.
+ * file @file by calling the ntfs version of the generic block_read_full_page()
+ * function provided by the kernel, ntfs_attr_read_block(), which in turn
+ * creates and reads in the buffers associated with the page asynchronously.
  *
  * For resident attributes, OTOH, ntfs_file_readpage() fills @page by copying
  * the data from the mft record (which at this stage is most likely in memory)
- * and fills the remainder with zeroes. Thus, in this case I/O is synchronous,
+ * and fills the remainder with zeroes. Thus, in this case, I/O is synchronous,
  * as even if the mft record is not cached at this point in time, we need to
  * wait for it to be read in before we can do the copy.
  *
- * Return zero on success or -errno on error.
+ * Return 0 on success or -errno on error.
  */
 static int ntfs_file_readpage(struct file *file, struct page *page)
 {
@@ -256,43 +312,43 @@ static int ntfs_file_readpage(struct file *file, struct page *page)
        u32 attr_len;
        int err = 0;
 
-       if (!PageLocked(page))
+       if (unlikely(!PageLocked(page)))
                PAGE_BUG(page);
 
        ni = NTFS_I(page->mapping->host);
 
        /* Is the unnamed $DATA attribute resident? */
-       if (test_bit(NI_NonResident, &ni->state)) {
+       if (NInoNonResident(ni)) {
                /* Attribute is not resident. */
 
                /* If the file is encrypted, we deny access, just like NT4. */
-               if (test_bit(NI_Encrypted, &ni->state)) {
+               if (NInoEncrypted(ni)) {
                        err = -EACCES;
                        goto unl_err_out;
                }
                /* Compressed data stream. Handled in compress.c. */
-               if (test_bit(NI_Compressed, &ni->state))
+               if (NInoCompressed(ni))
                        return ntfs_file_read_compressed_block(page);
                /* Normal data stream. */
-               return ntfs_file_read_block(page);
+               return ntfs_attr_read_block(page);
        }
        /* Attribute is resident, implying it is not compressed or encrypted. */
 
        /* Map, pin and lock the mft record for reading. */
        mrec = map_mft_record(READ, ni);
-       if (IS_ERR(mrec)) {
+       if (unlikely(IS_ERR(mrec))) {
                err = PTR_ERR(mrec);
                goto unl_err_out;
        }
 
        ctx = get_attr_search_ctx(ni, mrec);
-       if (!ctx) {
+       if (unlikely(!ctx)) {
                err = -ENOMEM;
                goto unm_unl_err_out;
        }
 
        /* Find the data attribute in the mft record. */
-       if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) {
+       if (unlikely(!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx))) {
                err = -ENOENT;
                goto put_unm_unl_err_out;
        }
@@ -330,6 +386,25 @@ unl_err_out:
        return err;
 }
 
+/**
+ * ntfs_mst_readpage - fill a @page of the mft or a directory with data
+ * @file:      open file/directory to which the @page belongs or NULL
+ * @page:      page cache page to fill with data
+ *
+ * Readpage method for the VFS address space operations of directory inodes
+ * and the $MFT/$DATA attribute.
+ *
+ * We just call ntfs_attr_read_block() here, in fact we only need this wrapper
+ * because of the difference in function parameters.
+ */
+int ntfs_mst_readpage(struct file *file, struct page *page)
+{
+       if (unlikely(!PageLocked(page)))
+               PAGE_BUG(page);
+
+       return ntfs_attr_read_block(page);
+}
+
 /**
  * end_buffer_read_mftbmp_async -
  *
@@ -343,7 +418,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate)
        struct buffer_head *tmp;
        struct page *page;
 
-       if (uptodate)
+       if (likely(uptodate))
                set_buffer_uptodate(bh);
        else
                clear_buffer_uptodate(bh);
@@ -386,7 +461,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate)
        }
 
        spin_unlock_irqrestore(&page_uptodate_lock, flags);
-       if (!PageError(page))
+       if (likely(!PageError(page)))
                SetPageUptodate(page);
        unlock_page(page);
        return;
@@ -410,7 +485,7 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
        int nr, i;
        unsigned char blocksize_bits;
 
-       if (!PageLocked(page))
+       if (unlikely(!PageLocked(page)))
                PAGE_BUG(page);
 
        blocksize = vol->sb->s_blocksize;
@@ -419,7 +494,7 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
        if (!page_has_buffers(page))
                create_empty_buffers(page, blocksize, 0);
        bh = head = page_buffers(page);
-       if (!bh)
+       if (unlikely(!bh))
                return -ENOMEM;
 
        blocks = PAGE_CACHE_SIZE >> blocksize_bits;
@@ -503,264 +578,7 @@ handle_zblock:
                return 0;
        }
        /* No i/o was scheduled on any of the buffers. */
-       if (!PageError(page))
-               SetPageUptodate(page);
-       else /* Signal synchronous i/o error. */
-               nr = -EIO;
-       unlock_page(page);
-       return nr;
-}
-
-/**
- * end_buffer_read_mst_async - async io completion for reading index records
- * @bh:                buffer head on which io is completed
- * @uptodate:  whether @bh is now uptodate or not
- *
- * Asynchronous I/O completion handler for reading pages belonging to the
- * index allocation attribute address space of directory inodes.
- *
- * Perform the post read mst fixups when all IO on the page has been completed
- * and marks the page uptodate or sets the error bit on the page.
- *
- * Adapted from fs/buffer.c.
- *
- * NOTE: We use this function as async io completion handler for reading pages
- * belonging to the mft data attribute address space, too as this saves
- * duplicating an almost identical function. We do this by cheating a little
- * bit in setting the index_block_size in the mft ntfs_inode to the mft record
- * size of the volume (vol->mft_record_size), and index_block_size_bits to
- * mft_record_size_bits, respectively.
- */
-static void end_buffer_read_mst_async(struct buffer_head *bh, int uptodate)
-{
-       static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
-       unsigned long flags;
-       struct buffer_head *tmp;
-       struct page *page;
-       ntfs_inode *ni;
-
-       if (uptodate)
-               set_buffer_uptodate(bh);
-       else
-               clear_buffer_uptodate(bh);
-
-       page = bh->b_page;
-
-       ni = NTFS_I(page->mapping->host);
-
-       if (likely(uptodate)) {
-               s64 file_ofs;
-
-               file_ofs = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
-               /* Check for the current buffer head overflowing. */
-               if (file_ofs + bh->b_size > ni->initialized_size) {
-                       char *addr;
-                       int ofs = 0;
-
-                       if (file_ofs < ni->initialized_size)
-                               ofs = ni->initialized_size - file_ofs;
-                       addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
-                       memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs);
-                       flush_dcache_page(page);
-                       kunmap_atomic(addr, KM_BIO_SRC_IRQ);
-               }
-       } else
-               SetPageError(page);
-
-       spin_lock_irqsave(&page_uptodate_lock, flags);
-       clear_buffer_async_read(bh);
-       unlock_buffer(bh);
-
-       tmp = bh->b_this_page;
-       while (tmp != bh) {
-               if (buffer_locked(tmp)) {
-                       if (buffer_async_read(tmp))
-                               goto still_busy;
-               } else if (!buffer_uptodate(tmp))
-                       SetPageError(page);
-               tmp = tmp->b_this_page;
-       }
-
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
-       /*
-        * If none of the buffers had errors then we can set the page uptodate,
-        * but we first have to perform the post read mst fixups.
-        */
-       if (!PageError(page)) {
-               char *addr;
-               unsigned int i, recs, nr_err = 0;
-               u32 rec_size;
-
-               rec_size = ni->_IDM(index_block_size);
-               recs = PAGE_CACHE_SIZE / rec_size;
-               addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
-               for (i = 0; i < recs; i++) {
-                       if (!post_read_mst_fixup((NTFS_RECORD*)(addr +
-                                       i * rec_size), rec_size))
-                               continue;
-                       nr_err++;
-                       ntfs_error(ni->vol->sb, "post_read_mst_fixup() failed, "
-                                       "corrupt %s record 0x%Lx. Run chkdsk.",
-                                       ni->mft_no ? "index" : "mft",
-                                       (long long)((page->index <<
-                                       PAGE_CACHE_SHIFT >>
-                                       ni->_IDM(index_block_size_bits)) + i));
-               }
-               flush_dcache_page(page);
-               kunmap_atomic(addr, KM_BIO_SRC_IRQ);
-               if (likely(!nr_err && recs))
-                       SetPageUptodate(page);
-               else {
-                       ntfs_error(ni->vol->sb, "Setting page error, index "
-                                       "0x%lx.", page->index);
-                       SetPageError(page);
-               }
-       }
-       unlock_page(page);
-       return;
-still_busy:
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
-       return;
-}
-
-/**
- * ntfs_mst_readpage - fill a @page of the mft or a directory with data
- * @file:      open file/directory to which the page @page belongs or NULL
- * @page:      page cache page to fill with data
- *
- * Readpage method for the VFS address space operations.
- *
- * Fill the page @page of the $MFT or the open directory @dir. We read each
- * buffer asynchronously and when all buffers are read in our io completion
- * handler end_buffer_read_mst_async() automatically applies the mst fixups to
- * the page before finally marking it uptodate and unlocking it.
- *
- * Contains an adapted version of fs/buffer.c::block_read_full_page().
- */
-int ntfs_mst_readpage(struct file *dir, struct page *page)
-{
-       VCN vcn;
-       LCN lcn;
-       ntfs_inode *ni;
-       ntfs_volume *vol;
-       struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
-       sector_t iblock, lblock, zblock;
-       unsigned int blocksize, blocks, vcn_ofs;
-       int i, nr;
-       unsigned char blocksize_bits;
-
-       if (!PageLocked(page))
-               PAGE_BUG(page);
-
-       ni = NTFS_I(page->mapping->host);
-       vol = ni->vol;
-
-       blocksize_bits = VFS_I(ni)->i_blkbits;
-       blocksize = 1 << blocksize_bits;
-
-       if (!page_has_buffers(page))
-               create_empty_buffers(page, blocksize, 0);
-       bh = head = page_buffers(page);
-       if (!bh)
-               return -ENOMEM;
-
-       blocks = PAGE_CACHE_SIZE >> blocksize_bits;
-       iblock = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
-       lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
-       zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
-
-#ifdef DEBUG
-       if (unlikely(!ni->run_list.rl && !ni->mft_no))
-               panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
-                               "very serious bug! Cannot continue...");
-#endif
-
-       /* Loop through all the buffers in the page. */
-       nr = i = 0;
-       do {
-               if (unlikely(buffer_uptodate(bh)))
-                       continue;
-               if (unlikely(buffer_mapped(bh))) {
-                       arr[nr++] = bh;
-                       continue;
-               }
-               bh->b_bdev = vol->sb->s_bdev;
-               /* Is the block within the allowed limits? */
-               if (iblock < lblock) {
-                       BOOL is_retry = FALSE;
-
-                       /* Convert iblock into corresponding vcn and offset. */
-                       vcn = (VCN)iblock << blocksize_bits >>
-                                       vol->cluster_size_bits;
-                       vcn_ofs = ((VCN)iblock << blocksize_bits) &
-                                       vol->cluster_size_mask;
-retry_remap:
-                       /* Convert the vcn to the corresponding lcn. */
-                       down_read(&ni->run_list.lock);
-                       lcn = vcn_to_lcn(ni->run_list.rl, vcn);
-                       up_read(&ni->run_list.lock);
-                       /* Successful remap. */
-                       if (lcn >= 0) {
-                               /* Setup buffer head to correct block. */
-                               bh->b_blocknr = ((lcn << vol->cluster_size_bits)
-                                               + vcn_ofs) >> blocksize_bits;
-                               set_buffer_mapped(bh);
-                               /* Only read initialized data blocks. */
-                               if (iblock < zblock) {
-                                       arr[nr++] = bh;
-                                       continue;
-                               }
-                               /* Fully non-initialized data block, zero it. */
-                               goto handle_zblock;
-                       }
-                       /* It is a hole, need to zero it. */
-                       if (lcn == LCN_HOLE)
-                               goto handle_hole;
-                       /* If first try and run list unmapped, map and retry. */
-                       if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
-                               is_retry = TRUE;
-                               if (!map_run_list(ni, vcn))
-                                       goto retry_remap;
-                       }
-                       /* Hard error, zero out region. */
-                       SetPageError(page);
-                       ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) failed "
-                                       "with error code 0x%Lx%s.",
-                                       (long long)vcn, (long long)-lcn,
-                                       is_retry ? " even after retrying" : "");
-                       // FIXME: Depending on vol->on_errors, do something.
-               }
-               /*
-                * Either iblock was outside lblock limits or vcn_to_lcn()
-                * returned error. Just zero that portion of the page and set
-                * the buffer uptodate.
-                */
-handle_hole:
-               bh->b_blocknr = -1UL;
-               clear_buffer_mapped(bh);
-handle_zblock:
-               memset(kmap(page) + i * blocksize, 0, blocksize);
-               flush_dcache_page(page);
-               kunmap(page);
-               set_buffer_uptodate(bh);
-       } while (i++, iblock++, (bh = bh->b_this_page) != head);
-
-       /* Check we have at least one buffer ready for i/o. */
-       if (nr) {
-               /* Lock the buffers. */
-               for (i = 0; i < nr; i++) {
-                       struct buffer_head *tbh = arr[i];
-                       lock_buffer(tbh);
-                       tbh->b_end_io = end_buffer_read_mst_async;
-                       set_buffer_async_read(tbh);
-               }
-               /* Finally, start i/o on the buffers. */
-               for (i = 0; i < nr; i++)
-                       submit_bh(READ, arr[i]);
-               return 0;
-       }
-       /* No i/o was scheduled on any of the buffers. */
-       if (!PageError(page))
+       if (likely(!PageError(page)))
                SetPageUptodate(page);
        else /* Signal synchronous i/o error. */
                nr = -EIO;
index 0a8e360b4ad30ca4e3d55bb3a0befb9eaa4c39d3..bede95895c110e5e1be0c299eeab20008bea34c8 100644 (file)
@@ -102,7 +102,7 @@ extern int ntfs_mst_readpage(struct file *, struct page *);
  * ntfs_mft_aops - address space operations for access to $MFT
  *
  * Address space operations for access to $MFT. This allows us to simply use
- * read_cache_page() in map_mft_record().
+ * ntfs_map_page() in map_mft_record_page().
  */
 struct address_space_operations ntfs_mft_aops = {
        writepage:      NULL,                   /* Write dirty page to disk. */