Staging: android: lowmemorykiller: remove a predefine
[safe/jmp/linux-2.6] / fs / ecryptfs / mmap.c
index 9a5e0d1..5c6bab9 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/file.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -100,13 +101,14 @@ static void set_header_info(char *page_virt,
                            struct ecryptfs_crypt_stat *crypt_stat)
 {
        size_t written;
-       int save_num_header_extents_at_front =
-               crypt_stat->num_header_extents_at_front;
+       size_t save_num_header_bytes_at_front =
+               crypt_stat->num_header_bytes_at_front;
 
-       crypt_stat->num_header_extents_at_front = 1;
+       crypt_stat->num_header_bytes_at_front =
+               ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
        ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
-       crypt_stat->num_header_extents_at_front =
-               save_num_header_extents_at_front;
+       crypt_stat->num_header_bytes_at_front =
+               save_num_header_bytes_at_front;
 }
 
 /**
@@ -132,8 +134,11 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                loff_t view_extent_num = ((((loff_t)page->index)
                                           * num_extents_per_page)
                                          + extent_num_in_page);
+               size_t num_header_extents_at_front =
+                       (crypt_stat->num_header_bytes_at_front
+                        / crypt_stat->extent_size);
 
-               if (view_extent_num < crypt_stat->num_header_extents_at_front) {
+               if (view_extent_num < num_header_extents_at_front) {
                        /* This is a header extent */
                        char *page_virt;
 
@@ -149,15 +154,14 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        flush_dcache_page(page);
                        if (rc) {
                                printk(KERN_ERR "%s: Error reading xattr "
-                                      "region; rc = [%d]\n", __FUNCTION__, rc);
+                                      "region; rc = [%d]\n", __func__, rc);
                                goto out;
                        }
                } else {
                        /* This is an encrypted data extent */
                        loff_t lower_offset =
-                               ((view_extent_num -
-                                 crypt_stat->num_header_extents_at_front)
-                                * crypt_stat->extent_size);
+                               ((view_extent_num * crypt_stat->extent_size)
+                                - crypt_stat->num_header_bytes_at_front);
 
                        rc = ecryptfs_read_lower_page_segment(
                                page, (lower_offset >> PAGE_CACHE_SHIFT),
@@ -166,7 +170,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        if (rc) {
                                printk(KERN_ERR "%s: Error attempting to read "
                                       "extent at offset [%lld] in the lower "
-                                      "file; rc = [%d]\n", __FUNCTION__,
+                                      "file; rc = [%d]\n", __func__,
                                       lower_offset, rc);
                                goto out;
                        }
@@ -209,7 +213,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
                                       "the encrypted content from the lower "
                                       "file whilst inserting the metadata "
                                       "from the xattr into the header; rc = "
-                                      "[%d]\n", __FUNCTION__, rc);
+                                      "[%d]\n", __func__, rc);
                                goto out;
                        }
 
@@ -260,52 +264,113 @@ out:
        return 0;
 }
 
