Home Home > GIT Browse > SLE11-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2019-01-07 10:42:28 +1100
committerNeilBrown <neilb@suse.com>2019-01-07 14:04:37 +1100
commitb59351e055b3f04e5b1ea995e7dd7010fda7c49f (patch)
tree0e819d8c3626fa460d869cf104684a6092c15072
parent1ff345db7f5e8e893562343c79bd971606c00f67 (diff)
fscache: Fix race in fscache_op_complete() due to split
atomic_sub & read (git-fixes).
-rw-r--r--patches.fixes/fscache-Fix-race-in-fscache_op_complete-due-to-split.patch70
-rw-r--r--series.conf1
2 files changed, 71 insertions, 0 deletions
diff --git a/patches.fixes/fscache-Fix-race-in-fscache_op_complete-due-to-split.patch b/patches.fixes/fscache-Fix-race-in-fscache_op_complete-due-to-split.patch
new file mode 100644
index 0000000000..0c4bffdc9d
--- /dev/null
+++ b/patches.fixes/fscache-Fix-race-in-fscache_op_complete-due-to-split.patch
@@ -0,0 +1,70 @@
+From: "kiran.modukuri" <kiran.modukuri@gmail.com>
+Date: Mon, 26 Nov 2018 15:41:48 +0000
+Subject: [PATCH] fscache: Fix race in fscache_op_complete() due to split
+ atomic_sub & read
+Git-commit: 3f2b7b9035107d6096ea438ea3d97dcf0481b6d2
+Patch-mainline: v4.20
+References: git-fixes
+
+The code in fscache_retrieval_complete is using atomic_sub followed by an
+Atomic_read:
+
+ atomic_sub(n_pages, &op->n_pages);
+ if (atomic_read(&op->n_pages) <= 0)
+ fscache_op_complete(&op->op, true);
+
+This causes two threads doing a decrement of n_pages to race with each
+other seeing the op->refcount 0 at same time - and they end up calling
+fscache_op_complete() in both the threads leading to an assertion failure.
+
+Fix this by using atomic_sub_return() instead of two calls. Note
+that I'm using 'relaxed' rather than, say, 'release' as there aren't
+multiple variables that appear to need ordering across the release.
+
+The oops looks something like:
+
+Fs-cache: Assertion failed
+Fs-cache: 0 > 0 is false
+...
+kernel BUG at /usr/src/linux-4.4.0/fs/fscache/operation.c:449!
+...
+Workqueue: fscache_operation fscache_op_work_func [fscache]
+...
+Rip: 0010:[<ffffffffc037eacd>] fscache_op_complete+0x10d/0x180 [fscache]
+...
+Call Trace:
+ [<ffffffffc1464cf9>] cachefiles_read_copier+0x3a9/0x410 [cachefiles]
+ [<ffffffffc037e272>] fscache_op_work_func+0x22/0x50 [fscache]
+ [<ffffffff81096da0>] process_one_work+0x150/0x3f0
+ [<ffffffff8109751a>] worker_thread+0x11a/0x470
+ [<ffffffff81808e59>] ? __schedule+0x359/0x980
+ [<ffffffff81097400>] ? rescuer_thread+0x310/0x310
+ [<ffffffff8109cdd6>] kthread+0xd6/0xf0
+ [<ffffffff8109cd00>] ? kthread_park+0x60/0x60
+ [<ffffffff8180d0cf>] ret_from_fork+0x3f/0x70
+ [<ffffffff8109cd00>] ? kthread_park+0x60/0x60
+
+This seen this in 4.4.x kernels and the same bug affects fscache in latest
+upstreams kernels.
+
+Fixes: 1bb4b7f98f36 ("FS-Cache: The retrieval remaining-pages counter needs to be atomic_t")
+Signed-off-by: Kiran Kumar Modukuri <kiran.modukuri@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Acked-by: NeilBrown <neilb@suse.com>
+
+---
+ include/linux/fscache-cache.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/include/linux/fscache-cache.h
++++ b/include/linux/fscache-cache.h
+@@ -195,8 +195,7 @@ static inline void fscache_enqueue_retri
+ static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
+ int n_pages)
+ {
+- atomic_sub(n_pages, &op->n_pages);
+- if (atomic_read(&op->n_pages) <= 0)
++ if (atomic_sub_return(n_pages, &op->n_pages) <= 0)
+ fscache_op_complete(&op->op, true);
+ }
+
diff --git a/series.conf b/series.conf
index 5f25b35fbd..ec43fabcaf 100644
--- a/series.conf
+++ b/series.conf
@@ -6739,6 +6739,7 @@
patches.suse/ubifs-check-for-name-being-null-while-mounting.patch
patches.fixes/0001-FS-Cache-Synchronise-object-death-state-change-vs-op.patch
patches.fixes/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch
+ patches.fixes/fscache-Fix-race-in-fscache_op_complete-due-to-split.patch
########################################################
# Swap-over-NFS