drm/nouveau: off by one in init_i2c_device_find()
[safe/jmp/linux-2.6] / fs / ecryptfs / mmap.c
index 46cec2b..b1d8275 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/file.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
+#include <linux/slab.h>
 #include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
  * Returns locked and up-to-date page (if ok), with increased
  * refcnt.
  */
-struct page *ecryptfs_get_locked_page(struct file *file, loff_t index)
+struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index)
 {
-       struct dentry *dentry;
-       struct inode *inode;
-       struct address_space *mapping;
-       struct page *page;
-
-       dentry = file->f_path.dentry;
-       inode = dentry->d_inode;
-       mapping = inode->i_mapping;
-       page = read_mapping_page(mapping, index, (void *)file);
+       struct page *page = read_mapping_page(inode->i_mapping, index, NULL);
        if (!IS_ERR(page))
                lock_page(page);
        return page;
@@ -82,6 +75,19 @@ out:
        return rc;
 }
 
+static void strip_xattr_flag(char *page_virt,
+                            struct ecryptfs_crypt_stat *crypt_stat)
+{
+       if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
+               size_t written;
+
+               crypt_stat->flags &= ~ECRYPTFS_METADATA_IN_XATTR;
+               ecryptfs_write_crypt_stat_flags(page_virt, crypt_stat,
+                                               &written);
+               crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+       }
+}
+
 /**
  *   Header Extent:
  *     Octets 0-7:        Unencrypted file size (big-endian)
@@ -97,19 +103,6 @@ out:
  *                        (big-endian)
  *     Octet  26:         Begin RFC 2440 authentication token packet set
  */
-static void set_header_info(char *page_virt,
-                           struct ecryptfs_crypt_stat *crypt_stat)
-{
-       size_t written;
-       size_t save_num_header_bytes_at_front =
-               crypt_stat->num_header_bytes_at_front;
-
-       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_bytes_at_front =
-               save_num_header_bytes_at_front;
-}
 
 /**
  * ecryptfs_copy_up_encrypted_with_header
@@ -135,8 +128,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                                           * 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);
+                       (crypt_stat->metadata_size / crypt_stat->extent_size);
 
                if (view_extent_num < num_header_extents_at_front) {
                        /* This is a header extent */
@@ -146,9 +138,14 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        memset(page_virt, 0, PAGE_CACHE_SIZE);
                        /* TODO: Support more than one header extent */
                        if (view_extent_num == 0) {
+                               size_t written;
+
                                rc = ecryptfs_read_xattr_region(
                                        page_virt, page->mapping->host);
-                               set_header_info(page_virt, crypt_stat);
+                               strip_xattr_flag(page_virt + 16, crypt_stat);
+                               ecryptfs_write_header_metadata(page_virt + 20,
+                                                              crypt_stat,
+                                                              &written);
                        }
                        kunmap_atomic(page_virt, KM_USER0);
                        flush_dcache_page(page);
@@ -161,7 +158,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        /* This is an encrypted data extent */
                        loff_t lower_offset =
                                ((view_extent_num * crypt_stat->extent_size)
-                                - crypt_stat->num_header_bytes_at_front);
+                                - crypt_stat->metadata_size);
 
                        rc = ecryptfs_read_lower_page_segment(
                                page, (lower_offset >> PAGE_CACHE_SHIFT),
@@ -193,7 +190,7 @@ out:
 static int ecryptfs_readpage(struct file *file, struct page *page)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat;
        int rc = 0;
 
        if (!crypt_stat
@@ -295,8 +292,7 @@ static int ecryptfs_write_begin(struct file *file,
 
        if (!PageUptodate(page)) {
                struct ecryptfs_crypt_stat *crypt_stat =
-                       &ecryptfs_inode_to_private(
-                               file->f_path.dentry->d_inode)->crypt_stat;
+                       &ecryptfs_inode_to_private(mapping->host)->crypt_stat;
 
                if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
                    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
@@ -396,9 +392,11 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
        rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
                                  sizeof(u64));
        kfree(file_size_virt);
-       if (rc)
+       if (rc < 0)
                printk(KERN_ERR "%s: Error writing file size to header; "
                       "rc = [%d]\n", __func__, rc);
+       else
+               rc = 0;
 out:
        return rc;
 }
@@ -449,6 +447,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
@@ -479,7 +478,7 @@ static int ecryptfs_write_end(struct file *file,
        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;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        int rc;
 
        if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
@@ -490,6 +489,16 @@ static int ecryptfs_write_end(struct file *file,
                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", 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) {
@@ -534,7 +543,7 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
        return rc;
 }
 
-struct address_space_operations ecryptfs_aops = {
+const struct address_space_operations ecryptfs_aops = {
        .writepage = ecryptfs_writepage,
        .readpage = ecryptfs_readpage,
        .write_begin = ecryptfs_write_begin,