-/* This function must zero any hole we create */
-static int ecryptfs_prepare_write(struct file *file, struct page *page,
-                                 unsigned from, unsigned to)
+/**
+ * ecryptfs_write_begin
+ * @file: The eCryptfs file
+ * @mapping: The eCryptfs object
+ * @pos: The file offset at which to start writing
+ * @len: Length of the write
+ * @flags: Various flags
+ * @pagep: Pointer to return the page
+ * @fsdata: Pointer to return fs data (unused)
+ *
+ * This function must zero any hole we create
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_write_begin(struct file *file,
+                       struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata)
 {
-       int rc = 0;
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+       struct page *page;
        loff_t prev_page_end_size;
+       int rc = 0;
+
+       page = grab_cache_page_write_begin(mapping, index, flags);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
 
        if (!PageUptodate(page)) {
-               rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
-                                                     PAGE_CACHE_SIZE,
-                                                     page->mapping->host);
-               if (rc) {
-                       printk(KERN_ERR "%s: Error attemping to read lower "
-                              "page segment; rc = [%d]\n", __FUNCTION__, rc);
-                       ClearPageUptodate(page);
-                       goto out;
-               } else
+               struct ecryptfs_crypt_stat *crypt_stat =
+                       &ecryptfs_inode_to_private(
+                               file->f_path.dentry->d_inode)->crypt_stat;
+
+               if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+                   || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
+                       rc = ecryptfs_read_lower_page_segment(
+                               page, index, 0, PAGE_CACHE_SIZE, mapping->host);
+                       if (rc) {
+                               printk(KERN_ERR "%s: Error attemping to read "
+                                      "lower page segment; rc = [%d]\n",
+                                      __func__, rc);
+                               ClearPageUptodate(page);
+                               goto out;
+                       } else
+                               SetPageUptodate(page);
+               } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
+                       if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
+                               rc = ecryptfs_copy_up_encrypted_with_header(
+                                       page, crypt_stat);
+                               if (rc) {
+                                       printk(KERN_ERR "%s: Error attempting "
+                                              "to copy the encrypted content "
+                                              "from the lower file whilst "
+                                              "inserting the metadata from "
+                                              "the xattr into the header; rc "
+                                              "= [%d]\n", __func__, rc);
+                                       ClearPageUptodate(page);
+                                       goto out;
+                               }
+                               SetPageUptodate(page);
+                       } else {
+                               rc = ecryptfs_read_lower_page_segment(
+                                       page, index, 0, PAGE_CACHE_SIZE,
+                                       mapping->host);
+                               if (rc) {
+                                       printk(KERN_ERR "%s: Error reading "
+                                              "page; rc = [%d]\n",
+                                              __func__, rc);
+                                       ClearPageUptodate(page);
+                                       goto out;
+                               }
+                               SetPageUptodate(page);
+                       }
+               } else {
+                       rc = ecryptfs_decrypt_page(page);
+                       if (rc) {
+                               printk(KERN_ERR "%s: Error decrypting page "
+                                      "at index [%ld]; rc = [%d]\n",
+                                      __func__, page->index, rc);
+                               ClearPageUptodate(page);
+                               goto out;
+                       }
                        SetPageUptodate(page);
+               }
        }
-
-       prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
-
-       /*
-        * If creating a page or more of holes, zero them out via truncate.
-        * Note, this will increase i_size.
-        */
-       if (page->index != 0) {
+       prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT);
+       /* If creating a page or more of holes, zero them out via truncate.
+        * Note, this will increase i_size. */
+       if (index != 0) {
                if (prev_page_end_size > i_size_read(page->mapping->host)) {
                        rc = ecryptfs_truncate(file->f_path.dentry,
                                               prev_page_end_size);
                        if (rc) {
-                               printk(KERN_ERR "Error on attempt to "
+                               printk(KERN_ERR "%s: Error on attempt to "
                                       "truncate to (higher) offset [%lld];"
-                                      " rc = [%d]\n", prev_page_end_size, rc);
+                                      " rc = [%d]\n", __func__,
+                                      prev_page_end_size, rc);
                                goto out;
                        }
                }
        }
-       /*
-        * Writing to a new page, and creating a small hole from start of page?
-        * Zero it out.
-        */
-       if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
-           (from != 0)) {
+       /* Writing to a new page, and creating a small hole from start
+        * of page?  Zero it out. */
+       if ((i_size_read(mapping->host) == prev_page_end_size)
+           && (pos != 0))
                zero_user(page, 0, PAGE_CACHE_SIZE);
-       }
 out:
        return rc;
 }
@@ -319,7 +384,6 @@ out:
  */
 static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
 {
-       u64 file_size;
        char *file_size_virt;
        int rc;
 
@@ -328,15 +392,13 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
                rc = -ENOMEM;
                goto out;
        }
-       file_size = (u64)i_size_read(ecryptfs_inode);
-       file_size = cpu_to_be64(file_size);
-       memcpy(file_size_virt, &file_size, sizeof(u64));
+       put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
        rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
                                  sizeof(u64));
        kfree(file_size_virt);
        if (rc)
                printk(KERN_ERR "%s: Error writing file size to header; "
-                      "rc = [%d]\n", __FUNCTION__, rc);
+                      "rc = [%d]\n", __func__, rc);
 out:
        return rc;
 }
