diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-28 12:27:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-28 12:27:58 -0400 |
commit | e0f3e6a7ccc002be056b6a21768fceee0d44941e (patch) | |
tree | 2a37947a080ea84ef14d8d0a68c5e995e0505bf7 /drivers/md | |
parent | 43937003de5b677781b2fe4c871d628ab00cc341 (diff) | |
parent | dafa724bf582181d9a7d54f5cb4ca0bf8ef29269 (diff) |
Merge tag 'dm-4.9-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer:
- a couple DM raid and DM mirror fixes
- a couple .request_fn request-based DM NULL pointer fixes
- a fix for a DM target reference count leak, on target load error,
that prevented associated DM target kernel module(s) from being
removed
* tag 'dm-4.9-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm table: fix missing dm_put_target_type() in dm_table_add_target()
dm rq: clear kworker_task if kthread_run() returned an error
dm: free io_barrier after blk_cleanup_queue call
dm raid: fix activation of existing raid4/10 devices
dm mirror: use all available legs on multiple failures
dm mirror: fix read error on recovery after default leg failure
dm raid: fix compat_features validation
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-raid.c | 15 | ||||
-rw-r--r-- | drivers/md/dm-raid1.c | 22 | ||||
-rw-r--r-- | drivers/md/dm-rq.c | 7 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 24 | ||||
-rw-r--r-- | drivers/md/dm.c | 4 |
5 files changed, 28 insertions, 44 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 8abde6b8cedc..6d53810963f7 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -266,7 +266,7 @@ static struct raid_type { | |||
266 | {"raid10_offset", "raid10 offset (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_OFFSET}, | 266 | {"raid10_offset", "raid10 offset (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_OFFSET}, |
267 | {"raid10_near", "raid10 near (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_NEAR}, | 267 | {"raid10_near", "raid10 near (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_NEAR}, |
268 | {"raid10", "raid10 (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_DEFAULT}, | 268 | {"raid10", "raid10 (striped mirrors)", 0, 2, 10, ALGORITHM_RAID10_DEFAULT}, |
269 | {"raid4", "raid4 (dedicated last parity disk)", 1, 2, 4, ALGORITHM_PARITY_N}, /* raid4 layout = raid5_n */ | 269 | {"raid4", "raid4 (dedicated first parity disk)", 1, 2, 5, ALGORITHM_PARITY_0}, /* raid4 layout = raid5_0 */ |
270 | {"raid5_n", "raid5 (dedicated last parity disk)", 1, 2, 5, ALGORITHM_PARITY_N}, | 270 | {"raid5_n", "raid5 (dedicated last parity disk)", 1, 2, 5, ALGORITHM_PARITY_N}, |
271 | {"raid5_ls", "raid5 (left symmetric)", 1, 2, 5, ALGORITHM_LEFT_SYMMETRIC}, | 271 | {"raid5_ls", "raid5 (left symmetric)", 1, 2, 5, ALGORITHM_LEFT_SYMMETRIC}, |
272 | {"raid5_rs", "raid5 (right symmetric)", 1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC}, | 272 | {"raid5_rs", "raid5 (right symmetric)", 1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC}, |
@@ -2087,11 +2087,11 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev) | |||
2087 | /* | 2087 | /* |
2088 | * No takeover/reshaping, because we don't have the extended v1.9.0 metadata | 2088 | * No takeover/reshaping, because we don't have the extended v1.9.0 metadata |
2089 | */ | 2089 | */ |
2090 | if (le32_to_cpu(sb->level) != mddev->level) { | 2090 | if (le32_to_cpu(sb->level) != mddev->new_level) { |
2091 | DMERR("Reshaping/takeover raid sets not yet supported. (raid level/stripes/size change)"); | 2091 | DMERR("Reshaping/takeover raid sets not yet supported. (raid level/stripes/size change)"); |
2092 | return -EINVAL; | 2092 | return -EINVAL; |
2093 | } | 2093 | } |
2094 | if (le32_to_cpu(sb->layout) != mddev->layout) { | 2094 | if (le32_to_cpu(sb->layout) != mddev->new_layout) { |
2095 | DMERR("Reshaping raid sets not yet supported. (raid layout change)"); | 2095 | DMERR("Reshaping raid sets not yet supported. (raid layout change)"); |
2096 | DMERR(" 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout); | 2096 | DMERR(" 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout); |
2097 | DMERR(" Old layout: %s w/ %d copies", | 2097 | DMERR(" Old layout: %s w/ %d copies", |
@@ -2102,7 +2102,7 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev) | |||
2102 | raid10_md_layout_to_copies(mddev->layout)); | 2102 | raid10_md_layout_to_copies(mddev->layout)); |
2103 | return -EINVAL; | 2103 | return -EINVAL; |
2104 | } | 2104 | } |
2105 | if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) { | 2105 | if (le32_to_cpu(sb->stripe_sectors) != mddev->new_chunk_sectors) { |
2106 | DMERR("Reshaping raid sets not yet supported. (stripe sectors change)"); | 2106 | DMERR("Reshaping raid sets not yet supported. (stripe sectors change)"); |
2107 | return -EINVAL; | 2107 | return -EINVAL; |
2108 | } | 2108 | } |
@@ -2115,6 +2115,8 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev) | |||
2115 | return -EINVAL; | 2115 | return -EINVAL; |
2116 | } | 2116 | } |
2117 | 2117 | ||
2118 | DMINFO("Discovered old metadata format; upgrading to extended metadata format"); | ||
2119 | |||
2118 | /* Table line is checked vs. authoritative superblock */ | 2120 | /* Table line is checked vs. authoritative superblock */ |
2119 | rs_set_new(rs); | 2121 | rs_set_new(rs); |
2120 | } | 2122 | } |
@@ -2258,7 +2260,8 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev) | |||
2258 | if (!mddev->events && super_init_validation(rs, rdev)) | 2260 | if (!mddev->events && super_init_validation(rs, rdev)) |
2259 | return -EINVAL; | 2261 | return -EINVAL; |
2260 | 2262 | ||
2261 | if (le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) { | 2263 | if (le32_to_cpu(sb->compat_features) && |
2264 | le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) { | ||
2262 | rs->ti->error = "Unable to assemble array: Unknown flag(s) in compatible feature flags"; | 2265 | rs->ti->error = "Unable to assemble array: Unknown flag(s) in compatible feature flags"; |
2263 | return -EINVAL; | 2266 | return -EINVAL; |
2264 | } | 2267 | } |
@@ -3646,7 +3649,7 @@ static void raid_resume(struct dm_target *ti) | |||
3646 | 3649 | ||
3647 | static struct target_type raid_target = { | 3650 | static struct target_type raid_target = { |
3648 | .name = "raid", | 3651 | .name = "raid", |
3649 | .version = {1, 9, 0}, | 3652 | .version = {1, 9, 1}, |
3650 | .module = THIS_MODULE, | 3653 | .module = THIS_MODULE, |
3651 | .ctr = raid_ctr, | 3654 | .ctr = raid_ctr, |
3652 | .dtr = raid_dtr, | 3655 | .dtr = raid_dtr, |
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index bdf1606f67bc..9a8b71067c6e 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -145,7 +145,6 @@ static void dispatch_bios(void *context, struct bio_list *bio_list) | |||
145 | 145 | ||
146 | struct dm_raid1_bio_record { | 146 | struct dm_raid1_bio_record { |
147 | struct mirror *m; | 147 | struct mirror *m; |
148 | /* if details->bi_bdev == NULL, details were not saved */ | ||
149 | struct dm_bio_details details; | 148 | struct dm_bio_details details; |
150 | region_t write_region; | 149 | region_t write_region; |
151 | }; | 150 | }; |
@@ -1200,8 +1199,6 @@ static int mirror_map(struct dm_target *ti, struct bio *bio) | |||
1200 | struct dm_raid1_bio_record *bio_record = | 1199 | struct dm_raid1_bio_record *bio_record = |
1201 | dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); | 1200 | dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); |
1202 | 1201 | ||
1203 | bio_record->details.bi_bdev = NULL; | ||
1204 | |||
1205 | if (rw == WRITE) { | 1202 | if (rw == WRITE) { |
1206 | /* Save region for mirror_end_io() handler */ | 1203 | /* Save region for mirror_end_io() handler */ |
1207 | bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); | 1204 | bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); |
@@ -1260,22 +1257,12 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) | |||
1260 | } | 1257 | } |
1261 | 1258 | ||
1262 | if (error == -EOPNOTSUPP) | 1259 | if (error == -EOPNOTSUPP) |
1263 | goto out; | 1260 | return error; |
1264 | 1261 | ||
1265 | if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD)) | 1262 | if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD)) |
1266 | goto out; | 1263 | return error; |
1267 | 1264 | ||
1268 | if (unlikely(error)) { | 1265 | if (unlikely(error)) { |
1269 | if (!bio_record->details.bi_bdev) { | ||
1270 | /* | ||
1271 | * There wasn't enough memory to record necessary | ||
1272 | * information for a retry or there was no other | ||
1273 | * mirror in-sync. | ||
1274 | */ | ||
1275 | DMERR_LIMIT("Mirror read failed."); | ||
1276 | return -EIO; | ||
1277 | } | ||
1278 | |||
1279 | m = bio_record->m; | 1266 | m = bio_record->m; |
1280 | 1267 | ||
1281 | DMERR("Mirror read failed from %s. Trying alternative device.", | 1268 | DMERR("Mirror read failed from %s. Trying alternative device.", |
@@ -1291,7 +1278,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) | |||
1291 | bd = &bio_record->details; | 1278 | bd = &bio_record->details; |
1292 | 1279 | ||
1293 | dm_bio_restore(bd, bio); | 1280 | dm_bio_restore(bd, bio); |
1294 | bio_record->details.bi_bdev = NULL; | 1281 | bio->bi_error = 0; |
1295 | 1282 | ||
1296 | queue_bio(ms, bio, rw); | 1283 | queue_bio(ms, bio, rw); |
1297 | return DM_ENDIO_INCOMPLETE; | 1284 | return DM_ENDIO_INCOMPLETE; |
@@ -1299,9 +1286,6 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) | |||
1299 | DMERR("All replicated volumes dead, failing I/O"); | 1286 | DMERR("All replicated volumes dead, failing I/O"); |
1300 | } | 1287 | } |
1301 | 1288 | ||
1302 | out: | ||
1303 | bio_record->details.bi_bdev = NULL; | ||
1304 | |||
1305 | return error; | 1289 | return error; |
1306 | } | 1290 | } |
1307 | 1291 | ||
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index dc75bea0d541..1d0d2adc050a 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c | |||
@@ -856,8 +856,11 @@ int dm_old_init_request_queue(struct mapped_device *md) | |||
856 | kthread_init_worker(&md->kworker); | 856 | kthread_init_worker(&md->kworker); |
857 | md->kworker_task = kthread_run(kthread_worker_fn, &md->kworker, | 857 | md->kworker_task = kthread_run(kthread_worker_fn, &md->kworker, |
858 | "kdmwork-%s", dm_device_name(md)); | 858 | "kdmwork-%s", dm_device_name(md)); |
859 | if (IS_ERR(md->kworker_task)) | 859 | if (IS_ERR(md->kworker_task)) { |
860 | return PTR_ERR(md->kworker_task); | 860 | int error = PTR_ERR(md->kworker_task); |
861 | md->kworker_task = NULL; | ||
862 | return error; | ||
863 | } | ||
861 | 864 | ||
862 | elv_register_queue(md->queue); | 865 | elv_register_queue(md->queue); |
863 | 866 | ||
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 3e407a9cde1f..c4b53b332607 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -695,37 +695,32 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
695 | 695 | ||
696 | tgt->type = dm_get_target_type(type); | 696 | tgt->type = dm_get_target_type(type); |
697 | if (!tgt->type) { | 697 | if (!tgt->type) { |
698 | DMERR("%s: %s: unknown target type", dm_device_name(t->md), | 698 | DMERR("%s: %s: unknown target type", dm_device_name(t->md), type); |
699 | type); | ||
700 | return -EINVAL; | 699 | return -EINVAL; |
701 | } | 700 | } |
702 | 701 | ||
703 | if (dm_target_needs_singleton(tgt->type)) { | 702 | if (dm_target_needs_singleton(tgt->type)) { |
704 | if (t->num_targets) { | 703 | if (t->num_targets) { |
705 | DMERR("%s: target type %s must appear alone in table", | 704 | tgt->error = "singleton target type must appear alone in table"; |
706 | dm_device_name(t->md), type); | 705 | goto bad; |
707 | return -EINVAL; | ||
708 | } | 706 | } |
709 | t->singleton = true; | 707 | t->singleton = true; |
710 | } | 708 | } |
711 | 709 | ||
712 | if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) { | 710 | if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) { |
713 | DMERR("%s: target type %s may not be included in read-only tables", | 711 | tgt->error = "target type may not be included in a read-only table"; |
714 | dm_device_name(t->md), type); | 712 | goto bad; |
715 | return -EINVAL; | ||
716 | } | 713 | } |
717 | 714 | ||
718 | if (t->immutable_target_type) { | 715 | if (t->immutable_target_type) { |
719 | if (t->immutable_target_type != tgt->type) { | 716 | if (t->immutable_target_type != tgt->type) { |
720 | DMERR("%s: immutable target type %s cannot be mixed with other target types", | 717 | tgt->error = "immutable target type cannot be mixed with other target types"; |
721 | dm_device_name(t->md), t->immutable_target_type->name); | 718 | goto bad; |
722 | return -EINVAL; | ||
723 | } | 719 | } |
724 | } else if (dm_target_is_immutable(tgt->type)) { | 720 | } else if (dm_target_is_immutable(tgt->type)) { |
725 | if (t->num_targets) { | 721 | if (t->num_targets) { |
726 | DMERR("%s: immutable target type %s cannot be mixed with other target types", | 722 | tgt->error = "immutable target type cannot be mixed with other target types"; |
727 | dm_device_name(t->md), tgt->type->name); | 723 | goto bad; |
728 | return -EINVAL; | ||
729 | } | 724 | } |
730 | t->immutable_target_type = tgt->type; | 725 | t->immutable_target_type = tgt->type; |
731 | } | 726 | } |
@@ -740,7 +735,6 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
740 | */ | 735 | */ |
741 | if (!adjoin(t, tgt)) { | 736 | if (!adjoin(t, tgt)) { |
742 | tgt->error = "Gap in table"; | 737 | tgt->error = "Gap in table"; |
743 | r = -EINVAL; | ||
744 | goto bad; | 738 | goto bad; |
745 | } | 739 | } |
746 | 740 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 147af9536d0c..ef7bf1dd6900 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1423,8 +1423,6 @@ static void cleanup_mapped_device(struct mapped_device *md) | |||
1423 | if (md->bs) | 1423 | if (md->bs) |
1424 | bioset_free(md->bs); | 1424 | bioset_free(md->bs); |
1425 | 1425 | ||
1426 | cleanup_srcu_struct(&md->io_barrier); | ||
1427 | |||
1428 | if (md->disk) { | 1426 | if (md->disk) { |
1429 | spin_lock(&_minor_lock); | 1427 | spin_lock(&_minor_lock); |
1430 | md->disk->private_data = NULL; | 1428 | md->disk->private_data = NULL; |
@@ -1436,6 +1434,8 @@ static void cleanup_mapped_device(struct mapped_device *md) | |||
1436 | if (md->queue) | 1434 | if (md->queue) |
1437 | blk_cleanup_queue(md->queue); | 1435 | blk_cleanup_queue(md->queue); |
1438 | 1436 | ||
1437 | cleanup_srcu_struct(&md->io_barrier); | ||
1438 | |||
1439 | if (md->bdev) { | 1439 | if (md->bdev) { |
1440 | bdput(md->bdev); | 1440 | bdput(md->bdev); |
1441 | md->bdev = NULL; | 1441 | md->bdev = NULL; |