]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ntfs/aops.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / fs / ntfs / aops.c
index 6e5c2534f4bc806b965957254a6bea80af646c62..00e9ccde8e42b787724bee44aedc432df37e7875 100644 (file)
@@ -2,7 +2,7 @@
  * aops.c - NTFS kernel address space operations and page cache handling.
  *         Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2006 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
  * Copyright (c) 2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -87,13 +87,17 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
                /* Check for the current buffer head overflowing. */
                if (unlikely(file_ofs + bh->b_size > init_size)) {
                        int ofs;
+                       void *kaddr;
 
                        ofs = 0;
                        if (file_ofs < init_size)
                                ofs = init_size - file_ofs;
                        local_irq_save(flags);
-                       zero_user_page(page, bh_offset(bh) + ofs,
-                                        bh->b_size - ofs, KM_BIO_SRC_IRQ);
+                       kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+                       memset(kaddr + bh_offset(bh) + ofs, 0,
+                                       bh->b_size - ofs);
+                       flush_dcache_page(page);
+                       kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
                        local_irq_restore(flags);
                }
        } else {
@@ -334,7 +338,7 @@ handle_hole:
                bh->b_blocknr = -1UL;
                clear_buffer_mapped(bh);
 handle_zblock:
-               zero_user_page(page, i * blocksize, blocksize, KM_USER0);
+               zero_user(page, i * blocksize, blocksize);
                if (likely(!err))
                        set_buffer_uptodate(bh);
        } while (i++, iblock++, (bh = bh->b_this_page) != head);
@@ -396,7 +400,7 @@ static int ntfs_readpage(struct file *file, struct page *page)
        loff_t i_size;
        struct inode *vi;
        ntfs_inode *ni, *base_ni;
-       u8 *kaddr;
+       u8 *addr;
        ntfs_attr_search_ctx *ctx;
        MFT_RECORD *mrec;
        unsigned long flags;
@@ -405,6 +409,15 @@ static int ntfs_readpage(struct file *file, struct page *page)
 
 retry_readpage:
        BUG_ON(!PageLocked(page));
+       vi = page->mapping->host;
+       i_size = i_size_read(vi);
+       /* Is the page fully outside i_size? (truncate in progress) */
+       if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
+                       PAGE_CACHE_SHIFT)) {
+               zero_user(page, 0, PAGE_CACHE_SIZE);
+               ntfs_debug("Read outside i_size - truncated?");
+               goto done;
+       }
        /*
         * This can potentially happen because we clear PageUptodate() during
         * ntfs_writepage() of MstProtected() attributes.
@@ -413,7 +426,6 @@ retry_readpage:
                unlock_page(page);
                return 0;
        }
-       vi = page->mapping->host;
        ni = NTFS_I(vi);
        /*
         * Only $DATA attributes can be encrypted and only unnamed $DATA
@@ -451,7 +463,7 @@ retry_readpage:
         * ok to ignore the compressed flag here.
         */
        if (unlikely(page->index > 0)) {
-               zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+               zero_user(page, 0, PAGE_CACHE_SIZE);
                goto done;
        }
        if (!NInoAttr(ni))
@@ -491,15 +503,15 @@ retry_readpage:
                /* Race with shrinking truncate. */
                attr_len = i_size;
        }
-       kaddr = kmap_atomic(page, KM_USER0);
+       addr = kmap_atomic(page, KM_USER0);
        /* Copy the data to the page. */
-       memcpy(kaddr, (u8*)ctx->attr +
+       memcpy(addr, (u8*)ctx->attr +
                        le16_to_cpu(ctx->attr->data.resident.value_offset),
                        attr_len);
        /* Zero the remainder of the page. */
-       memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
+       memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
        flush_dcache_page(page);
-       kunmap_atomic(kaddr, KM_USER0);
+       kunmap_atomic(addr, KM_USER0);
 put_unm_err_out:
        ntfs_attr_put_search_ctx(ctx);
 unm_err_out:
@@ -780,8 +792,7 @@ lock_retry_remap:
                if (err == -ENOENT || lcn == LCN_ENOENT) {
                        bh->b_blocknr = -1;
                        clear_buffer_dirty(bh);
-                       zero_user_page(page, bh_offset(bh), blocksize,
-                                       KM_USER0);
+                       zero_user(page, bh_offset(bh), blocksize);
                        set_buffer_uptodate(bh);
                        err = 0;
                        continue;
@@ -1344,7 +1355,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
        loff_t i_size;
        struct inode *vi = page->mapping->host;
        ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi);
-       char *kaddr;
+       char *addr;
        ntfs_attr_search_ctx *ctx = NULL;
        MFT_RECORD *m = NULL;
        u32 attr_len;
@@ -1406,8 +1417,7 @@ retry_writepage:
                if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) {
                        /* The page straddles i_size. */
                        unsigned int ofs = i_size & ~PAGE_CACHE_MASK;
-                       zero_user_page(page, ofs, PAGE_CACHE_SIZE - ofs,
-                                       KM_USER0);
+                       zero_user_segment(page, ofs, PAGE_CACHE_SIZE);
                }
                /* Handle mst protected attributes. */
                if (NInoMstProtected(ni))
@@ -1484,14 +1494,14 @@ retry_writepage:
                /* Shrinking cannot fail. */
                BUG_ON(err);
        }
-       kaddr = kmap_atomic(page, KM_USER0);
+       addr = kmap_atomic(page, KM_USER0);
        /* Copy the data from the page to the mft record. */
        memcpy((u8*)ctx->attr +
                        le16_to_cpu(ctx->attr->data.resident.value_offset),
-                       kaddr, attr_len);
+                       addr, attr_len);
        /* Zero out of bounds area in the page cache page. */
-       memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
-       kunmap_atomic(kaddr, KM_USER0);
+       memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
+       kunmap_atomic(addr, KM_USER0);
        flush_dcache_page(page);
        flush_dcache_mft_record_page(ctx->ntfs_ino);
        /* We are done with the page. */