Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 19 Sep 2017 15:39:32 +0000 (08:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 19 Sep 2017 15:39:32 +0000 (08:39 -0700)
Pull MD fixes from Shaohua Li:
 "Two small patches to fix long-lived raid5 stripe batch bugs, one from
  Dennis and the other from me"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md:
  md/raid5: preserve STRIPE_ON_UNPLUG_LIST in break_stripe_batch_list
  md/raid5: fix a race condition in stripe batch

1  2 
drivers/md/raid5.c

diff --combined drivers/md/raid5.c
index 4188a488114814aadf7df7b4c2ba07240b8e0408,34c01e83395af4b618cd56189a1fe4f14d44ae8a..076409455b603582f589ea8fcc68173d421ca33a
@@@ -811,6 -811,14 +811,14 @@@ static void stripe_add_to_batch_list(st
                        spin_unlock(&head->batch_head->batch_lock);
                        goto unlock_out;
                }
+               /*
+                * We must assign batch_head of this stripe within the
+                * batch_lock, otherwise clear_batch_ready of batch head
+                * stripe could clear BATCH_READY bit of this stripe and
+                * this stripe->batch_head doesn't get assigned, which
+                * could confuse clear_batch_ready for this stripe
+                */
+               sh->batch_head = head->batch_head;
  
                /*
                 * at this point, head's BATCH_READY could be cleared, but we
                 */
                list_add(&sh->batch_list, &head->batch_list);
                spin_unlock(&head->batch_head->batch_lock);
-               sh->batch_head = head->batch_head;
        } else {
                head->batch_head = head;
                sh->batch_head = head->batch_head;
@@@ -1095,7 -1101,7 +1101,7 @@@ again
  
                        set_bit(STRIPE_IO_STARTED, &sh->state);
  
 -                      bi->bi_bdev = rdev->bdev;
 +                      bio_set_dev(bi, rdev->bdev);
                        bio_set_op_attrs(bi, op, op_flags);
                        bi->bi_end_io = op_is_write(op)
                                ? raid5_end_write_request
                                set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
  
                        if (conf->mddev->gendisk)
 -                              trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
 +                              trace_block_bio_remap(bi->bi_disk->queue,
                                                      bi, disk_devt(conf->mddev->gendisk),
                                                      sh->dev[i].sector);
                        if (should_defer && op_is_write(op))
  
                        set_bit(STRIPE_IO_STARTED, &sh->state);
  
 -                      rbi->bi_bdev = rrdev->bdev;
 +                      bio_set_dev(rbi, rrdev->bdev);
                        bio_set_op_attrs(rbi, op, op_flags);
                        BUG_ON(!op_is_write(op));
                        rbi->bi_end_io = raid5_end_write_request;
                        if (op == REQ_OP_DISCARD)
                                rbi->bi_vcnt = 0;
                        if (conf->mddev->gendisk)
 -                              trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
 +                              trace_block_bio_remap(rbi->bi_disk->queue,
                                                      rbi, disk_devt(conf->mddev->gendisk),
                                                      sh->dev[i].sector);
                        if (should_defer && op_is_write(op))
@@@ -4599,7 -4605,8 +4605,8 @@@ static void break_stripe_batch_list(str
  
                set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS |
                                            (1 << STRIPE_PREREAD_ACTIVE) |
-                                           (1 << STRIPE_DEGRADED)),
+                                           (1 << STRIPE_DEGRADED) |
+                                           (1 << STRIPE_ON_UNPLUG_LIST)),
                              head_sh->state & (1 << STRIPE_INSYNC));
  
                sh->check_state = head_sh->check_state;
@@@ -5083,12 -5090,10 +5090,12 @@@ static int raid5_congested(struct mdde
  static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
  {
        struct r5conf *conf = mddev->private;
 -      sector_t sector = bio->bi_iter.bi_sector + get_start_sect(bio->bi_bdev);
 +      sector_t sector = bio->bi_iter.bi_sector;
        unsigned int chunk_sectors;
        unsigned int bio_sectors = bio_sectors(bio);
  
 +      WARN_ON_ONCE(bio->bi_partno);
 +
        chunk_sectors = min(conf->chunk_sectors, conf->prev_chunk_sectors);
        return  chunk_sectors >=
                ((sector & (chunk_sectors - 1)) + bio_sectors);
@@@ -5224,7 -5229,7 +5231,7 @@@ static int raid5_read_one_chunk(struct 
                atomic_inc(&rdev->nr_pending);
                rcu_read_unlock();
                raid_bio->bi_next = (void*)rdev;
 -              align_bi->bi_bdev =  rdev->bdev;
 +              bio_set_dev(align_bi, rdev->bdev);
                bio_clear_flag(align_bi, BIO_SEG_VALID);
  
                if (is_badblock(rdev, align_bi->bi_iter.bi_sector,
                spin_unlock_irq(&conf->device_lock);
  
                if (mddev->gendisk)
 -                      trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
 +                      trace_block_bio_remap(align_bi->bi_disk->queue,
                                              align_bi, disk_devt(mddev->gendisk),
                                              raid_bio->bi_iter.bi_sector);
                generic_make_request(align_bi);