Skip to content

Commit d268675

Browse files
committed
Merge tag 'dm-4.8-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer: - a stable dm-flakey fix to error read IO during the 'down_interval' - a DM core suspend fix to establish the SUSPENDED flag before dropping the SUSPENDING flag - a blk-mq request-based DM (dm-mq) dm_stop_queue() fix to properly stop the blk-mq hw_queues (and cancel pending requeue work); also set/clear QUEUE_FLAG_STOPPED when stopping/starting the dm-mq request_queue. - a DM multipath fix to harden locking of in-core state flags in the face of concurrent access while handling path failures under heavy IO. - a few small DM raid fixes to edge cases caught with further testing. * tag 'dm-4.8-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm raid: fix use of wrong status char during resynchronization dm raid: constructor fails on non-zero incompat_features dm raid: fix processing of max_recovery_rate constructor flag dm: set DMF_SUSPENDED* _before_ clearing DMF_NOFLUSH_SUSPENDING dm rq: fix the starting and stopping of blk-mq queues dm mpath: add locking to multipath_resume and must_push_back dm flakey: error READ bios during the down_interval
2 parents fff648d + 2a034ec commit d268675

File tree

5 files changed

+63
-22
lines changed

5 files changed

+63
-22
lines changed

drivers/md/dm-flakey.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,16 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
289289
pb->bio_submitted = true;
290290

291291
/*
292-
* Map reads as normal.
292+
* Map reads as normal only if corrupt_bio_byte set.
293293
*/
294-
if (bio_data_dir(bio) == READ)
295-
goto map_bio;
294+
if (bio_data_dir(bio) == READ) {
295+
/* If flags were specified, only corrupt those that match. */
296+
if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
297+
all_corrupt_bio_flags_match(bio, fc))
298+
goto map_bio;
299+
else
300+
return -EIO;
301+
}
296302

297303
/*
298304
* Drop writes?
@@ -330,12 +336,13 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
330336

331337
/*
332338
* Corrupt successful READs while in down state.
333-
* If flags were specified, only corrupt those that match.
334339
*/
335-
if (fc->corrupt_bio_byte && !error && pb->bio_submitted &&
336-
(bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
337-
all_corrupt_bio_flags_match(bio, fc))
338-
corrupt_bio_data(bio, fc);
340+
if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
341+
if (fc->corrupt_bio_byte)
342+
corrupt_bio_data(bio, fc);
343+
else
344+
return -EIO;
345+
}
339346

340347
return error;
341348
}

drivers/md/dm-mpath.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,13 +507,27 @@ static bool __must_push_back(struct multipath *m)
507507

508508
static bool must_push_back_rq(struct multipath *m)
509509
{
510-
return (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
511-
__must_push_back(m));
510+
bool r;
511+
unsigned long flags;
512+
513+
spin_lock_irqsave(&m->lock, flags);
514+
r = (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
515+
__must_push_back(m));
516+
spin_unlock_irqrestore(&m->lock, flags);
517+
518+
return r;
512519
}
513520

514521
static bool must_push_back_bio(struct multipath *m)
515522
{
516-
return __must_push_back(m);
523+
bool r;
524+
unsigned long flags;
525+
526+
spin_lock_irqsave(&m->lock, flags);
527+
r = __must_push_back(m);
528+
spin_unlock_irqrestore(&m->lock, flags);
529+
530+
return r;
517531
}
518532

