From ae73fc093a8cae4d92e22ab8b635e3590e80785d Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Wed, 28 Feb 2007 20:12:16 -0800 Subject: [PATCH] eCryptfs: resolve lower page unlocking problem eCryptfs lower file handling code has several issues: - Retval from prepare_write()/commit_write() wasn't checked to equality to AOP_TRUNCATED_PAGE. - In some places page wasn't unmapped and unlocked after error. Signed-off-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/mmap.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'fs/ecryptfs/mmap.c') diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 3a6f65c3f14f..82bdbed658d7 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -422,9 +422,11 @@ out: return rc; } -static void ecryptfs_release_lower_page(struct page *lower_page) +static +void ecryptfs_release_lower_page(struct page *lower_page, int page_locked) { - unlock_page(lower_page); + if (page_locked) + unlock_page(lower_page); page_cache_release(lower_page); } @@ -454,6 +456,13 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, } lower_a_ops = lower_inode->i_mapping->a_ops; rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); + if (rc) { + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(header_page, 0); + else + ecryptfs_release_lower_page(header_page, 1); + goto out; + } file_size = (u64)i_size_read(inode); ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); file_size = cpu_to_be64(file_size); @@ -465,7 +474,10 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, if (rc < 0) ecryptfs_printk(KERN_ERR, "Error commiting header page " "write\n"); - ecryptfs_release_lower_page(header_page); + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(header_page, 0); + else + ecryptfs_release_lower_page(header_page, 1); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); out: @@ -572,7 +584,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, } out: if (rc && (*lower_page)) { - ecryptfs_release_lower_page(*lower_page); + if (rc == AOP_TRUNCATED_PAGE) + ecryptfs_release_lower_page(*lower_page, 0); + else + ecryptfs_release_lower_page(*lower_page, 1); (*lower_page) = NULL; } return rc; @@ -588,16 +603,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, struct file *lower_file, int byte_offset, int region_size) { + int page_locked = 1; int rc = 0; rc = lower_inode->i_mapping->a_ops->commit_write( lower_file, lower_page, byte_offset, region_size); + if (rc == AOP_TRUNCATED_PAGE) + page_locked = 0; if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error committing write; rc = [%d]\n", rc); } else rc = 0; - ecryptfs_release_lower_page(lower_page); + ecryptfs_release_lower_page(lower_page, page_locked); return rc; } -- cgit v1.2.3 From 1ed6d896de3a57bdfb38cffaa748612f112c2a75 Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Wed, 28 Feb 2007 20:12:52 -0800 Subject: [PATCH] eCryptfs: remove unnecessary flush_dcache_page() Remove unnecessary flush_dcache_page() call. Thanks to Dmitriy Monakhov for pointing this out. Signed-off-by: Michael Halcrow Cc: Dmitriy Monakhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/mmap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/ecryptfs/mmap.c') diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 82bdbed658d7..7be8e91b5ba0 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -238,7 +238,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, lower_page_data = kmap_atomic(lower_page, KM_USER1); memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); kunmap_atomic(lower_page_data, KM_USER1); - flush_dcache_page(lower_page); kunmap_atomic(page_data, KM_USER0); flush_dcache_page(page); rc = 0; -- cgit v1.2.3 From ad5f1196792653dadf09c07a5fa917092b469c1c Mon Sep 17 00:00:00 2001 From: Dmitriy Monakhov Date: Mon, 5 Mar 2007 00:30:12 -0800 Subject: [PATCH] ecryptfs: check xattr operation support fix - ecryptfs_write_inode_size_to_metadata() error code was ignored. - i_op->setxattr() must be supported by lower fs because used below. Signed-off-by: Monakhov Dmitriy Acked-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/inode.c | 6 +++--- fs/ecryptfs/mmap.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/ecryptfs/mmap.c') diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 0cfff4fefa9e..e62f3fc7241e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -168,9 +168,9 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, goto out; } i_size_write(inode, 0); - ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode, - ecryptfs_dentry, - ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); + rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, + inode, ecryptfs_dentry, + ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE; out: return rc; diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 7be8e91b5ba0..7def4be83e61 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -502,7 +502,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode, goto out; } lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); - if (!lower_dentry->d_inode->i_op->getxattr) { + if (!lower_dentry->d_inode->i_op->getxattr || + !lower_dentry->d_inode->i_op->setxattr) { printk(KERN_WARNING "No support for setting xattr in lower filesystem\n"); rc = -ENOSYS; -- cgit v1.2.3 From a8fa74ab529f23f812092ece8d7a4766af092332 Mon Sep 17 00:00:00 2001 From: Dmitriy Monakhov Date: Mon, 5 Mar 2007 00:30:47 -0800 Subject: [PATCH] ecryptfs: handle AOP_TRUNCATED_PAGE better - In fact we don't have to fail if AOP_TRUNCATED_PAGE was returned from prepare_write or commit_write. It is beter to retry attempt where it is possible. - Rearange ecryptfs_get_lower_page() error handling logic, make it more clean. Signed-off-by: Dmitriy Monakhov Acked-by: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/mmap.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'fs/ecryptfs/mmap.c') diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 7def4be83e61..b731b09499cb 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -446,6 +446,7 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, const struct address_space_operations *lower_a_ops; u64 file_size; +retry: header_page = grab_cache_page(lower_inode->i_mapping, 0); if (!header_page) { ecryptfs_printk(KERN_ERR, "grab_cache_page for " @@ -456,9 +457,10 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, lower_a_ops = lower_inode->i_mapping->a_ops; rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); if (rc) { - if (rc == AOP_TRUNCATED_PAGE) + if (rc == AOP_TRUNCATED_PAGE) { ecryptfs_release_lower_page(header_page, 0); - else + goto retry; + } else ecryptfs_release_lower_page(header_page, 1); goto out; } @@ -473,9 +475,10 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, if (rc < 0) ecryptfs_printk(KERN_ERR, "Error commiting header page " "write\n"); - if (rc == AOP_TRUNCATED_PAGE) + if (rc == AOP_TRUNCATED_PAGE) { ecryptfs_release_lower_page(header_page, 0); - else + goto retry; + } else ecryptfs_release_lower_page(header_page, 1); lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; mark_inode_dirty_sync(inode); @@ -565,6 +568,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, { int rc = 0; +retry: *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); if (!(*lower_page)) { rc = -EINVAL; @@ -578,18 +582,18 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, byte_offset, region_bytes); if (rc) { - ecryptfs_printk(KERN_ERR, "prepare_write for " + if (rc == AOP_TRUNCATED_PAGE) { + ecryptfs_release_lower_page(*lower_page, 0); + goto retry; + } else { + ecryptfs_printk(KERN_ERR, "prepare_write for " "lower_page_index = [0x%.16x] failed; rc = " "[%d]\n", lower_page_index, rc); - } -out: - if (rc && (*lower_page)) { - if (rc == AOP_TRUNCATED_PAGE) - ecryptfs_release_lower_page(*lower_page, 0); - else ecryptfs_release_lower_page(*lower_page, 1); - (*lower_page) = NULL; + (*lower_page) = NULL; + } } +out: return rc; } -- cgit v1.2.3