aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2009-10-14 17:18:27 -0400
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>2010-01-19 23:32:07 -0500
commit5f3ef64f4da1c587cdcfaaac72311225b7df094c (patch)
tree0bdf086980df60d73bc650cdc520b59029faaa5a /fs
parent24bc7347da73a9ed3383056c3d0f28c0e361621e (diff)
eCryptfs: Use notify_change for truncating lower inodes
When truncating inodes in the lower filesystem, eCryptfs directly invoked vmtruncate(). As Christoph Hellwig pointed out, vmtruncate() is a filesystem helper function, but filesystems may need to do more than just a call to vmtruncate(). This patch moves the lower inode truncation out of ecryptfs_truncate() and renames the function to truncate_upper(). truncate_upper() updates an iattr for the lower inode to indicate if the lower inode needs to be truncated upon return. ecryptfs_setattr() then calls notify_change(), using the updated iattr for the lower inode, to complete the truncation. For eCryptfs functions needing to truncate, ecryptfs_truncate() is reintroduced as a simple way to truncate the upper inode to a specified size and then truncate the lower inode accordingly. https://bugs.launchpad.net/bugs/451368 Reported-by: Christoph Hellwig <hch@lst.de> Acked-by: Dustin Kirkland <kirkland@canonical.com> Cc: ecryptfs-devel@lists.launchpad.net Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/inode.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7f8545032930..2b449d79b7fa 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -772,18 +772,23 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
772} 772}
773 773
774/** 774/**
775 * ecryptfs_truncate 775 * truncate_upper
776 * @dentry: The ecryptfs layer dentry 776 * @dentry: The ecryptfs layer dentry
777 * @new_length: The length to expand the file to 777 * @ia: Address of the ecryptfs inode's attributes
778 * @lower_ia: Address of the lower inode's attributes
778 * 779 *
779 * Function to handle truncations modifying the size of the file. Note 780 * Function to handle truncations modifying the size of the file. Note
780 * that the file sizes are interpolated. When expanding, we are simply 781 * that the file sizes are interpolated. When expanding, we are simply
781 * writing strings of 0's out. When truncating, we need to modify the 782 * writing strings of 0's out. When truncating, we truncate the upper
782 * underlying file size according to the page index interpolations. 783 * inode and update the lower_ia according to the page index
784 * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return,
785 * the caller must use lower_ia in a call to notify_change() to perform
786 * the truncation of the lower inode.
783 * 787 *
784 * Returns zero on success; non-zero otherwise 788 * Returns zero on success; non-zero otherwise
785 */ 789 */
786int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) 790static int truncate_upper(struct dentry *dentry, struct iattr *ia,
791 struct iattr *lower_ia)
787{ 792{
788 int rc = 0; 793 int rc = 0;
789 struct inode *inode = dentry->d_inode; 794 struct inode *inode = dentry->d_inode;
@@ -794,8 +799,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
794 loff_t lower_size_before_truncate; 799 loff_t lower_size_before_truncate;
795 loff_t lower_size_after_truncate; 800 loff_t lower_size_after_truncate;
796 801
797 if (unlikely((new_length == i_size))) 802 if (unlikely((ia->ia_size == i_size))) {
803 lower_ia->ia_valid &= ~ATTR_SIZE;
798 goto out; 804 goto out;
805 }
799 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; 806 crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
800 /* Set up a fake ecryptfs file, this is used to interface with 807 /* Set up a fake ecryptfs file, this is used to interface with
801 * the file in the underlying filesystem so that the 808 * the file in the underlying filesystem so that the
@@ -815,28 +822,30 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
815 &fake_ecryptfs_file, 822 &fake_ecryptfs_file,
816 ecryptfs_inode_to_private(dentry->d_inode)->lower_file); 823 ecryptfs_inode_to_private(dentry->d_inode)->lower_file);
817 /* Switch on growing or shrinking file */ 824 /* Switch on growing or shrinking file */
818 if (new_length > i_size) { 825 if (ia->ia_size > i_size) {
819 char zero[] = { 0x00 }; 826 char zero[] = { 0x00 };
820 827
828 lower_ia->ia_valid &= ~ATTR_SIZE;
821 /* Write a single 0 at the last position of the file; 829 /* Write a single 0 at the last position of the file;
822 * this triggers code that will fill in 0's throughout 830 * this triggers code that will fill in 0's throughout
823 * the intermediate portion of the previous end of the 831 * the intermediate portion of the previous end of the
824 * file and the new and of the file */ 832 * file and the new and of the file */
825 rc = ecryptfs_write(&fake_ecryptfs_file, zero, 833 rc = ecryptfs_write(&fake_ecryptfs_file, zero,
826 (new_length - 1), 1); 834 (ia->ia_size - 1), 1);
827 } else { /* new_length < i_size_read(inode) */ 835 } else { /* ia->ia_size < i_size_read(inode) */
828 /* We're chopping off all the pages down do the page 836 /* We're chopping off all the pages down to the page
829 * in which new_length is located. Fill in the end of 837 * in which ia->ia_size is located. Fill in the end of
830 * that page from (new_length & ~PAGE_CACHE_MASK) to 838 * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to
831 * PAGE_CACHE_SIZE with zeros. */ 839 * PAGE_CACHE_SIZE with zeros. */
832 size_t num_zeros = (PAGE_CACHE_SIZE 840 size_t num_zeros = (PAGE_CACHE_SIZE
833 - (new_length & ~PAGE_CACHE_MASK)); 841 - (ia->ia_size & ~PAGE_CACHE_MASK));
834 842
835 if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 843 if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
836 rc = vmtruncate(inode, new_length); 844 rc = vmtruncate(inode, ia->ia_size);
837 if (rc) 845 if (rc)
838 goto out_free; 846 goto out_free;
839 rc = vmtruncate(lower_dentry->d_inode, new_length); 847 lower_ia->ia_size = ia->ia_size;
848 lower_ia->ia_valid |= ATTR_SIZE;
840 goto out_free; 849 goto out_free;
841 } 850 }
842 if (num_zeros) { 851 if (num_zeros) {
@@ -848,7 +857,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
848 goto out_free; 857 goto out_free;
849 } 858 }
850 rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, 859 rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt,
851 new_length, num_zeros); 860 ia->ia_size, num_zeros);
852 kfree(zeros_virt); 861 kfree(zeros_virt);
853 if (rc) { 862 if (rc) {
854 printk(KERN_ERR "Error attempting to zero out " 863 printk(KERN_ERR "Error attempting to zero out "
@@ -857,7 +866,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
857 goto out_free; 866 goto out_free;
858 } 867 }
859 } 868 }
860 vmtruncate(inode, new_length); 869 vmtruncate(inode, ia->ia_size);
861 rc = ecryptfs_write_inode_size_to_metadata(inode); 870 rc = ecryptfs_write_inode_size_to_metadata(inode);
862 if (rc) { 871 if (rc) {
863 printk(KERN_ERR "Problem with " 872 printk(KERN_ERR "Problem with "
@@ -870,10 +879,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
870 lower_size_before_truncate = 879 lower_size_before_truncate =
871 upper_size_to_lower_size(crypt_stat, i_size); 880 upper_size_to_lower_size(crypt_stat, i_size);
872 lower_size_after_truncate = 881 lower_size_after_truncate =
873 upper_size_to_lower_size(crypt_stat, new_length); 882 upper_size_to_lower_size(crypt_stat, ia->ia_size);
874 if (lower_size_after_truncate < lower_size_before_truncate) 883 if (lower_size_after_truncate < lower_size_before_truncate) {
875 vmtruncate(lower_dentry->d_inode, 884 lower_ia->ia_size = lower_size_after_truncate;
876 lower_size_after_truncate); 885 lower_ia->ia_valid |= ATTR_SIZE;
886 } else
887 lower_ia->ia_valid &= ~ATTR_SIZE;
877 } 888 }
878out_free: 889out_free:
879 if (ecryptfs_file_to_private(&fake_ecryptfs_file)) 890 if (ecryptfs_file_to_private(&fake_ecryptfs_file))
@@ -883,6 +894,33 @@ out:
883 return rc; 894 return rc;
884} 895}
885 896
897/**
898 * ecryptfs_truncate
899 * @dentry: The ecryptfs layer dentry
900 * @new_length: The length to expand the file to
901 *
902 * Simple function that handles the truncation of an eCryptfs inode and
903 * its corresponding lower inode.
904 *
905 * Returns zero on success; non-zero otherwise
906 */
907int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
908{
909 struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length };
910 struct iattr lower_ia = { .ia_valid = 0 };
911 int rc;
912
913 rc = truncate_upper(dentry, &ia, &lower_ia);
914 if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
915 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
916
917 mutex_lock(&lower_dentry->d_inode->i_mutex);
918 rc = notify_change(lower_dentry, &lower_ia);
919 mutex_unlock(&lower_dentry->d_inode->i_mutex);
920 }
921 return rc;
922}
923
886static int 924static int
887ecryptfs_permission(struct inode *inode, int mask) 925ecryptfs_permission(struct inode *inode, int mask)
888{ 926{
@@ -905,6 +943,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
905{ 943{
906 int rc = 0; 944 int rc = 0;
907 struct dentry *lower_dentry; 945 struct dentry *lower_dentry;
946 struct iattr lower_ia;
908 struct inode *inode; 947 struct inode *inode;
909 struct inode *lower_inode; 948 struct inode *lower_inode;
910 struct ecryptfs_crypt_stat *crypt_stat; 949 struct ecryptfs_crypt_stat *crypt_stat;
@@ -943,15 +982,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
943 } 982 }
944 } 983 }
945 mutex_unlock(&crypt_stat->cs_mutex); 984 mutex_unlock(&crypt_stat->cs_mutex);
985 memcpy(&lower_ia, ia, sizeof(lower_ia));
986 if (ia->ia_valid & ATTR_FILE)
987 lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
946 if (ia->ia_valid & ATTR_SIZE) { 988 if (ia->ia_valid & ATTR_SIZE) {
947 ecryptfs_printk(KERN_DEBUG, 989 rc = truncate_upper(dentry, ia, &lower_ia);
948 "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n",
949 ia->ia_valid, ATTR_SIZE);
950 rc = ecryptfs_truncate(dentry, ia->ia_size);
951 /* ecryptfs_truncate handles resizing of the lower file */
952 ia->ia_valid &= ~ATTR_SIZE;
953 ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n",
954 ia->ia_valid);
955 if (rc < 0) 990 if (rc < 0)
956 goto out; 991 goto out;
957 } 992 }
@@ -960,11 +995,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
960 * mode change is for clearing setuid/setgid bits. Allow lower fs 995 * mode change is for clearing setuid/setgid bits. Allow lower fs
961 * to interpret this in its own way. 996 * to interpret this in its own way.
962 */ 997 */
963 if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) 998 if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
964 ia->ia_valid &= ~ATTR_MODE; 999 lower_ia.ia_valid &= ~ATTR_MODE;
965 1000
966 mutex_lock(&lower_dentry->d_inode->i_mutex); 1001 mutex_lock(&lower_dentry->d_inode->i_mutex);
967 rc = notify_change(lower_dentry, ia); 1002 rc = notify_change(lower_dentry, &lower_ia);
968 mutex_unlock(&lower_dentry->d_inode->i_mutex); 1003 mutex_unlock(&lower_dentry->d_inode->i_mutex);
969out: 1004out:
970 fsstack_copy_attr_all(inode, lower_inode); 1005 fsstack_copy_attr_all(inode, lower_inode);