summaryrefslogtreecommitdiffstats
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-02-02 07:12:54 +0100
committerJeff Garzik <jgarzik@pobox.com>2006-02-02 07:12:54 +0100
commit18ee3610040a4c008ce08a40a5dd025241cc7e97 (patch)
tree32a996a5123726b63c31a1522f230933fb967a32 /fs/buffer.c
parent[libata sata_mv] add 6042 support, fix 60xx/50xx EDMA configuration (diff)
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa (diff)
downloadlinux-18ee3610040a4c008ce08a40a5dd025241cc7e97.tar.xz
linux-18ee3610040a4c008ce08a40a5dd025241cc7e97.zip
Merge branch 'master'
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index 3dc712f29d2d..5e4a90ee103f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1022,6 +1022,7 @@ try_again:
bh->b_state = 0;
atomic_set(&bh->b_count, 0);
+ bh->b_private = NULL;
bh->b_size = size;
/* Link the buffer to its page */
@@ -3050,6 +3051,66 @@ asmlinkage long sys_bdflush(int func, long data)
}
/*
+ * 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
*/
static kmem_cache_t *bh_cachep;