lkml.org 
[lkml]   [2010]   [Aug]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[20/54] md/raid10: fix deadlock with unaligned read during resync
    2.6.34-stable review patch.  If anyone has any objections, please let us know.

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

    From: NeilBrown <neilb@suse.de>

    commit 51e9ac77035a3dfcb6fc0a88a0d80b6f99b5edb1 upstream.

    If the 'bio_split' path in raid10-read is used while
    resync/recovery is happening it is possible to deadlock.
    Fix this be elevating ->nr_waiting for the duration of both
    parts of the split request.

    This fixes a bug that has been present since 2.6.22
    but has only started manifesting recently for unknown reasons.
    It is suitable for and -stable since then.

    Reported-by: Justin Bronder <jsbronder@gentoo.org>
    Tested-by: Justin Bronder <jsbronder@gentoo.org>
    Signed-off-by: NeilBrown <neilb@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/md/raid10.c | 18 ++++++++++++++++++
    1 file changed, 18 insertions(+)

    --- a/drivers/md/raid10.c
    +++ b/drivers/md/raid10.c
    @@ -825,11 +825,29 @@ static int make_request(struct request_q
    */
    bp = bio_split(bio,
    chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
    +
    + /* Each of these 'make_request' calls will call 'wait_barrier'.
    + * If the first succeeds but the second blocks due to the resync
    + * thread raising the barrier, we will deadlock because the
    + * IO to the underlying device will be queued in generic_make_request
    + * and will never complete, so will never reduce nr_pending.
    + * So increment nr_waiting here so no new raise_barriers will
    + * succeed, and so the second wait_barrier cannot block.
    + */
    + spin_lock_irq(&conf->resync_lock);
    + conf->nr_waiting++;
    + spin_unlock_irq(&conf->resync_lock);
    +
    if (make_request(q, &bp->bio1))
    generic_make_request(&bp->bio1);
    if (make_request(q, &bp->bio2))
    generic_make_request(&bp->bio2);

    + spin_lock_irq(&conf->resync_lock);
    + conf->nr_waiting--;
    + wake_up(&conf->wait_barrier);
    + spin_unlock_irq(&conf->resync_lock);
    +
    bio_pair_release(bp);
    return 0;
    bad_map:



    \
     
     \ /
      Last update: 2010-08-12 02:27    [W:0.031 / U:1.036 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site