Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e965f963 authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds
Browse files

[PATCH] Direct Migration V9: Avoid writeback / page_migrate() method



Migrate a page with buffers without requiring writeback

This introduces a new address space operation migratepage() that may be used
by a filesystem to implement its own version of page migration.

A version is provided that migrates buffers attached to pages.  Some
filesystems (ext2, ext3, xfs) are modified to utilize this feature.

The swapper address space operation are modified so that a regular
migrate_page() will occur for anonymous pages without writeback (migrate_pages
forces every anonymous page to have a swap entry).

Signed-off-by: default avatarMike Kravetz <kravetz@us.ibm.com>
Signed-off-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7e2ab150
Loading
Loading
Loading
Loading
+60 −0
Original line number Original line Diff line number Diff line
@@ -3049,6 +3049,66 @@ asmlinkage long sys_bdflush(int func, long data)
	return 0;
	return 0;
}
}


/*
 * Migration function for pages with buffers. This function can only be used
 * if the underlying filesystem guarantees that no other references to "page"
 * exist.
 */
#ifdef CONFIG_MIGRATION
int buffer_migrate_page(struct page *newpage, struct page *page)
{
	struct address_space *mapping = page->mapping;
	struct buffer_head *bh, *head;

	if (!mapping)
		return -EAGAIN;

	if (!page_has_buffers(page))
		return migrate_page(newpage, page);

	head = page_buffers(page);

	if (migrate_page_remove_references(newpage, page, 3))
		return -EAGAIN;

	bh = head;
	do {
		get_bh(bh);
		lock_buffer(bh);
		bh = bh->b_this_page;

	} while (bh != head);

	ClearPagePrivate(page);
	set_page_private(newpage, page_private(page));
	set_page_private(page, 0);
	put_page(page);
	get_page(newpage);

	bh = head;
	do {
		set_bh_page(bh, newpage, bh_offset(bh));
		bh = bh->b_this_page;

	} while (bh != head);

	SetPagePrivate(newpage);

	migrate_page_copy(newpage, page);

	bh = head;
	do {
		unlock_buffer(bh);
 		put_bh(bh);
		bh = bh->b_this_page;

	} while (bh != head);

	return 0;
}
EXPORT_SYMBOL(buffer_migrate_page);
#endif

/*
/*
 * Buffer-head allocation
 * Buffer-head allocation
 */
 */
+2 −0
Original line number Original line Diff line number Diff line
@@ -706,6 +706,7 @@ struct address_space_operations ext2_aops = {
	.bmap			= ext2_bmap,
	.bmap			= ext2_bmap,
	.direct_IO		= ext2_direct_IO,
	.direct_IO		= ext2_direct_IO,
	.writepages		= ext2_writepages,
	.writepages		= ext2_writepages,
	.migratepage		= buffer_migrate_page,
};
};


struct address_space_operations ext2_aops_xip = {
struct address_space_operations ext2_aops_xip = {
@@ -723,6 +724,7 @@ struct address_space_operations ext2_nobh_aops = {
	.bmap			= ext2_bmap,
	.bmap			= ext2_bmap,
	.direct_IO		= ext2_direct_IO,
	.direct_IO		= ext2_direct_IO,
	.writepages		= ext2_writepages,
	.writepages		= ext2_writepages,
	.migratepage		= buffer_migrate_page,
};
};


/*
/*
+2 −0
Original line number Original line Diff line number Diff line
@@ -1559,6 +1559,7 @@ static struct address_space_operations ext3_ordered_aops = {
	.invalidatepage	= ext3_invalidatepage,
	.invalidatepage	= ext3_invalidatepage,
	.releasepage	= ext3_releasepage,
	.releasepage	= ext3_releasepage,
	.direct_IO	= ext3_direct_IO,
	.direct_IO	= ext3_direct_IO,
	.migratepage	= buffer_migrate_page,
};
};


static struct address_space_operations ext3_writeback_aops = {
static struct address_space_operations ext3_writeback_aops = {
@@ -1572,6 +1573,7 @@ static struct address_space_operations ext3_writeback_aops = {
	.invalidatepage	= ext3_invalidatepage,
	.invalidatepage	= ext3_invalidatepage,
	.releasepage	= ext3_releasepage,
	.releasepage	= ext3_releasepage,
	.direct_IO	= ext3_direct_IO,
	.direct_IO	= ext3_direct_IO,
	.migratepage	= buffer_migrate_page,
};
};


static struct address_space_operations ext3_journalled_aops = {
static struct address_space_operations ext3_journalled_aops = {
+1 −0
Original line number Original line Diff line number Diff line
@@ -1462,4 +1462,5 @@ struct address_space_operations linvfs_aops = {
	.commit_write		= generic_commit_write,
	.commit_write		= generic_commit_write,
	.bmap			= linvfs_bmap,
	.bmap			= linvfs_bmap,
	.direct_IO		= linvfs_direct_IO,
	.direct_IO		= linvfs_direct_IO,
	.migratepage		= buffer_migrate_page,
};
};
+1 −0
Original line number Original line Diff line number Diff line
@@ -1521,6 +1521,7 @@ xfs_mapping_buftarg(
	struct address_space	*mapping;
	struct address_space	*mapping;
	static struct address_space_operations mapping_aops = {
	static struct address_space_operations mapping_aops = {
		.sync_page = block_sync_page,
		.sync_page = block_sync_page,
		.migratepage = fail_migrate_page,
	};
	};


	inode = new_inode(bdev->bd_inode->i_sb);
	inode = new_inode(bdev->bd_inode->i_sb);
Loading