519533
/*
@@ -1680,12 +1694,14 @@ static void multipath_postsuspend(struct dm_target *ti)
16801694
static void multipath_resume(struct dm_target *ti)
16811695
{
16821696
struct multipath *m = ti->private;
1697+
unsigned long flags;
16831698

1699+
spin_lock_irqsave(&m->lock, flags);
16841700
if (test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags))
16851701
set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
16861702
else
16871703
clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
1688-
smp_mb__after_atomic();
1704+
spin_unlock_irqrestore(&m->lock, flags);
16891705
}
16901706

16911707
/*

drivers/md/dm-raid.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as,
12701270
}
12711271
rs->md.sync_speed_min = (int)value;
12721272
} else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE))) {
1273-
if (test_and_set_bit(__CTR_FLAG_MIN_RECOVERY_RATE, &rs->ctr_flags)) {
1273+
if (test_and_set_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags)) {
12741274
rs->ti->error = "Only one max_recovery_rate argument pair allowed";
12751275
return -EINVAL;
12761276
}
@@ -1960,6 +1960,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
19601960
sb->data_offset = cpu_to_le64(rdev->data_offset);
19611961
sb->new_data_offset = cpu_to_le64(rdev->new_data_offset);
19621962
sb->sectors = cpu_to_le64(rdev->sectors);
1963+
sb->incompat_features = cpu_to_le32(0);
19631964

19641965
/* Zero out the rest of the payload after the size of the superblock */
19651966
memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
@@ -3577,7 +3578,6 @@ static int raid_preresume(struct dm_target *ti)
35773578
/* Be prepared for mddev_resume() in raid_resume() */
35783579
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
35793580
if (mddev->recovery_cp && mddev->recovery_cp < MaxSector) {
3580-
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
35813581
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
35823582
mddev->resync_min = mddev->recovery_cp;
35833583
}

drivers/md/dm-rq.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ void dm_start_queue(struct request_queue *q)
7878
if (!q->mq_ops)
7979
dm_old_start_queue(q);
8080
else {
81+
queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, q);
8182
blk_mq_start_stopped_hw_queues(q, true);
8283
blk_mq_kick_requeue_list(q);
8384
}
@@ -101,8 +102,14 @@ void dm_stop_queue(struct request_queue *q)
101102
{
102103
if (!q->mq_ops)
103104
dm_old_stop_queue(q);
104-
else
105+
else {
106+
spin_lock_irq(q->queue_lock);
107+
queue_flag_set(QUEUE_FLAG_STOPPED, q);
108+
spin_unlock_irq(q->queue_lock);
109+
110+
blk_mq_cancel_requeue_work(q);
105111
blk_mq_stop_hw_queues(q);
112+
}
106113
}
107114

108115
static struct dm_rq_target_io *alloc_old_rq_tio(struct mapped_device *md,
@@ -864,6 +871,17 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
864871
dm_put_live_table(md, srcu_idx);
865872
}
866873

874+
/*
875+
* On suspend dm_stop_queue() handles stopping the blk-mq
876+
* request_queue BUT: even though the hw_queues are marked
877+
* BLK_MQ_S_STOPPED at that point there is still a race that
878+
* is allowing block/blk-mq.c to call ->queue_rq against a
879+
* hctx that it really shouldn't. The following check guards
880+
* against this rarity (albeit _not_ race-free).
881+
*/
882+
if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
883+
return BLK_MQ_RQ_QUEUE_BUSY;
884+
867885
if (ti->type->busy && ti->type->busy(ti))
868886
return BLK_MQ_RQ_QUEUE_BUSY;
869887

drivers/md/dm.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,8 @@ static void unlock_fs(struct mapped_device *md)
20822082
* Caller must hold md->suspend_lock
20832083
*/
20842084
static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
2085-
unsigned suspend_flags, int interruptible)
2085+
unsigned suspend_flags, int interruptible,
2086+
int dmf_suspended_flag)
20862087
{
20872088
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
20882089
bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
@@ -2149,6 +2150,8 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
21492150
* to finish.
21502151
*/
21512152
r = dm_wait_for_completion(md, interruptible);
2153+
if (!r)
2154+
set_bit(dmf_suspended_flag, &md->flags);
21522155

21532156
if (noflush)
21542157
clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
@@ -2210,12 +2213,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
22102213

22112214
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
22122215

2213-
r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE);
2216+
r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
22142217
if (r)
22152218
goto out_unlock;
22162219

2217-
set_bit(DMF_SUSPENDED, &md->flags);
2218-
22192220
dm_table_postsuspend_targets(map);
22202221

22212222
out_unlock:
@@ -2309,9 +2310,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
23092310
* would require changing .presuspend to return an error -- avoid this
23102311
* until there is a need for more elaborate variants of internal suspend.
23112312
*/
2312-
(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE);
2313-
2314-
set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
2313+
(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
2314+
DMF_SUSPENDED_INTERNALLY);
23152315

23162316
dm_table_postsuspend_targets(map);
23172317
}

0 commit comments

Comments
 (0)