lkml.org 
[lkml]   [2016]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 38/62] jffs2: Fix page lock / f->sem deadlock
    3.2.79-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: David Woodhouse <David.Woodhouse@intel.com>

    commit 49e91e7079febe59a20ca885a87dd1c54240d0f1 upstream.

    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>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    fs/jffs2/README.Locking | 5 +----
    fs/jffs2/gc.c | 17 ++++++++++-------
    2 files changed, 11 insertions(+), 11 deletions(-)

    --- a/fs/jffs2/README.Locking
    +++ b/fs/jffs2/README.Locking
    @@ -2,10 +2,6 @@
    JFFS2 LOCKING DOCUMENTATION
    ---------------------------

    -At least theoretically, JFFS2 does not require the Big Kernel Lock
    -(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
    -code. It has its own locking, as described below.
    -
    This document attempts to describe the existing locking rules for
    JFFS2. It is not expected to remain perfectly up to date, but ought to
    be fairly close.
    @@ -69,6 +65,7 @@ Ordering constraints:
    any f->sem held.
    2. Never attempt to lock two file mutexes in one thread.
    No ordering rules have been made for doing so.
    + 3. Never lock a page cache page with f->sem held.


    erase_completion_lock spinlock
    --- a/fs/jffs2/gc.c
    +++ b/fs/jffs2/gc.c
    @@ -1246,14 +1246,17 @@ static int jffs2_garbage_collect_dnode(s
    BUG_ON(start > orig_start);
    }

    - /* First, use readpage() to read the appropriate page into the page cache */
    - /* Q: What happens if we actually try to GC the _same_ page for which commit_write()
    - * triggered garbage collection in the first place?
    - * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
    - * page OK. We'll actually write it out again in commit_write, which is a little
    - * suboptimal, but at least we're correct.
    - */
    + /* The rules state that we must obtain the page lock *before* f->sem, so
    + * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
    + * actually going to *change* so we're safe; we only allow reading.
    + *
    + * It is important to note that jffs2_write_begin() will ensure that its
    + * page is marked Uptodate before allocating space. That means that if we
    + * end up here trying to GC the *same* page that jffs2_write_begin() is
    + * trying to write out, read_cache_page() will not deadlock. */
    + mutex_unlock(&f->sem);
    pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
    + mutex_lock(&f->sem);

    if (IS_ERR(pg_ptr)) {
    printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg_ptr));
    \
     
     \ /
      Last update: 2016-03-29 22:41    [W:2.337 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site