[patch 35/44] ecryptfs convert to new aops

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

 



Cc: Linux Filesystems <linux-fsdevel@xxxxxxxxxxxxxxx>
Cc: mhalcrow@xxxxxxxxxx
Cc: phillip@xxxxxxxxxxxxxxxxxxxx
Cc: ecryptfs-devel@xxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Nick Piggin <npiggin@xxxxxxx>

 fs/ecryptfs/crypto.c          |   32 +++---
 fs/ecryptfs/ecryptfs_kernel.h |    4 
 fs/ecryptfs/mmap.c            |  213 +++++++++++++++++++-----------------------
 3 files changed, 119 insertions(+), 130 deletions(-)

Index: linux-2.6/fs/ecryptfs/mmap.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/mmap.c
+++ linux-2.6/fs/ecryptfs/mmap.c
@@ -36,26 +36,6 @@
 
 struct kmem_cache *ecryptfs_lower_page_cache;
 
-/**
- * ecryptfs_get1page
- *
- * Get one page from cache or lower f/s, return error otherwise.
- *
- * Returns unlocked and up-to-date page (if ok), with increased
- * refcnt.
- */
-static struct page *ecryptfs_get1page(struct file *file, int index)
-{
-	struct dentry *dentry;
-	struct inode *inode;
-	struct address_space *mapping;
-
-	dentry = file->f_path.dentry;
-	inode = dentry->d_inode;
-	mapping = inode->i_mapping;
-	return read_mapping_page(mapping, index, (void *)file);
-}
-
 static
 int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
 
@@ -360,17 +340,14 @@ out:
 /**
  * Called with lower inode mutex held.
  */
-static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
+static int fill_zeros_to_end_of_page(struct page *page, loff_t new_isize)
 {
-	struct inode *inode = page->mapping->host;
 	int end_byte_in_page;
 	char *page_virt;
 
-	if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+	if ((new_isize >> PAGE_CACHE_SHIFT) != page->index)
 		goto out;
-	end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
-	if (to > end_byte_in_page)
-		end_byte_in_page = to;
+	end_byte_in_page = new_isize % PAGE_CACHE_SIZE;
 	page_virt = kmap_atomic(page, KM_USER0);
 	memset((page_virt + end_byte_in_page), 0,
 	       (PAGE_CACHE_SIZE - end_byte_in_page));
@@ -380,16 +357,35 @@ out:
 	return 0;
 }
 
-static int ecryptfs_prepare_write(struct file *file, struct page *page,
-				  unsigned from, unsigned to)
+static int ecryptfs_write_begin(struct file *file,struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata)
 {
+	struct page *page;
+	pgoff_t index;
 	int rc = 0;
 
-	if (from == 0 && to == PAGE_CACHE_SIZE)
-		goto out;	/* If we are writing a full page, it will be
-				   up to date. */
-	if (!PageUptodate(page))
-		rc = ecryptfs_do_readpage(file, page, page->index);
+	index = pos >> PAGE_CACHE_SHIFT;
+	page = __grab_cache_page(mapping, index);
+	if (!page) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * If we are writing a full page (with no possibility of a short
+	 * write), it will be guaranteed to end up being uptodate at
+	 * write_end-time
+	 */
+	if (flags & AOP_FLAG_UNINTERRUPTIBLE && len == PAGE_CACHE_SIZE)
+		goto out;
+	if (!PageUptodate(page)) {
+		rc = ecryptfs_do_readpage(file, page, index);
+		if (rc) {
+			unlock_page(page);
+			page_cache_release(page);
+		}
+	}
 out:
 	return rc;
 }
@@ -412,12 +408,6 @@ out:
 	return rc;
 }
 
