Home Home > GIT Browse > openSUSE-15.0
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2019-01-03 13:29:46 +0100
committerJan Kara <jack@suse.cz>2019-01-21 09:16:10 +0100
commitf94c281bebd72b84ebf34b3bf5f2601cf1bc3fe7 (patch)
treee6bb9e3c5196f7c5c70b8d7ec2491a6491393499
parenta63c5478fdcb370f075bec425067246f9bce8469 (diff)
mm: migrate: provide buffer_migrate_page_norefs() (bsc#1084216).
-rw-r--r--patches.fixes/mm-migrate-provide-buffer_migrate_page_norefs.patch125
-rw-r--r--series.conf1
2 files changed, 126 insertions, 0 deletions
diff --git a/patches.fixes/mm-migrate-provide-buffer_migrate_page_norefs.patch b/patches.fixes/mm-migrate-provide-buffer_migrate_page_norefs.patch
new file mode 100644
index 0000000000..4d8f07f172
--- /dev/null
+++ b/patches.fixes/mm-migrate-provide-buffer_migrate_page_norefs.patch
@@ -0,0 +1,125 @@
+From 89cb0888ca1483ad72648844ddd1b801863a8949 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 28 Dec 2018 00:39:12 -0800
+Subject: [PATCH] mm: migrate: provide buffer_migrate_page_norefs()
+Git-commit: 89cb0888ca1483ad72648844ddd1b801863a8949
+Patch-mainline: v4.21-rc1
+References: bsc#1084216
+
+Provide a variant of buffer_migrate_page() that also checks whether there
+are no unexpected references to buffer heads. This function will then be
+safe to use for block device pages.
+
+[akpm@linux-foundation.org: remove EXPORT_SYMBOL(buffer_migrate_page_norefs)]
+Link: http://lkml.kernel.org/r/20181211172143.7358-5-jack@suse.cz
+Signed-off-by: Jan Kara <jack@suse.cz>
+Acked-by: Mel Gorman <mgorman@suse.de>
+Cc: Michal Hocko <mhocko@suse.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Acked-by: Jan Kara <jack@suse.cz>
+
+---
+ include/linux/fs.h | 4 +++
+ mm/migrate.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 57 insertions(+), 7 deletions(-)
+
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -3109,8 +3109,12 @@ extern int generic_check_addressable(uns
+ extern int buffer_migrate_page(struct address_space *,
+ struct page *, struct page *,
+ enum migrate_mode);
++extern int buffer_migrate_page_norefs(struct address_space *,
++ struct page *, struct page *,
++ enum migrate_mode);
+ #else
+ #define buffer_migrate_page NULL
++#define buffer_migrate_page_norefs NULL
+ #endif
+
+ extern int setattr_prepare(struct dentry *, struct iattr *);
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -733,13 +733,9 @@ int migrate_page(struct address_space *m
+ EXPORT_SYMBOL(migrate_page);
+
+ #ifdef CONFIG_BLOCK
+-/*
+- * Migration function for pages with buffers. This function can only be used
+- * if the underlying filesystem guarantees that no other references to "page"
+- * exist.
+- */
+-int buffer_migrate_page(struct address_space *mapping,
+- struct page *newpage, struct page *page, enum migrate_mode mode)
++static int __buffer_migrate_page(struct address_space *mapping,
++ struct page *newpage, struct page *page, enum migrate_mode mode,
++ bool check_refs)
+ {
+ struct buffer_head *bh, *head;
+ int rc;
+@@ -757,6 +753,33 @@ int buffer_migrate_page(struct address_s
+ if (!buffer_migrate_lock_buffers(head, mode))
+ return -EAGAIN;
+
++ if (check_refs) {
++ bool busy;
++ bool invalidated = false;
++
++recheck_buffers:
++ busy = false;
++ spin_lock(&mapping->private_lock);
++ bh = head;
++ do {
++ if (atomic_read(&bh->b_count)) {
++ busy = true;
++ break;
++ }
++ bh = bh->b_this_page;
++ } while (bh != head);
++ spin_unlock(&mapping->private_lock);
++ if (busy) {
++ if (invalidated) {
++ rc = -EAGAIN;
++ goto unlock_buffers;
++ }
++ invalidate_bh_lrus();
++ invalidated = true;
++ goto recheck_buffers;
++ }
++ }
++
+ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+ if (rc != MIGRATEPAGE_SUCCESS)
+ goto unlock_buffers;
+@@ -793,7 +816,30 @@ unlock_buffers:
+
+ return rc;
+ }
++
++/*
++ * Migration function for pages with buffers. This function can only be used
++ * if the underlying filesystem guarantees that no other references to "page"
++ * exist. For example attached buffer heads are accessed only under page lock.
++ */
++int buffer_migrate_page(struct address_space *mapping,
++ struct page *newpage, struct page *page, enum migrate_mode mode)
++{
++ return __buffer_migrate_page(mapping, newpage, page, mode, false);
++}
+ EXPORT_SYMBOL(buffer_migrate_page);
++
++/*
++ * Same as above except that this variant is more careful and checks that there
++ * are also no buffer head references. This function is the right one for
++ * mappings where buffer heads are directly looked up and referenced (such as
++ * block device mappings).
++ */
++int buffer_migrate_page_norefs(struct address_space *mapping,
++ struct page *newpage, struct page *page, enum migrate_mode mode)
++{
++ return __buffer_migrate_page(mapping, newpage, page, mode, true);
++}
+ #endif
+
+ /*
diff --git a/series.conf b/series.conf
index 6ba46b0d61..dbfceddf22 100644
--- a/series.conf
+++ b/series.conf
@@ -19699,6 +19699,7 @@
patches.fixes/0001-hwpoison-memory_hotplug-allow-hwpoisoned-pages-to-be.patch
patches.fixes/mm-migration-factor-out-code-to-compute-expected-num.patch
patches.fixes/mm-migrate-lock-buffers-before-migrate_page_move_map.patch
+ patches.fixes/mm-migrate-provide-buffer_migrate_page_norefs.patch
patches.drivers/gpiolib-Fix-return-value-of-gpio_to_desc-stub-if-GPI.patch
patches.drivers/power-supply-olpc_battery-correct-the-temperature-un.patch
patches.drivers/usb-dwc2-host-use-hrtimer-for-nak-retries.patch