aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2016-02-01 07:37:20 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2016-02-25 06:11:26 -0500
commit49e91e7079febe59a20ca885a87dd1c54240d0f1 (patch)
tree492560579a27a7658d2327f0e0a3a6eb825a303f
parent157078f64b8a9cd7011b6b900b2f2498df850748 (diff)
jffs2: Fix page lock / f->sem deadlock
With this fix, all code paths should now be obtaining the page lock before f->sem. Reported-by: Szabó Tamás <sztomi89@gmail.com> Tested-by: Thomas Betker <thomas.betker@rohde-schwarz.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Cc: stable@vger.kernel.org
-rw-r--r--fs/jffs2/README.Locking5
-rw-r--r--fs/jffs2/gc.c17
2 files changed, 11 insertions, 11 deletions
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index 3ea36554107f..8918ac905a3b 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -2,10 +2,6 @@
2 JFFS2 LOCKING DOCUMENTATION 2 JFFS2 LOCKING DOCUMENTATION
3 --------------------------- 3 ---------------------------
4 4
5At least theoretically, JFFS2 does not require the Big Kernel Lock
6(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
7code. It has its own locking, as described below.
8
9This document attempts to describe the existing locking rules for 5This document attempts to describe the existing locking rules for
10JFFS2. It is not expected to remain perfectly up to date, but ought to 6JFFS2. It is not expected to remain perfectly up to date, but ought to
11be fairly close. 7be fairly close.
@@ -69,6 +65,7 @@ Ordering constraints:
69 any f->sem held. 65 any f->sem held.
70 2. Never attempt to lock two file mutexes in one thread. 66 2. Never attempt to lock two file mutexes in one thread.
71 No ordering rules have been made for doing so. 67 No ordering rules have been made for doing so.
68 3. Never lock a page cache page with f->sem held.
72 69
73 70
74 erase_completion_lock spinlock 71 erase_completion_lock spinlock
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 5a2dec2b064c..95d5880a63ee 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
1296 BUG_ON(start > orig_start); 1296 BUG_ON(start > orig_start);
1297 } 1297 }
1298 1298
1299 /* First, use readpage() to read the appropriate page into the page cache */ 1299 /* The rules state that we must obtain the page lock *before* f->sem, so
1300 /* Q: What happens if we actually try to GC the _same_ page for which commit_write() 1300 * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
1301 * triggered garbage collection in the first place? 1301 * actually going to *change* so we're safe; we only allow reading.
1302 * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the 1302 *
1303 * page OK. We'll actually write it out again in commit_write, which is a little 1303 * It is important to note that jffs2_write_begin() will ensure that its
1304 * suboptimal, but at least we're correct. 1304 * page is marked Uptodate before allocating space. That means that if we
1305 */ 1305 * end up here trying to GC the *same* page that jffs2_write_begin() is
1306 * trying to write out, read_cache_page() will not deadlock. */
1307 mutex_unlock(&f->sem);
1306 pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); 1308 pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
1309 mutex_lock(&f->sem);
1307 1310
1308 if (IS_ERR(pg_ptr)) { 1311 if (IS_ERR(pg_ptr)) {
1309 pr_warn("read_cache_page() returned error: %ld\n", 1312 pr_warn("read_cache_page() returned error: %ld\n",