@@ -350,7 +412,6 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
        struct dentry *lower_dentry =
                ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
        struct inode *lower_inode = lower_dentry->d_inode;
-       u64 file_size;
        int rc;
 
        if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
@@ -371,9 +432,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
                                           xattr_virt, PAGE_CACHE_SIZE);
        if (size < 0)
                size = 8;
-       file_size = (u64)i_size_read(ecryptfs_inode);
-       file_size = cpu_to_be64(file_size);
-       memcpy(xattr_virt, &file_size, sizeof(u64));
+       put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
        rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
                                         xattr_virt, size, 0);
        mutex_unlock(&lower_inode->i_mutex);
@@ -390,6 +449,7 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
        struct ecryptfs_crypt_stat *crypt_stat;
 
        crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
+       BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
        if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
                return ecryptfs_write_inode_size_to_xattr(ecryptfs_inode);
        else
@@ -397,21 +457,28 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
 }
 
 /**
- * ecryptfs_commit_write
+ * ecryptfs_write_end
  * @file: The eCryptfs file object
+ * @mapping: The eCryptfs object
+ * @pos: The file position
+ * @len: The length of the data (unused)
+ * @copied: The amount of data copied
  * @page: The eCryptfs page
- * @from: Ignored (we rotate the page IV on each write)
- * @to: Ignored
+ * @fsdata: The fsdata (unused)
  *
  * This is where we encrypt the data and pass the encrypted data to
  * the lower filesystem.  In OpenPGP-compatible mode, we operate on
  * entire underlying packets.
  */
-static int ecryptfs_commit_write(struct file *file, struct page *page,
-                                unsigned from, unsigned to)
+static int ecryptfs_write_end(struct file *file,
+                       struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata)
 {
-       loff_t pos;
-       struct inode *ecryptfs_inode = page->mapping->host;
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+       unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+       unsigned to = from + copied;
+       struct inode *ecryptfs_inode = mapping->host;
        struct ecryptfs_crypt_stat *crypt_stat =
                &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
        int rc;
@@ -423,25 +490,32 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
        } else
                ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
        ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
-                       "(page w/ index = [0x%.16x], to = [%d])\n", page->index,
-                       to);
+                       "(page w/ index = [0x%.16x], to = [%d])\n", index, to);
+       if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+               rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0,
+                                                      to);
+               if (!rc) {
+                       rc = copied;
+                       fsstack_copy_inode_size(ecryptfs_inode,
+                               ecryptfs_inode_to_lower(ecryptfs_inode));
+               }
+               goto out;
+       }
        /* Fills in zeros if 'to' goes beyond inode size */
        rc = fill_zeros_to_end_of_page(page, to);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
-                               "zeros in page with index = [0x%.16x]\n",
-                               page->index);
+                       "zeros in page with index = [0x%.16x]\n", index);
                goto out;
        }
        rc = ecryptfs_encrypt_page(page);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
-                               "index [0x%.16x])\n", page->index);
+                               "index [0x%.16x])\n", index);
                goto out;
        }
-       pos = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + to;
-       if (pos > i_size_read(ecryptfs_inode)) {
-               i_size_write(ecryptfs_inode, pos);
+       if (pos + copied > i_size_read(ecryptfs_inode)) {
+               i_size_write(ecryptfs_inode, pos + copied);
                ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
                                "[0x%.16x]\n", i_size_read(ecryptfs_inode));
        }
@@ -449,7 +523,11 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
        if (rc)
                printk(KERN_ERR "Error writing inode size to metadata; "
                       "rc = [%d]\n", rc);
+       else
+               rc = copied;
 out:
+       unlock_page(page);
+       page_cache_release(page);
        return rc;
 }
 
@@ -470,7 +548,7 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
 struct address_space_operations ecryptfs_aops = {
        .writepage = ecryptfs_writepage,
        .readpage = ecryptfs_readpage,
-       .prepare_write = ecryptfs_prepare_write,
-       .commit_write = ecryptfs_commit_write,
+       .write_begin = ecryptfs_write_begin,
+       .write_end = ecryptfs_write_end,
        .bmap = ecryptfs_bmap,
 };