-static void ecryptfs_release_lower_page(struct page *lower_page)
-{
-	unlock_page(lower_page);
-	page_cache_release(lower_page);
-}
-
 /**
  * ecryptfs_write_inode_size_to_header
  *
@@ -431,23 +421,17 @@ static int ecryptfs_write_inode_size_to_
 {
 	int rc = 0;
 	struct page *header_page;
+	void *fsdata;
 	char *header_virt;
-	const struct address_space_operations *lower_a_ops;
+	struct address_space *lower_mapping = lower_inode->i_mapping;
 	u64 file_size;
 
-	header_page = grab_cache_page(lower_inode->i_mapping, 0);
-	if (!header_page) {
-		ecryptfs_printk(KERN_ERR, "grab_cache_page for "
-				"lower_page_index 0 failed\n");
-		rc = -EINVAL;
-		goto out;
-	}
-	lower_a_ops = lower_inode->i_mapping->a_ops;
-	rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8);
-	if (rc) {
-		ecryptfs_release_lower_page(header_page);
+	rc = pagecache_write_begin(lower_file, lower_mapping, 0, sizeof(u64),
+					AOP_FLAG_UNINTERRUPTIBLE,
+					&header_page, &fsdata);
+	if (rc)
 		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);
@@ -455,13 +439,17 @@ static int ecryptfs_write_inode_size_to_
 	memcpy(header_virt, &file_size, sizeof(u64));
 	kunmap_atomic(header_virt, KM_USER0);
 	flush_dcache_page(header_page);
-	rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
-	if (rc < 0)
+
+	rc = pagecache_write_end(lower_file, lower_mapping, 0, sizeof(u64),
+					sizeof(u64), header_page, fsdata);
+	if (rc != sizeof(u64)) {
 		ecryptfs_printk(KERN_ERR, "Error commiting header page "
 				"write\n");
-	ecryptfs_release_lower_page(header_page);
+		if (rc > 0)
+			rc = -EINVAL; /* XXX: can we do better? */
+	}
 	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty_sync(inode);
+	mark_inode_dirty_sync(inode); /* XXX: lower_inode? */
 out:
 	return rc;
 }
