Merge tag 'md/3.12-fixes' of git://neil.brown.name/md
Pull md bugfixes from Neil Brown: "Assorted md bug-fixes for 3.12. All tagged for -stable releases too" * tag 'md/3.12-fixes' of git://neil.brown.name/md: raid5: avoid finding "discard" stripe raid5: set bio bi_vcnt 0 for discard request md: avoid deadlock when md_set_badblocks. md: Fix skipping recovery for read-only arrays.
This commit is contained in:
@@ -8111,6 +8111,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
|
||||
u64 *p;
|
||||
int lo, hi;
|
||||
int rv = 1;
|
||||
unsigned long flags;
|
||||
|
||||
if (bb->shift < 0)
|
||||
/* badblocks are disabled */
|
||||
@@ -8125,7 +8126,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
|
||||
sectors = next - s;
|
||||
}
|
||||
|
||||
write_seqlock_irq(&bb->lock);
|
||||
write_seqlock_irqsave(&bb->lock, flags);
|
||||
|
||||
p = bb->page;
|
||||
lo = 0;
|
||||
@@ -8241,7 +8242,7 @@ static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
|
||||
bb->changed = 1;
|
||||
if (!acknowledged)
|
||||
bb->unacked_exist = 1;
|
||||
write_sequnlock_irq(&bb->lock);
|
||||
write_sequnlock_irqrestore(&bb->lock, flags);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@@ -1479,6 +1479,7 @@ static int raid1_spare_active(struct mddev *mddev)
|
||||
}
|
||||
}
|
||||
if (rdev
|
||||
&& rdev->recovery_offset == MaxSector
|
||||
&& !test_bit(Faulty, &rdev->flags)
|
||||
&& !test_and_set_bit(In_sync, &rdev->flags)) {
|
||||
count++;
|
||||
|
@@ -1782,6 +1782,7 @@ static int raid10_spare_active(struct mddev *mddev)
|
||||
}
|
||||
sysfs_notify_dirent_safe(tmp->replacement->sysfs_state);
|
||||
} else if (tmp->rdev
|
||||
&& tmp->rdev->recovery_offset == MaxSector
|
||||
&& !test_bit(Faulty, &tmp->rdev->flags)
|
||||
&& !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
|
||||
count++;
|
||||
|
@@ -778,6 +778,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
|
||||
bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
|
||||
bi->bi_io_vec[0].bv_offset = 0;
|
||||
bi->bi_size = STRIPE_SIZE;
|
||||
/*
|
||||
* If this is discard request, set bi_vcnt 0. We don't
|
||||
* want to confuse SCSI because SCSI will replace payload
|
||||
*/
|
||||
if (rw & REQ_DISCARD)
|
||||
bi->bi_vcnt = 0;
|
||||
if (rrdev)
|
||||
set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
|
||||
|
||||
@@ -816,6 +822,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
|
||||
rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
|
||||
rbi->bi_io_vec[0].bv_offset = 0;
|
||||
rbi->bi_size = STRIPE_SIZE;
|
||||
/*
|
||||
* If this is discard request, set bi_vcnt 0. We don't
|
||||
* want to confuse SCSI because SCSI will replace payload
|
||||
*/
|
||||
if (rw & REQ_DISCARD)
|
||||
rbi->bi_vcnt = 0;
|
||||
if (conf->mddev->gendisk)
|
||||
trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
|
||||
rbi, disk_devt(conf->mddev->gendisk),
|
||||
@@ -2910,6 +2922,14 @@ static void handle_stripe_clean_event(struct r5conf *conf,
|
||||
}
|
||||
/* now that discard is done we can proceed with any sync */
|
||||
clear_bit(STRIPE_DISCARD, &sh->state);
|
||||
/*
|
||||
* SCSI discard will change some bio fields and the stripe has
|
||||
* no updated data, so remove it from hash list and the stripe
|
||||
* will be reinitialized
|
||||
*/
|
||||
spin_lock_irq(&conf->device_lock);
|
||||
remove_hash(sh);
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
|
||||
set_bit(STRIPE_HANDLE, &sh->state);
|
||||
|
||||
|
Reference in New Issue
Block a user