Re: [PATCH] eCryptfs: Revert to a writethrough cache model

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2012-07-10 12:44:05, Colin Ian King wrote:
> On 06/07/12 23:40, Tyler Hicks wrote:
> >A change was made about a year ago to get eCryptfs to better utilize its
> >page cache during writes. The idea was to do the page encryption
> >operations during page writeback, rather than doing them when initially
> >writing into the page cache, to reduce the number of page encryption
> >operations during sequential writes. This meant that the encrypted page
> >would only be written to the lower filesystem during page writeback,
> >which was a change from how eCryptfs had previously wrote to the lower
> >filesystem in ecryptfs_write_end().
> >
> >The change caused a few eCryptfs-internal bugs that were shook out.
> >Unfortunately, more grave side effects have been identified that will
> >force changes outside of eCryptfs. Because the lower filesystem isn't
> >consulted until page writeback, eCryptfs has no way to pass lower write
> >errors (ENOSPC, mainly) back to userspace. Additionaly, it was reported
> >that quotas could be bypassed because of the way eCryptfs may sometimes
> >open the lower filesystem using a privileged kthread.
> >
> >It would be nice to resolve the latest issues, but it is best if the
> >eCryptfs commits be reverted to the old behavior in the meantime.
> >
> >This reverts:
> >32001d6f "eCryptfs: Flush file in vma close"
> >5be79de2 "eCryptfs: Flush dirty pages in setattr"
> >57db4e8d "ecryptfs: modify write path to encrypt page in writepage"
> >
> >Signed-off-by: Tyler Hicks <tyhicks@xxxxxxxxxxxxx>
> >Cc: Colin King <colin.king@xxxxxxxxxxxxx>
> >Cc: Thieu Le <thieule@xxxxxxxxxx>
> >---
> >  fs/ecryptfs/file.c  |   33 ++-------------------------------
> >  fs/ecryptfs/inode.c |    6 ------
> >  fs/ecryptfs/mmap.c  |   39 +++++++++++++--------------------------
> >  3 files changed, 15 insertions(+), 63 deletions(-)
> >
> >diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
> >index baf8b05..44ce5c6 100644
> >--- a/fs/ecryptfs/file.c
> >+++ b/fs/ecryptfs/file.c
> >@@ -138,27 +138,6 @@ out:
> >  	return rc;
> >  }
> >
> >-static void ecryptfs_vma_close(struct vm_area_struct *vma)
> >-{
> >-	filemap_write_and_wait(vma->vm_file->f_mapping);
> >-}
> >-
> >-static const struct vm_operations_struct ecryptfs_file_vm_ops = {
> >-	.close		= ecryptfs_vma_close,
> >-	.fault		= filemap_fault,
> >-};
> >-
> >-static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma)
> >-{
> >-	int rc;
> >-
> >-	rc = generic_file_mmap(file, vma);
> >-	if (!rc)
> >-		vma->vm_ops = &ecryptfs_file_vm_ops;
> >-
> >-	return rc;
> >-}
> >-
> >  struct kmem_cache *ecryptfs_file_info_cache;
> >
> >  static int read_or_initialize_metadata(struct dentry *dentry)
> >@@ -311,15 +290,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
> >  static int
> >  ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
> >  {
> >-	int rc = 0;
> >-
> >-	rc = generic_file_fsync(file, start, end, datasync);
> >-	if (rc)
> >-		goto out;
> >-	rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end,
> >-			     datasync);
> >-out:
> >-	return rc;
> >+	return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
> >  }
> >
> >  static int ecryptfs_fasync(int fd, struct file *file, int flag)
> >@@ -388,7 +359,7 @@ const struct file_operations ecryptfs_main_fops = {
> >  #ifdef CONFIG_COMPAT
> >  	.compat_ioctl = ecryptfs_compat_ioctl,
> >  #endif
> >-	.mmap = ecryptfs_file_mmap,
> >+	.mmap = generic_file_mmap,
> >  	.open = ecryptfs_open,
> >  	.flush = ecryptfs_flush,
> >  	.release = ecryptfs_release,
> >diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> >index 2d4143f..769fb85 100644
> >--- a/fs/ecryptfs/inode.c
> >+++ b/fs/ecryptfs/inode.c
> >@@ -981,12 +981,6 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
> >  			goto out;
> >  	}
> >
> >-	if (S_ISREG(inode->i_mode)) {
> >-		rc = filemap_write_and_wait(inode->i_mapping);
> >-		if (rc)
> >-			goto out;
> >-		fsstack_copy_attr_all(inode, lower_inode);
> >-	}
> >  	memcpy(&lower_ia, ia, sizeof(lower_ia));
> >  	if (ia->ia_valid & ATTR_FILE)
> >  		lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
> >diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
> >index a46b3a8..bd1d57f 100644
> >--- a/fs/ecryptfs/mmap.c
> >+++ b/fs/ecryptfs/mmap.c
> >@@ -66,18 +66,6 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
> >  {
> >  	int rc;
> >
> >-	/*
> >-	 * Refuse to write the page out if we are called from reclaim context
> >-	 * since our writepage() path may potentially allocate memory when
> >-	 * calling into the lower fs vfs_write() which may in turn invoke
> >-	 * us again.
> >-	 */
> >-	if (current->flags & PF_MEMALLOC) {
> >-		redirty_page_for_writepage(wbc, page);
> >-		rc = 0;
> >-		goto out;
> >-	}
> >-
> >  	rc = ecryptfs_encrypt_page(page);
> >  	if (rc) {
> >  		ecryptfs_printk(KERN_WARNING, "Error encrypting "
> >@@ -498,7 +486,6 @@ static int ecryptfs_write_end(struct file *file,
> >  	struct ecryptfs_crypt_stat *crypt_stat =
> >  		&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
> >  	int rc;
> >-	int need_unlock_page = 1;
> >
> >  	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
> >  			"(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
> >@@ -519,26 +506,26 @@ static int ecryptfs_write_end(struct file *file,
> >  			"zeros in page with index = [0x%.16lx]\n", index);
> >  		goto out;
> >  	}
> >-	set_page_dirty(page);
> >-	unlock_page(page);
> >-	need_unlock_page = 0;
> >+	rc = ecryptfs_encrypt_page(page);
> >+	if (rc) {
> >+		ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
> >+				"index [0x%.16lx])\n", index);
> >+		goto out;
> >+	}
> >  	if (pos + copied > i_size_read(ecryptfs_inode)) {
> >  		i_size_write(ecryptfs_inode, pos + copied);
> >  		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
> >  			"[0x%.16llx]\n",
> >  			(unsigned long long)i_size_read(ecryptfs_inode));
> >-		balance_dirty_pages_ratelimited(mapping);
> >-		rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
> >-		if (rc) {
> >-			printk(KERN_ERR "Error writing inode size to metadata; "
> >-			       "rc = [%d]\n", rc);
> >-			goto out;
> >-		}
> >  	}
> >-	rc = copied;
> >+	rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode);
> >+	if (rc)
> >+		printk(KERN_ERR "Error writing inode size to metadata; "
> >+		       "rc = [%d]\n", rc);
> >+	else
> >+		rc = copied;
> >  out:
> >-	if (need_unlock_page)
> >-		unlock_page(page);
> >+	unlock_page(page);
> >  	page_cache_release(page);
> >  	return rc;
> >  }
> >
> 
> This fixes the ENOSPC issue, I've tested this patch with ext2, ext3,
> ext4, xfs and btrfs lower file systems and it works fine. The patch
> also looks sane to me.
> 
> Tested-by: Colin Ian King <colin.king@xxxxxxxxxxxxx>

Thanks, Colin! I've pushed the patch to the eCryptfs -next branch. I'll
get it in during the 3.6 merge window.

Tyler

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Crypto]     [Device Mapper Crypto]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux