lkml.org 
[lkml]   [2017]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.10 61/63] locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y
    Date
    4.10-stable review patch.  If anyone has any objections, please let me know.

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

    From: Niklas Cassel <niklas.cassel@axis.com>

    commit 17fcbd590d0c3e35bd9646e2215f86586378bc42 upstream.

    We hang if SIGKILL has been sent, but the task is stuck in down_read()
    (after do_exit()), even though no task is doing down_write() on the
    rwsem in question:

    INFO: task libupnp:21868 blocked for more than 120 seconds.
    libupnp D 0 21868 1 0x08100008
    ...
    Call Trace:
    __schedule()
    schedule()
    __down_read()
    do_exit()
    do_group_exit()
    __wake_up_parent()

    This bug has already been fixed for CONFIG_RWSEM_XCHGADD_ALGORITHM=y in
    the following commit:

    04cafed7fc19 ("locking/rwsem: Fix down_write_killable()")

    ... however, this bug also exists for CONFIG_RWSEM_GENERIC_SPINLOCK=y.

    Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Cc: <mhocko@suse.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Niklas Cassel <niklass@axis.com>
    Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Fixes: d47996082f52 ("locking/rwsem: Introduce basis for down_write_killable()")
    Link: http://lkml.kernel.org/r/1487981873-12649-1-git-send-email-niklass@axis.com
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/locking/rwsem-spinlock.c | 15 ++++++++++-----
    1 file changed, 10 insertions(+), 5 deletions(-)

    --- a/kernel/locking/rwsem-spinlock.c
    +++ b/kernel/locking/rwsem-spinlock.c
    @@ -216,10 +216,8 @@ int __sched __down_write_common(struct r
    */
    if (sem->count == 0)
    break;
    - if (signal_pending_state(state, current)) {
    - ret = -EINTR;
    - goto out;
    - }
    + if (signal_pending_state(state, current))
    + goto out_nolock;
    set_task_state(tsk, state);
    raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
    schedule();
    @@ -227,12 +225,19 @@ int __sched __down_write_common(struct r
    }
    /* got the lock */
    sem->count = -1;
    -out:
    list_del(&waiter.list);

    raw_spin_unlock_irqrestore(&sem->wait_lock, flags);

    return ret;
    +
    +out_nolock:
    + list_del(&waiter.list);
    + if (!list_empty(&sem->wait_list))
    + __rwsem_do_wake(sem, 1);
    + raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
    +
    + return -EINTR;
    }

    void __sched __down_write(struct rw_semaphore *sem)

    \
     
     \ /
      Last update: 2017-03-20 19:13    [W:7.641 / U:0.508 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site