@@ -544,31 +532,21 @@ ecryptfs_write_inode_size_to_metadata(st
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
-			    int region_bytes)
+			    int region_bytes, void **fsdata)
 {
-	int rc = 0;
+	int rc;
+	struct address_space *lower_mapping = lower_inode->i_mapping;
+	loff_t pos = (lower_page_index << PAGE_CACHE_SHIFT) + byte_offset;
 
-retry:
-	*lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
-	if (!(*lower_page)) {
-		rc = -EINVAL;
-		ecryptfs_printk(KERN_ERR, "Error attempting to grab "
-				"lower page with index [0x%.16x]\n",
-				lower_page_index);
-		goto out;
-	}
-	rc = lower_inode->i_mapping->a_ops->prepare_write(lower_file,
-							  (*lower_page),
-							  byte_offset,
-							  region_bytes);
+	rc = pagecache_write_begin(lower_file, lower_mapping, pos, region_bytes,
+				AOP_FLAG_UNINTERRUPTIBLE, /* XXX: ok? */
+				lower_page, fsdata);
 	if (rc) {
-		ecryptfs_printk(KERN_ERR, "prepare_write for "
+		ecryptfs_printk(KERN_ERR, "pagecache_write_begin for "
 			"lower_page_index = [0x%.16x] failed; rc = "
 			"[%d]\n", lower_page_index, rc);
-		ecryptfs_release_lower_page(*lower_page);
 		(*lower_page) = NULL;
 	}
-out:
 	return rc;
 }
 
@@ -580,18 +558,21 @@ out:
 int
 ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
 			   struct file *lower_file, int byte_offset,
-			   int region_size)
+			   int region_size, void *fsdata)
 {
-	int rc = 0;
+	int rc;
+	struct address_space *lower_mapping = lower_inode->i_mapping;
+	loff_t pos = (lower_page->index << PAGE_CACHE_SHIFT) + byte_offset;
 
-	rc = lower_inode->i_mapping->a_ops->commit_write(
-		lower_file, lower_page, byte_offset, region_size);
-	if (rc < 0) {
+	rc = pagecache_write_end(lower_file, lower_mapping, pos, region_size,
+					region_size, lower_page, fsdata);
+	if (rc != region_size) {
 		ecryptfs_printk(KERN_ERR,
 				"Error committing write; rc = [%d]\n", rc);
+		if (rc > 0)
+			rc = -EINVAL;
 	} else
 		rc = 0;
-	ecryptfs_release_lower_page(lower_page);
 	return rc;
 }
 
@@ -606,9 +587,10 @@ int ecryptfs_copy_page_to_lower(struct p
 {
 	int rc = 0;
 	struct page *lower_page;
+	void *fsdata;
 
 	rc = ecryptfs_get_lower_page(&lower_page, lower_inode, lower_file,
-				     page->index, 0, PAGE_CACHE_SIZE);
+				     page->index, 0, PAGE_CACHE_SIZE, &fsdata);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error attempting to get page "
 				"at index [0x%.16x]\n", page->index);
@@ -618,7 +600,7 @@ int ecryptfs_copy_page_to_lower(struct p
 	memcpy((char *)page_address(lower_page), page_address(page),
 	       PAGE_CACHE_SIZE);
 	rc = ecryptfs_commit_lower_page(lower_page, lower_inode, lower_file,
-					0, PAGE_CACHE_SIZE);
+					0, PAGE_CACHE_SIZE, fsdata);
 	if (rc)
 		ecryptfs_printk(KERN_ERR, "Error attempting to commit page "
 				"at index [0x%.16x]\n", page->index);
@@ -629,31 +611,37 @@ out:
 struct kmem_cache *ecryptfs_xattr_cache;
 
 /**
- * ecryptfs_commit_write
+ * ecryptfs_write_end
  * @file: The eCryptfs file object
- * @page: The eCryptfs page
- * @from: Ignored (we rotate the page IV on each write)
- * @to: Ignored
+ * @mapping: The eCryptfs address_space
+ * @pos: The start of the write
+ * @len: The length passed to write_begin (unused)
+ * @copied: The actual amount copied
+ * @page: The eCryptfs page returned by write_begin
+ * @fsdata: Filesystem private data (unused)
  *
  * This is where we encrypt the data and pass the encrypted data to
  * the lower filesystem.  In OpenPGP-compatible mode, we operate on
  * entire underlying packets.
  */
-static int ecryptfs_commit_write(struct file *file, struct page *page,
-				 unsigned from, unsigned to)
+static int ecryptfs_write_end(struct file *file,
+					struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata)
 {
 	struct ecryptfs_page_crypt_context ctx;
-	loff_t pos;
+	loff_t isize;
 	struct inode *inode;
 	struct inode *lower_inode;
 	struct file *lower_file;
 	struct ecryptfs_crypt_stat *crypt_stat;
 	int rc;
 
-	inode = page->mapping->host;
+	inode = mapping->host;
+	isize = inode->i_size; /* i_mutex is held */
 	lower_inode = ecryptfs_inode_to_lower(inode);
 	lower_file = ecryptfs_file_to_lower(file);
-	mutex_lock(&lower_inode->i_mutex);
+	mutex_lock(&lower_inode->i_mutex); /* XXX: put this in write_begin? */
 	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
 				->crypt_stat;
 	if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
@@ -664,8 +652,8 @@ static int ecryptfs_commit_write(struct 
 		ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
 	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
 			"(page w/ index = [0x%.16x], to = [%d])\n", page->index,
-			to);
-	rc = fill_zeros_to_end_of_page(page, to);
+			max(isize, pos+copied));
+	rc = fill_zeros_to_end_of_page(page, max(isize, pos+copied));
 	if (rc) {
 		ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
 				"zeros in page with index = [0x%.16x]\n",
@@ -682,11 +670,10 @@ static int ecryptfs_commit_write(struct 
 		goto out;
 	}
 	inode->i_blocks = lower_inode->i_blocks;
-	pos = (page->index << PAGE_CACHE_SHIFT) + to;
-	if (pos > i_size_read(inode)) {
-		i_size_write(inode, pos);
+	if (pos + copied > isize) {
+		i_size_write(inode, pos + copied);
 		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
-				"[0x%.16x]\n", i_size_read(inode));
+				"[0x%.16x]\n", pos + copied);
 	}
 	rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
 						   inode, file->f_dentry,
@@ -702,6 +689,9 @@ out:
 	else
 		SetPageUptodate(page);
 	mutex_unlock(&lower_inode->i_mutex);
+	unlock_page(page);
+	page_cache_release(page);
+
 	return rc;
 }
 
