lkml.org 
[lkml]   [2022]   [Apr]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH v2 10/12] md/raid5: Refactor add_stripe_bio()
    Factor out two helper functions from add_stripe_bio(): one to check for
    overlap (stripe_bio_overlaps()), and one to actually add the bio to the
    stripe (__add_stripe_bio()). The latter function will always succeed.

    This will be useful in the next patch so that overlap can be checked for
    multiple disks before adding any

    Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
    ---
    drivers/md/raid5.c | 86 ++++++++++++++++++++++++++++++----------------
    1 file changed, 56 insertions(+), 30 deletions(-)

    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 28ea7b9b6ab6..1fa82d8fa89e 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3418,39 +3418,32 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
    s->locked, s->ops_request);
    }

    -/*
    - * Each stripe/dev can have one or more bion attached.
    - * toread/towrite point to the first in a chain.
    - * The bi_next chain must be in order.
    - */
    -static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
    - int forwrite, int previous)
    +static bool stripe_bio_overlaps(struct stripe_head *sh, struct bio *bi,
    + int dd_idx, int forwrite)
    {
    - struct bio **bip;
    struct r5conf *conf = sh->raid_conf;
    - int firstwrite=0;
    + struct bio **bip;

    - pr_debug("adding bi b#%llu to stripe s#%llu\n",
    - (unsigned long long)bi->bi_iter.bi_sector,
    - (unsigned long long)sh->sector);
    + pr_debug("checking bi b#%llu to stripe s#%llu\n",
    + bi->bi_iter.bi_sector, sh->sector);

    - spin_lock_irq(&sh->stripe_lock);
    /* Don't allow new IO added to stripes in batch list */
    if (sh->batch_head)
    - goto overlap;
    - if (forwrite) {
    + return true;
    +
    + if (forwrite)
    bip = &sh->dev[dd_idx].towrite;
    - if (*bip == NULL)
    - firstwrite = 1;
    - } else
    + else
    bip = &sh->dev[dd_idx].toread;
    +
    while (*bip && (*bip)->bi_iter.bi_sector < bi->bi_iter.bi_sector) {
    if (bio_end_sector(*bip) > bi->bi_iter.bi_sector)
    - goto overlap;
    - bip = & (*bip)->bi_next;
    + return true;
    + bip = &(*bip)->bi_next;
    }
    +
    if (*bip && (*bip)->bi_iter.bi_sector < bio_end_sector(bi))
    - goto overlap;
    + return true;

    if (forwrite && raid5_has_ppl(conf)) {
    /*
    @@ -3479,9 +3472,30 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
    }

    if (first + conf->chunk_sectors * (count - 1) != last)
    - goto overlap;
    + return true;
    }

    + return false;
    +}
    +
    +static void __add_stripe_bio(struct stripe_head *sh, struct bio *bi,
    + int dd_idx, int forwrite, int previous)
    +{
    + struct r5conf *conf = sh->raid_conf;
    + struct bio **bip;
    + int firstwrite = 0;
    +
    + if (forwrite) {
    + bip = &sh->dev[dd_idx].towrite;
    + if (!*bip)
    + firstwrite = 1;
    + } else {
    + bip = &sh->dev[dd_idx].toread;
    + }
    +
    + while (*bip && (*bip)->bi_iter.bi_sector < bi->bi_iter.bi_sector)
    + bip = &(*bip)->bi_next;
    +
    if (!forwrite || previous)
    clear_bit(STRIPE_BATCH_READY, &sh->state);

    @@ -3508,8 +3522,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
    }

    pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
    - (unsigned long long)(*bip)->bi_iter.bi_sector,
    - (unsigned long long)sh->sector, dd_idx);
    + (*bip)->bi_iter.bi_sector, sh->sector, dd_idx);

    if (conf->mddev->bitmap && firstwrite) {
    /* Cannot hold spinlock over bitmap_startwrite,
    @@ -3517,7 +3530,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
    * we have added to the bitmap and set bm_seq.
    * So set STRIPE_BITMAP_PENDING to prevent
    * batching.
    - * If multiple add_stripe_bio() calls race here they
    + * If multiple __add_stripe_bio() calls race here they
    * much all set STRIPE_BITMAP_PENDING. So only the first one
    * to complete "bitmap_startwrite" gets to set
    * STRIPE_BIT_DELAY. This is important as once a stripe
    @@ -3535,14 +3548,27 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
    set_bit(STRIPE_BIT_DELAY, &sh->state);
    }
    }
    - spin_unlock_irq(&sh->stripe_lock);
    +}

    - return 1;
    +/*
    + * Each stripe/dev can have one or more bios attached.
    + * toread/towrite point to the first in a chain.
    + * The bi_next chain must be in order.
    + */
    +static bool add_stripe_bio(struct stripe_head *sh, struct bio *bi,
    + int dd_idx, int forwrite, int previous)
    +{
    + spin_lock_irq(&sh->stripe_lock);

    - overlap:
    - set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
    + if (stripe_bio_overlaps(sh, bi, dd_idx, forwrite)) {
    + set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
    + spin_unlock_irq(&sh->stripe_lock);
    + return false;
    + }
    +
    + __add_stripe_bio(sh, bi, dd_idx, forwrite, previous);
    spin_unlock_irq(&sh->stripe_lock);
    - return 0;
    + return true;
    }

    static void end_reshape(struct r5conf *conf);
    --
    2.30.2
    \
     
     \ /
      Last update: 2022-04-20 21:57    [W:3.471 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site