diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:28:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:12 -0400 |
commit | 2ed92554abc5c40d4450f9869c9565a1919a9242 (patch) | |
tree | 3b9be8b86474ad61d357990185476fc56ac2f490 /fs/ecryptfs/inode.c | |
parent | d7cdc5febf9f2664755002c3a2f84bd348389fe9 (diff) |
eCryptfs: make open, truncate, and setattr use persistent file
Rather than open a new lower file for every eCryptfs file that is opened,
truncated, or setattr'd, instead use the existing lower persistent file for
the eCryptfs inode. Change truncate to use read_write.c functions. Change
ecryptfs_getxattr() to use the common ecryptfs_getxattr_lower() function.
Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r-- | fs/ecryptfs/inode.c | 113 |
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); | ||
835 | out_fput: | ||
836 | rc = ecryptfs_close_lower_file(lower_file); | ||
837 | if (rc) | ||
838 | printk(KERN_ERR "Error closing lower_file\n"); | ||
839 | out_free: | 822 | out_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 | |||
995 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | 962 | ecryptfs_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); | ||
1010 | out: | ||
1011 | return rc; | ||
1012 | } | 967 | } |
1013 | 968 | ||
1014 | static ssize_t | 969 | static ssize_t |