@@ -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:
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(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html