diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-06-27 17:09:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-28 14:34:53 -0400 |
commit | 240e2df5c740d73fc08cac9989872212deb2d20e (patch) | |
tree | 538dc70281c5401f3843ac8c752b2092f79ba9ee /fs/ecryptfs/inode.c | |
parent | b75ae8603568ae18f270213693758c78fb8a29ff (diff) |
eCryptfs: fix write zeros behavior
This patch fixes the processes involved in wiping regions of the data during
truncate and write events, fixing a kernel hang in 2.6.22-rc4 while assuring
that zero values are written out to the appropriate locations during events in
which the i_size will change.
The range passed to ecryptfs_truncate() from ecryptfs_prepare_write() includes
the page that is the object of ecryptfs_prepare_write(). This leads to a
kernel hang as read_cache_page() is executed on the same page in the
ecryptfs_truncate() execution path. This patch remedies this by limiting the
range passed to ecryptfs_truncate() so as to exclude the page that is the
object of ecryptfs_prepare_write(); it also adds code to
ecryptfs_prepare_write() to zero out the region of its own page when writing
past the i_size position. This patch also modifies ecryptfs_truncate() so
that when a file is truncated to a smaller size, eCryptfs will zero out the
contents of the new last page from the new size through to the end of the last
page.
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 | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 1548be26b5e..0981ae35ea1 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -800,6 +800,25 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
800 | goto out_fput; | 800 | goto out_fput; |
801 | } | 801 | } |
802 | } else { /* new_length < i_size_read(inode) */ | 802 | } else { /* new_length < i_size_read(inode) */ |
803 | pgoff_t index = 0; | ||
804 | int end_pos_in_page = -1; | ||
805 | |||
806 | if (new_length != 0) { | ||
807 | index = ((new_length - 1) >> PAGE_CACHE_SHIFT); | ||
808 | end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK); | ||
809 | } | ||
810 | if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) { | ||
811 | if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file, | ||
812 | index, | ||
813 | (end_pos_in_page + 1), | ||
814 | ((PAGE_CACHE_SIZE - 1) | ||
815 | - end_pos_in_page)))) { | ||
816 | printk(KERN_ERR "Error attempting to zero out " | ||
817 | "the remainder of the end page on " | ||
818 | "reducing truncate; rc = [%d]\n", rc); | ||
819 | goto out_fput; | ||
820 | } | ||
821 | } | ||
803 | vmtruncate(inode, new_length); | 822 | vmtruncate(inode, new_length); |
804 | rc = ecryptfs_write_inode_size_to_metadata( | 823 | rc = ecryptfs_write_inode_size_to_metadata( |
805 | lower_file, lower_dentry->d_inode, inode, dentry, | 824 | lower_file, lower_dentry->d_inode, inode, dentry, |