aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r--fs/ecryptfs/inode.c113
1 files changed, 34 insertions, 79 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index a29dc31965fa..5701f816faf4 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -739,8 +739,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
739 int rc = 0; 739 int rc = 0;
740 struct inode *inode = dentry->d_inode; 740 struct inode *inode = dentry->d_inode;
741 struct dentry *lower_dentry; 741 struct dentry *lower_dentry;
742 struct vfsmount *lower_mnt; 742 struct file fake_ecryptfs_file;
743 struct file fake_ecryptfs_file, *lower_file = NULL;
744 struct ecryptfs_crypt_stat *crypt_stat; 743 struct ecryptfs_crypt_stat *crypt_stat;
745 loff_t i_size = i_size_read(inode); 744 loff_t i_size = i_size_read(inode);
746 loff_t lower_size_before_truncate; 745 loff_t lower_size_before_truncate;
@@ -763,51 +762,43 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
763 goto out; 762 goto out;
764 } 763 }
765 lower_dentry = ecryptfs_dentry_to_lower(dentry); 764 lower_dentry = ecryptfs_dentry_to_lower(dentry);
766 /* This dget & mntget is released through fput at out_fput: */ 765 ecryptfs_set_file_lower(
767 lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); 766 &fake_ecryptfs_file,
768 rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, 767 ecryptfs_inode_to_private(dentry->d_inode)->lower_file);
769 O_RDWR);
770 if (rc) {
771 ecryptfs_printk(KERN_ERR,
772 "Error opening dentry; rc = [%i]\n", rc);
773 goto out_free;
774 }
775 ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file);
776 /* Switch on growing or shrinking file */ 768 /* Switch on growing or shrinking file */
777 if (new_length > i_size) { 769 if (new_length > i_size) {
778 rc = ecryptfs_fill_zeros(&fake_ecryptfs_file, new_length); 770 char zero[] = { 0x00 };
779 if (rc) { 771
780 ecryptfs_printk(KERN_ERR, 772 /* Write a single 0 at the last position of the file;
781 "Problem with fill_zeros\n"); 773 * this triggers code that will fill in 0's throughout
782 goto out_fput; 774 * the intermediate portion of the previous end of the
783 } 775 * file and the new and of the file */
784 i_size_write(inode, new_length); 776 rc = ecryptfs_write(&fake_ecryptfs_file, zero,
785 rc = ecryptfs_write_inode_size_to_metadata(inode); 777 (new_length - 1), 1);
786 if (rc) {
787 printk(KERN_ERR "Problem with "
788 "ecryptfs_write_inode_size_to_metadata; "
789 "rc = [%d]\n", rc);
790 goto out_fput;
791 }
792 } else { /* new_length < i_size_read(inode) */ 778 } else { /* new_length < i_size_read(inode) */
793 pgoff_t index = 0; 779 /* We're chopping off all the pages down do the page
794 int end_pos_in_page = -1; 780 * in which new_length is located. Fill in the end of
795 781 * that page from (new_length & ~PAGE_CACHE_MASK) to
796 if (new_length != 0) { 782 * PAGE_CACHE_SIZE with zeros. */
797 index = ((new_length - 1) >> PAGE_CACHE_SHIFT); 783 size_t num_zeros = (PAGE_CACHE_SIZE
798 end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK); 784 - (new_length & ~PAGE_CACHE_MASK));
799 } 785
800 if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) { 786 if (num_zeros) {
801 rc = ecryptfs_write_zeros(&fake_ecryptfs_file, 787 char *zeros_virt;
802 index, 788
803 (end_pos_in_page + 1), 789 zeros_virt = kzalloc(num_zeros, GFP_KERNEL);
804 ((PAGE_CACHE_SIZE - 1) 790 if (!zeros_virt) {
805 - end_pos_in_page)); 791 rc = -ENOMEM;
792 goto out_free;
793 }
794 rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt,
795 new_length, num_zeros);
796 kfree(zeros_virt);
806 if (rc) { 797 if (rc) {
807 printk(KERN_ERR "Error attempting to zero out " 798 printk(KERN_ERR "Error attempting to zero out "
808 "the remainder of the end page on " 799 "the remainder of the end page on "
809 "reducing truncate; rc = [%d]\n", rc); 800 "reducing truncate; rc = [%d]\n", rc);
810 goto out_fput; 801 goto out_free;
811 } 802 }
812 } 803 }
813 vmtruncate(inode, new_length); 804 vmtruncate(inode, new_length);
@@ -816,7 +807,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
816 printk(KERN_ERR "Problem with " 807 printk(KERN_ERR "Problem with "
817 "ecryptfs_write_inode_size_to_metadata; " 808 "ecryptfs_write_inode_size_to_metadata; "
818 "rc = [%d]\n", rc); 809 "rc = [%d]\n", rc);
819 goto out_fput; 810 goto out_free;
820 } 811 }
821 /* We are reducing the size of the ecryptfs file, and need to 812 /* We are reducing the size of the ecryptfs file, and need to
822 * know if we need to reduce the size of the lower file. */ 813 * know if we need to reduce the size of the lower file. */
@@ -828,14 +819,6 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
828 vmtruncate(lower_dentry->d_inode, 819 vmtruncate(lower_dentry->d_inode,
829 lower_size_after_truncate); 820 lower_size_after_truncate);
830 } 821 }
831 /* Update the access times */
832 lower_dentry->d_inode->i_mtime = lower_dentry->d_inode->i_ctime
833 = CURRENT_TIME;
834 mark_inode_dirty_sync(inode);
835out_fput:
836 rc = ecryptfs_close_lower_file(lower_file);
837 if (rc)
838 printk(KERN_ERR "Error closing lower_file\n");
839out_free: 822out_free:
840 if (ecryptfs_file_to_private(&fake_ecryptfs_file)) 823 if (ecryptfs_file_to_private(&fake_ecryptfs_file))
841 kmem_cache_free(ecryptfs_file_info_cache, 824 kmem_cache_free(ecryptfs_file_info_cache,
@@ -895,21 +878,8 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
895 else if (S_ISREG(dentry->d_inode->i_mode) 878 else if (S_ISREG(dentry->d_inode->i_mode)
896 && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) 879 && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
897 || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) { 880 || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {
898 struct vfsmount *lower_mnt;
899 struct file *lower_file = NULL;
900 struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 881 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
901 int lower_flags;
902 882
903 lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
904 lower_flags = O_RDONLY;
905 rc = ecryptfs_open_lower_file(&lower_file, lower_dentry,
906 lower_mnt, lower_flags);
907 if (rc) {
908 printk(KERN_ERR
909 "Error opening lower file; rc = [%d]\n", rc);
910 mutex_unlock(&crypt_stat->cs_mutex);
911 goto out;
912 }
913 mount_crypt_stat = &ecryptfs_superblock_to_private( 883 mount_crypt_stat = &ecryptfs_superblock_to_private(
914 dentry->d_sb)->mount_crypt_stat; 884 dentry->d_sb)->mount_crypt_stat;
915 rc = ecryptfs_read_metadata(dentry); 885 rc = ecryptfs_read_metadata(dentry);
@@ -923,16 +893,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
923 "enabled; returning -EIO\n"); 893 "enabled; returning -EIO\n");
924 894
925 mutex_unlock(&crypt_stat->cs_mutex); 895 mutex_unlock(&crypt_stat->cs_mutex);
926 fput(lower_file);
927 goto out; 896 goto out;
928 } 897 }
929 rc = 0; 898 rc = 0;
930 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 899 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
931 mutex_unlock(&crypt_stat->cs_mutex); 900 mutex_unlock(&crypt_stat->cs_mutex);
932 fput(lower_file);
933 goto out; 901 goto out;
934 } 902 }
935 fput(lower_file);
936 } 903 }
937 mutex_unlock(&crypt_stat->cs_mutex); 904 mutex_unlock(&crypt_stat->cs_mutex);
938 if (ia->ia_valid & ATTR_SIZE) { 905 if (ia->ia_valid & ATTR_SIZE) {
@@ -995,20 +962,8 @@ ssize_t
995ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, 962ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
996 size_t size) 963 size_t size)
997{ 964{
998 int rc = 0; 965 return ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), name,
999 struct dentry *lower_dentry; 966 value, size);
1000
1001 lower_dentry = ecryptfs_dentry_to_lower(dentry);
1002 if (!lower_dentry->d_inode->i_op->getxattr) {
1003 rc = -ENOSYS;
1004 goto out;
1005 }
1006 mutex_lock(&lower_dentry->d_inode->i_mutex);
1007 rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value,
1008 size);
1009 mutex_unlock(&lower_dentry->d_inode->i_mutex);
1010out:
1011 return rc;
1012} 967}
1013 968
1014static ssize_t 969static ssize_t