diff options
author | Christoph Lameter <clameter@sgi.com> | 2006-02-01 06:05:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-01 11:53:17 -0500 |
commit | e965f9630c651fa4249039fd4b80c9392d07a856 (patch) | |
tree | 1353dd536d0ee549c30e462086624c21788ee9d2 /fs/buffer.c | |
parent | 7e2ab150d1b3b286a4c864c60a549b2601777b63 (diff) |
[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: Mike Kravetz <kravetz@us.ibm.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 3dc712f29d2d..8bcbac87a28c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -3050,6 +3050,66 @@ asmlinkage long sys_bdflush(int func, long data) | |||
3050 | } | 3050 | } |
3051 | 3051 | ||
3052 | /* | 3052 | /* |
3053 | * Migration function for pages with buffers. This function can only be used | ||
3054 | * if the underlying filesystem guarantees that no other references to "page" | ||
3055 | * exist. | ||
3056 | */ | ||
3057 | #ifdef CONFIG_MIGRATION | ||
3058 | int buffer_migrate_page(struct page *newpage, struct page *page) | ||
3059 | { | ||
3060 | struct address_space *mapping = page->mapping; | ||
3061 | struct buffer_head *bh, *head; | ||
3062 | |||
3063 | if (!mapping) | ||
3064 | return -EAGAIN; | ||
3065 | |||
3066 | if (!page_has_buffers(page)) | ||
3067 | return migrate_page(newpage, page); | ||
3068 | |||
3069 | head = page_buffers(page); | ||
3070 | |||
3071 | if (migrate_page_remove_references(newpage, page, 3)) | ||
3072 | return -EAGAIN; | ||
3073 | |||
3074 | bh = head; | ||
3075 | do { | ||
3076 | get_bh(bh); | ||
3077 | lock_buffer(bh); | ||
3078 | bh = bh->b_this_page; | ||
3079 | |||
3080 | } while (bh != head); | ||
3081 | |||
3082 | ClearPagePrivate(page); | ||
3083 | set_page_private(newpage, page_private(page)); | ||
3084 | set_page_private(page, 0); | ||
3085 | put_page(page); | ||
3086 | get_page(newpage); | ||
3087 | |||
3088 | bh = head; | ||
3089 | do { | ||
3090 | set_bh_page(bh, newpage, bh_offset(bh)); | ||
3091 | bh = bh->b_this_page; | ||
3092 | |||
3093 | } while (bh != head); | ||
3094 | |||
3095 | SetPagePrivate(newpage); | ||
3096 | |||
3097 | migrate_page_copy(newpage, page); | ||
3098 | |||
3099 | bh = head; | ||
3100 | do { | ||
3101 | unlock_buffer(bh); | ||
3102 | put_bh(bh); | ||
3103 | bh = bh->b_this_page; | ||
3104 | |||
3105 | } while (bh != head); | ||
3106 | |||
3107 | return 0; | ||
3108 | } | ||
3109 | EXPORT_SYMBOL(buffer_migrate_page); | ||
3110 | #endif | ||
3111 | |||
3112 | /* | ||
3053 | * Buffer-head allocation | 3113 | * Buffer-head allocation |
3054 | */ | 3114 | */ |
3055 | static kmem_cache_t *bh_cachep; | 3115 | static kmem_cache_t *bh_cachep; |