aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2007-10-16 04:28:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:12 -0400
commit2ed92554abc5c40d4450f9869c9565a1919a9242 (patch)
tree3b9be8b86474ad61d357990185476fc56ac2f490
parentd7cdc5febf9f2664755002c3a2f84bd348389fe9 (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>
-rw-r--r--fs/ecryptfs/crypto.c2
-rw-r--r--fs/ecryptfs/file.c50
-rw-r--r--fs/ecryptfs/inode.c113
3 files changed, 44 insertions, 121 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 55110ffe9ebd..26070d69e59a 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1673,7 +1673,7 @@ out:
1673/** 1673/**
1674 * ecryptfs_read_xattr_region 1674 * ecryptfs_read_xattr_region
1675 * @page_virt: The vitual address into which to read the xattr data 1675 * @page_virt: The vitual address into which to read the xattr data
1676 * @ecryptfs_dentry: The eCryptfs dentry 1676 * @ecryptfs_inode: The eCryptfs inode
1677 * 1677 *
1678 * Attempts to read the crypto metadata from the extended attribute 1678 * Attempts to read the crypto metadata from the extended attribute
1679 * region of the lower file. 1679 * region of the lower file.
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index df70bfa176d9..95be9a90c504 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -187,11 +187,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
187 /* Private value of ecryptfs_dentry allocated in 187 /* Private value of ecryptfs_dentry allocated in
188 * ecryptfs_lookup() */ 188 * ecryptfs_lookup() */
189 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 189 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
190 struct inode *lower_inode = NULL;
191 struct file *lower_file = NULL;
192 struct vfsmount *lower_mnt;
193 struct ecryptfs_file_info *file_info; 190 struct ecryptfs_file_info *file_info;
194 int lower_flags;
195 191
196 mount_crypt_stat = &ecryptfs_superblock_to_private( 192 mount_crypt_stat = &ecryptfs_superblock_to_private(
197 ecryptfs_dentry->d_sb)->mount_crypt_stat; 193 ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -219,26 +215,12 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
219 if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) { 215 if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
220 ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n"); 216 ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
221 /* Policy code enabled in future release */ 217 /* Policy code enabled in future release */
222 crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED; 218 crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED
223 crypt_stat->flags |= ECRYPTFS_ENCRYPTED; 219 | ECRYPTFS_ENCRYPTED);
224 } 220 }
225 mutex_unlock(&crypt_stat->cs_mutex); 221 mutex_unlock(&crypt_stat->cs_mutex);
226 lower_flags = file->f_flags; 222 ecryptfs_set_file_lower(
227 if ((lower_flags & O_ACCMODE) == O_WRONLY) 223 file, ecryptfs_inode_to_private(inode)->lower_file);
228 lower_flags = (lower_flags & O_ACCMODE) | O_RDWR;
229 if (file->f_flags & O_APPEND)
230 lower_flags &= ~O_APPEND;
231 lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
232 /* Corresponding fput() in ecryptfs_release() */
233 rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt,
234 lower_flags);
235 if (rc) {
236 ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
237 goto out_puts;
238 }
239 ecryptfs_set_file_lower(file, lower_file);
240 /* Isn't this check the same as the one in lookup? */
241 lower_inode = lower_dentry->d_inode;
242 if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { 224 if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
243 ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); 225 ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
244 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 226 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -260,7 +242,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
260 "and plaintext passthrough mode is not " 242 "and plaintext passthrough mode is not "
261 "enabled; returning -EIO\n"); 243 "enabled; returning -EIO\n");
262 mutex_unlock(&crypt_stat->cs_mutex); 244 mutex_unlock(&crypt_stat->cs_mutex);
263 goto out_puts; 245 goto out_free;
264 } 246 }
265 rc = 0; 247 rc = 0;
266 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); 248 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
@@ -272,11 +254,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
272 ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] " 254 ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] "
273 "size: [0x%.16x]\n", inode, inode->i_ino, 255 "size: [0x%.16x]\n", inode, inode->i_ino,
274 i_size_read(inode)); 256 i_size_read(inode));
275 ecryptfs_set_file_lower(file, lower_file);
276 goto out; 257 goto out;
277out_puts: 258out_free:
278 mntput(lower_mnt);
279 dput(lower_dentry);
280 kmem_cache_free(ecryptfs_file_info_cache, 259 kmem_cache_free(ecryptfs_file_info_cache,
281 ecryptfs_file_to_private(file)); 260 ecryptfs_file_to_private(file));
282out: 261out:
@@ -296,20 +275,9 @@ static int ecryptfs_flush(struct file *file, fl_owner_t td)
296 275
297static int ecryptfs_release(struct inode *inode, struct file *file) 276static int ecryptfs_release(struct inode *inode, struct file *file)
298{ 277{
299 struct file *lower_file = ecryptfs_file_to_lower(file); 278 kmem_cache_free(ecryptfs_file_info_cache,
300 struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); 279 ecryptfs_file_to_private(file));
301 struct inode *lower_inode = ecryptfs_inode_to_lower(inode); 280 return 0;
302 int rc;
303
304 rc = ecryptfs_close_lower_file(lower_file);
305 if (rc) {
306 printk(KERN_ERR "Error closing lower_file\n");
307 goto out;
308 }
309 inode->i_blocks = lower_inode->i_blocks;
310 kmem_cache_free(ecryptfs_file_info_cache, file_info);
311out:
312 return rc;
313} 281}
314 282
315static int 283static int
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