@@ -722,32 +712,31 @@ int write_zeros(struct file *file, pgoff
 	int rc = 0;
 	struct page *tmp_page;
 	char *tmp_page_virt;
-
-	tmp_page = ecryptfs_get1page(file, index);
-	if (IS_ERR(tmp_page)) {
-		ecryptfs_printk(KERN_ERR, "Error getting page at index "
-				"[0x%.16x]\n", index);
-		rc = PTR_ERR(tmp_page);
-		goto out;
-	}
-	rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
+	void *fsdata;
+	struct address_space *mapping = file->f_path.dentry->d_inode->i_mapping;
+	loff_t pos = (index << PAGE_CACHE_SHIFT) + start;
+
+	rc = pagecache_write_begin(file, mapping, pos, num_zeros,
+					AOP_FLAG_UNINTERRUPTIBLE,
+					&tmp_page, &fsdata);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		page_cache_release(tmp_page);
 		goto out;
 	}
 	tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
 	memset(((char *)tmp_page_virt + start), 0, num_zeros);
 	kunmap_atomic(tmp_page_virt, KM_USER0);
 	flush_dcache_page(tmp_page);
-	rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
-	if (rc < 0) {
+	rc = pagecache_write_end(file, mapping, pos, num_zeros, num_zeros,
+					tmp_page, fsdata);
+	if (rc != num_zeros) {
 		ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		page_cache_release(tmp_page);
+		if (rc > 0)
+			rc = -EINVAL;
 		goto out;
 	}
 	rc = 0;
@@ -795,8 +784,8 @@ static void ecryptfs_sync_page(struct pa
 struct address_space_operations ecryptfs_aops = {
 	.writepage = ecryptfs_writepage,
 	.readpage = ecryptfs_readpage,
-	.prepare_write = ecryptfs_prepare_write,
-	.commit_write = ecryptfs_commit_write,
+	.write_begin = ecryptfs_write_begin,
+	.write_end = ecryptfs_write_end,
 	.bmap = ecryptfs_bmap,
 	.sync_page = ecryptfs_sync_page,
 };
Index: linux-2.6/fs/ecryptfs/crypto.c
===================================================================
--- linux-2.6.orig/fs/ecryptfs/crypto.c
+++ linux-2.6/fs/ecryptfs/crypto.c
@@ -375,7 +375,8 @@ ecryptfs_extent_to_lwr_pg_idx_and_offset
 static int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
 				   struct page *lower_page,
 				   struct inode *lower_inode,
-				   int byte_offset_in_page, int bytes_to_write)
+				   int byte_offset_in_page, int bytes_to_write,
+				   void *fsdata)
 {
 	int rc = 0;
 
@@ -383,7 +384,7 @@ static int ecryptfs_write_out_page(struc
 		rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
 						ctx->param.lower_file,
 						byte_offset_in_page,
-						bytes_to_write);
+						bytes_to_write, fsdata);
 		if (rc) {
 			ecryptfs_printk(KERN_ERR, "Error calling lower "
 					"commit; rc = [%d]\n", rc);
@@ -407,7 +408,7 @@ static int ecryptfs_read_in_page(struct 
 				 struct page **lower_page,
 				 struct inode *lower_inode,
 				 unsigned long lower_page_idx,
-				 int byte_offset_in_page)
+				 int byte_offset_in_page, void **fsdata)
 {
 	int rc = 0;
 
@@ -419,13 +420,12 @@ static int ecryptfs_read_in_page(struct 
 					     lower_page_idx,
 					     byte_offset_in_page,
 					     (PAGE_CACHE_SIZE
-					      - byte_offset_in_page));
+					      - byte_offset_in_page), fsdata);
 		if (rc) {
 			ecryptfs_printk(
-				KERN_ERR, "Error attempting to grab, map, "
-				"and prepare_write lower page with index "
+				KERN_ERR, "Error in ecryptfs_get_lower_page "
+				"lower page with index "
 				"[0x%.16x]; rc = [%d]\n", lower_page_idx, rc);
-			goto out;
 		}
 	} else {
 		*lower_page = grab_cache_page(lower_inode->i_mapping,
@@ -436,10 +436,9 @@ static int ecryptfs_read_in_page(struct 
 				KERN_ERR, "Error attempting to grab and map "
 				"lower page with index [0x%.16x]; rc = [%d]\n",
 				lower_page_idx, rc);
-			goto out;
 		}
 	}
-out:
+
 	return rc;
 }
 
@@ -475,6 +474,8 @@ int ecryptfs_encrypt_page(struct ecryptf
 	int lower_byte_offset = 0;
 	int orig_byte_offset = 0;
 	int num_extents_per_page;
+	void *fsdata;
+
 #define ECRYPTFS_PAGE_STATE_UNREAD    0
 #define ECRYPTFS_PAGE_STATE_READ      1
 #define ECRYPTFS_PAGE_STATE_MODIFIED  2
@@ -503,10 +504,9 @@ int ecryptfs_encrypt_page(struct ecryptf
 		if (prior_lower_page_idx != lower_page_idx
 		    && page_state == ECRYPTFS_PAGE_STATE_MODIFIED) {
 			rc = ecryptfs_write_out_page(ctx, lower_page,
-						     lower_inode,
-						     orig_byte_offset,
-						     (PAGE_CACHE_SIZE
-						      - orig_byte_offset));
+					lower_inode, orig_byte_offset,
+					(PAGE_CACHE_SIZE - orig_byte_offset),
+					fsdata);
 			if (rc) {
 				ecryptfs_printk(KERN_ERR, "Error attempting "
 						"to write out page; rc = [%d]"
@@ -519,7 +519,7 @@ int ecryptfs_encrypt_page(struct ecryptf
 		    || page_state == ECRYPTFS_PAGE_STATE_WRITTEN) {
 			rc = ecryptfs_read_in_page(ctx, &lower_page,
 						   lower_inode, lower_page_idx,
-						   lower_byte_offset);
+						   lower_byte_offset, &fsdata);
 			if (rc) {
 				ecryptfs_printk(KERN_ERR, "Error attempting "
 						"to read in lower page with "
@@ -571,8 +571,8 @@ int ecryptfs_encrypt_page(struct ecryptf
 	}
 	BUG_ON(orig_byte_offset != 0);
 	rc = ecryptfs_write_out_page(ctx, lower_page, lower_inode, 0,
-				     (lower_byte_offset
-				      + crypt_stat->extent_size));
+				(lower_byte_offset + crypt_stat->extent_size),
+				fsdata);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error attempting to write out "
 				"page; rc = [%d]\n", rc);
Index: linux-2.6/fs/ecryptfs/ecryptfs_kernel.h
===================================================================
--- linux-2.6.orig/fs/ecryptfs/ecryptfs_kernel.h
+++ linux-2.6/fs/ecryptfs/ecryptfs_kernel.h
@@ -503,11 +503,11 @@ int ecryptfs_write_inode_size_to_metadat
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
-			    int region_bytes);
+			    int region_bytes, void **fsdata);
 int
 ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
 			   struct file *lower_file, int byte_offset,
-			   int region_size);
+			   int region_size, void *fsdata);
 int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
 				struct file *lower_file);
 int ecryptfs_do_readpage(struct file *file, struct page *page,

-- 

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux