aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs/mmap.c')
-rw-r--r--fs/ecryptfs/mmap.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 0af3aa3b4b3e..ba3650d03c48 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -6,7 +6,7 @@
6 * 6 *
7 * Copyright (C) 1997-2003 Erez Zadok 7 * Copyright (C) 1997-2003 Erez Zadok
8 * Copyright (C) 2001-2003 Stony Brook University 8 * Copyright (C) 2001-2003 Stony Brook University
9 * Copyright (C) 2004-2006 International Business Machines Corp. 9 * Copyright (C) 2004-2007 International Business Machines Corp.
10 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> 10 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
@@ -308,6 +308,9 @@ out:
308 return rc; 308 return rc;
309} 309}
310 310
311/**
312 * Called with lower inode mutex held.
313 */
311static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) 314static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
312{ 315{
313 struct inode *inode = page->mapping->host; 316 struct inode *inode = page->mapping->host;
@@ -407,10 +410,9 @@ static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
407 * 410 *
408 * Returns zero on success; non-zero on error. 411 * Returns zero on success; non-zero on error.
409 */ 412 */
410int 413static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
411ecryptfs_write_inode_size_to_header(struct file *lower_file, 414 struct inode *lower_inode,
412 struct inode *lower_inode, 415 struct inode *inode)
413 struct inode *inode)
414{ 416{
415 int rc = 0; 417 int rc = 0;
416 struct page *header_page; 418 struct page *header_page;
@@ -442,6 +444,80 @@ out:
442 return rc; 444 return rc;
443} 445}
444 446
447static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
448 struct inode *inode,
449 struct dentry *ecryptfs_dentry,
450 int lower_i_mutex_held)
451{
452 ssize_t size;
453 void *xattr_virt;
454 struct dentry *lower_dentry;
455 u64 file_size;
456 int rc;
457
458 xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
459 if (!xattr_virt) {
460 printk(KERN_ERR "Out of memory whilst attempting to write "
461 "inode size to xattr\n");
462 rc = -ENOMEM;
463 goto out;
464 }
465 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
466 if (!lower_dentry->d_inode->i_op->getxattr) {
467 printk(KERN_WARNING
468 "No support for setting xattr in lower filesystem\n");
469 rc = -ENOSYS;
470 kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
471 goto out;
472 }
473 if (!lower_i_mutex_held)
474 mutex_lock(&lower_dentry->d_inode->i_mutex);
475 size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
476 ECRYPTFS_XATTR_NAME,
477 xattr_virt,
478 PAGE_CACHE_SIZE);
479 if (!lower_i_mutex_held)
480 mutex_unlock(&lower_dentry->d_inode->i_mutex);
481 if (size < 0)
482 size = 8;
483 file_size = (u64)i_size_read(inode);
484 file_size = cpu_to_be64(file_size);
485 memcpy(xattr_virt, &file_size, sizeof(u64));
486 if (!lower_i_mutex_held)
487 mutex_lock(&lower_dentry->d_inode->i_mutex);
488 rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
489 ECRYPTFS_XATTR_NAME,
490 xattr_virt, size, 0);
491 if (!lower_i_mutex_held)
492 mutex_unlock(&lower_dentry->d_inode->i_mutex);
493 if (rc)
494 printk(KERN_ERR "Error whilst attempting to write inode size "
495 "to lower file xattr; rc = [%d]\n", rc);
496 kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
497out:
498 return rc;
499}
500
501int
502ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
503 struct inode *lower_inode,
504 struct inode *inode,
505 struct dentry *ecryptfs_dentry,
506 int lower_i_mutex_held)
507{
508 struct ecryptfs_crypt_stat *crypt_stat;
509
510 crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
511 if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
512 return ecryptfs_write_inode_size_to_xattr(lower_inode, inode,
513 ecryptfs_dentry,
514 lower_i_mutex_held);
515 else
516 return ecryptfs_write_inode_size_to_header(lower_file,
517 lower_inode,
518 inode);
519}
520
445int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, 521int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
446 struct file *lower_file, 522 struct file *lower_file,
447 unsigned long lower_page_index, int byte_offset, 523 unsigned long lower_page_index, int byte_offset,
@@ -528,6 +604,8 @@ out:
528 return rc; 604 return rc;
529} 605}
530 606
607struct kmem_cache *ecryptfs_xattr_cache;
608
531/** 609/**
532 * ecryptfs_commit_write 610 * ecryptfs_commit_write
533 * @file: The eCryptfs file object 611 * @file: The eCryptfs file object
@@ -581,7 +659,6 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
581 "index [0x%.16x])\n", page->index); 659 "index [0x%.16x])\n", page->index);
582 goto out; 660 goto out;
583 } 661 }
584 rc = 0;
585 inode->i_blocks = lower_inode->i_blocks; 662 inode->i_blocks = lower_inode->i_blocks;
586 pos = (page->index << PAGE_CACHE_SHIFT) + to; 663 pos = (page->index << PAGE_CACHE_SHIFT) + to;
587 if (pos > i_size_read(inode)) { 664 if (pos > i_size_read(inode)) {
@@ -589,7 +666,12 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
589 ecryptfs_printk(KERN_DEBUG, "Expanded file size to " 666 ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
590 "[0x%.16x]\n", i_size_read(inode)); 667 "[0x%.16x]\n", i_size_read(inode));
591 } 668 }
592 ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); 669 rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
670 inode, file->f_dentry,
671 ECRYPTFS_LOWER_I_MUTEX_HELD);
672 if (rc)
673 printk(KERN_ERR "Error writing inode size to metadata; "
674 "rc = [%d]\n", rc);
593 lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; 675 lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
594 mark_inode_dirty_sync(inode); 676 mark_inode_dirty_sync(inode);
595out: 677out: