All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2]ext4: Invalidate donor file page not to refer old blocks
@ 2009-10-02  8:24 Akira Fujita
  0 siblings, 0 replies; only message in thread
From: Akira Fujita @ 2009-10-02  8:24 UTC (permalink / raw)
  To: Theodore Tso, linux-ext4

ext4: Invalidate donor file page not to refer old blocks

After exchanging blocks between original and donor files in mext_extent_per_page(),
the page cache of donor file still refers to old block(s) on memory.
Therefore we have to invalidate page cache of donor file to avoid wrong reference.
The patch fixes this issue.

Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
---
 fs/ext4/move_extent.c |   60 ++++++++++++++++++++++++++++++------------------
 1 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 83f8c9e..6ce8764 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -813,14 +813,15 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 	struct inode *orig_inode = o_filp->f_dentry->d_inode;
 	struct address_space *mapping = orig_inode->i_mapping;
 	struct buffer_head *bh;
-	struct page *page = NULL;
+	struct page *orig_page = NULL;
+	struct page *donor_page = NULL;
 	const struct address_space_operations *a_ops = mapping->a_ops;
 	handle_t *handle;
 	ext4_lblk_t orig_blk_offset;
-	long long offs = orig_page_offset << PAGE_CACHE_SHIFT;
+	long long o_pos;
+	pgoff_t donor_page_offset = orig_page_offset;
 	unsigned long blocksize = orig_inode->i_sb->s_blocksize;
-	unsigned int w_flags = 0;
-	unsigned int tmp_data_size, data_size, replaced_size;
+	unsigned int tmp_data_size, data_size, replaced_size, w_flags = 0;
 	void *fsdata;
 	int i, jblocks;
 	int err2 = 0;
@@ -861,7 +862,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 		goto out2;
 	}

-	offs = (long long)orig_blk_offset << orig_inode->i_blkbits;
+	o_pos = (long long)orig_blk_offset << orig_inode->i_blkbits;

 	/* Calculate data_size */
 	if ((orig_blk_offset + block_len_in_page - 1) ==
@@ -882,14 +883,14 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,

 	replaced_size = data_size;

-	*err = a_ops->write_begin(o_filp, mapping, offs, data_size, w_flags,
-				 &page, &fsdata);
+	*err = a_ops->write_begin(o_filp, mapping, o_pos, data_size, w_flags,
+				 &orig_page, &fsdata);
 	if (unlikely(*err < 0))
 		goto out;

-	if (!PageUptodate(page)) {
-		mapping->a_ops->readpage(o_filp, page);
-		lock_page(page);
+	if (!PageUptodate(orig_page)) {
+		mapping->a_ops->readpage(o_filp, orig_page);
+		lock_page(orig_page);
 	}

 	/*
@@ -899,11 +900,11 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 	 * It needs to call wait_on_page_writeback() to wait for the
 	 * writeback of the page.
 	 */
-	if (PageWriteback(page))
-		wait_on_page_writeback(page);
+	if (PageWriteback(orig_page))
+		wait_on_page_writeback(orig_page);

 	/* Release old bh and drop refs */
-	try_to_release_page(page, 0);
+	try_to_release_page(orig_page, 0);

 	replaced_count = mext_replace_branches(handle, orig_inode, donor_inode,
 					orig_blk_offset, block_len_in_page,
@@ -921,10 +922,23 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 	ext4_ext_invalidate_cache(orig_inode);
 	ext4_ext_invalidate_cache(donor_inode);

-	if (!page_has_buffers(page))
-		create_empty_buffers(page, 1 << orig_inode->i_blkbits, 0);
+	donor_page = grab_cache_page(donor_inode->i_mapping,
+						donor_page_offset);
+	if (!donor_page) {
+		*err = -ENOMEM;
+		goto out;
+	}
+	/* Invalidate donor page not to indicate old block on memory */
+	invalidate_mapping_pages(donor_inode->i_mapping, donor_page_offset,
+				donor_page_offset + 1);
+	unlock_page(donor_page);
+	page_cache_release(donor_page);
+	donor_page = NULL;
+
+	if (!page_has_buffers(orig_page))
+		create_empty_buffers(orig_page, 1 << orig_inode->i_blkbits, 0);

-	bh = page_buffers(page);
+	bh = page_buffers(orig_page);
 	for (i = 0; i < data_offset_in_page; i++)
 		bh = bh->b_this_page;

@@ -938,15 +952,15 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 			bh = bh->b_this_page;
 	}

-	*err = a_ops->write_end(o_filp, mapping, offs, data_size, replaced_size,
-			       page, fsdata);
-	page = NULL;
+	*err = a_ops->write_end(o_filp, mapping, o_pos, data_size,
+			       replaced_size, orig_page, fsdata);
+	orig_page = NULL;

 out:
-	if (unlikely(page)) {
-		if (PageLocked(page))
-			unlock_page(page);
-		page_cache_release(page);
+	if (unlikely(orig_page)) {
+		if (PageLocked(orig_page))
+			unlock_page(orig_page);
+		page_cache_release(orig_page);
 		ext4_journal_stop(handle);
 	}
 out2:

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2009-10-02  8:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-02  8:24 [PATCH 2/2]ext4: Invalidate donor file page not to refer old blocks Akira Fujita

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.