diff options
Diffstat (limited to 'drivers/md')
| -rw-r--r-- | drivers/md/dm-crypt.c | 2 | ||||
| -rw-r--r-- | drivers/md/dm-flakey.c | 4 | ||||
| -rw-r--r-- | drivers/md/dm-raid.c | 2 | ||||
| -rw-r--r-- | drivers/md/dm-table.c | 32 | ||||
| -rw-r--r-- | drivers/md/md.c | 22 | ||||
| -rw-r--r-- | drivers/md/md.h | 2 | ||||
| -rw-r--r-- | drivers/md/multipath.c | 3 | ||||
| -rw-r--r-- | drivers/md/raid1.c | 3 | ||||
| -rw-r--r-- | drivers/md/raid10.c | 5 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 6 |
10 files changed, 58 insertions, 23 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 49da55c1528a..8c2a000cf3f5 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -1698,6 +1698,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1698 | } | 1698 | } |
| 1699 | 1699 | ||
| 1700 | ti->num_flush_requests = 1; | 1700 | ti->num_flush_requests = 1; |
| 1701 | ti->discard_zeroes_data_unsupported = 1; | ||
| 1702 | |||
| 1701 | return 0; | 1703 | return 0; |
| 1702 | 1704 | ||
| 1703 | bad: | 1705 | bad: |
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 89f73ca22cfa..f84c08029b21 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c | |||
| @@ -81,8 +81,10 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, | |||
| 81 | * corrupt_bio_byte <Nth_byte> <direction> <value> <bio_flags> | 81 | * corrupt_bio_byte <Nth_byte> <direction> <value> <bio_flags> |
| 82 | */ | 82 | */ |
| 83 | if (!strcasecmp(arg_name, "corrupt_bio_byte")) { | 83 | if (!strcasecmp(arg_name, "corrupt_bio_byte")) { |
| 84 | if (!argc) | 84 | if (!argc) { |
| 85 | ti->error = "Feature corrupt_bio_byte requires parameters"; | 85 | ti->error = "Feature corrupt_bio_byte requires parameters"; |
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 86 | 88 | ||
| 87 | r = dm_read_arg(_args + 1, as, &fc->corrupt_bio_byte, &ti->error); | 89 | r = dm_read_arg(_args + 1, as, &fc->corrupt_bio_byte, &ti->error); |
| 88 | if (r) | 90 | if (r) |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index a002dd85db1e..86df8b2cf927 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
| @@ -449,7 +449,7 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
| 449 | rs->ti->error = "write_mostly option is only valid for RAID1"; | 449 | rs->ti->error = "write_mostly option is only valid for RAID1"; |
| 450 | return -EINVAL; | 450 | return -EINVAL; |
| 451 | } | 451 | } |
| 452 | if (value > rs->md.raid_disks) { | 452 | if (value >= rs->md.raid_disks) { |
| 453 | rs->ti->error = "Invalid write_mostly drive index given"; | 453 | rs->ti->error = "Invalid write_mostly drive index given"; |
| 454 | return -EINVAL; | 454 | return -EINVAL; |
| 455 | } | 455 | } |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 986b8754bb08..bc04518e9d8b 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -1238,14 +1238,15 @@ static void dm_table_set_integrity(struct dm_table *t) | |||
| 1238 | return; | 1238 | return; |
| 1239 | 1239 | ||
| 1240 | template_disk = dm_table_get_integrity_disk(t, true); | 1240 | template_disk = dm_table_get_integrity_disk(t, true); |
| 1241 | if (!template_disk && | 1241 | if (template_disk) |
| 1242 | blk_integrity_is_initialized(dm_disk(t->md))) { | 1242 | blk_integrity_register(dm_disk(t->md), |
| 1243 | blk_get_integrity(template_disk)); | ||
| 1244 | else if (blk_integrity_is_initialized(dm_disk(t->md))) | ||
| 1243 | DMWARN("%s: device no longer has a valid integrity profile", | 1245 | DMWARN("%s: device no longer has a valid integrity profile", |
| 1244 | dm_device_name(t->md)); | 1246 | dm_device_name(t->md)); |
| 1245 | return; | 1247 | else |
| 1246 | } | 1248 | DMWARN("%s: unable to establish an integrity profile", |
| 1247 | blk_integrity_register(dm_disk(t->md), | 1249 | dm_device_name(t->md)); |
| 1248 | blk_get_integrity(template_disk)); | ||
| 1249 | } | 1250 | } |
| 1250 | 1251 | ||
| 1251 | static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, | 1252 | static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, |
| @@ -1282,6 +1283,22 @@ static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) | |||
| 1282 | return 0; | 1283 | return 0; |
| 1283 | } | 1284 | } |
| 1284 | 1285 | ||
| 1286 | static bool dm_table_discard_zeroes_data(struct dm_table *t) | ||
| 1287 | { | ||
| 1288 | struct dm_target *ti; | ||
| 1289 | unsigned i = 0; | ||
| 1290 | |||
| 1291 | /* Ensure that all targets supports discard_zeroes_data. */ | ||
| 1292 | while (i < dm_table_get_num_targets(t)) { | ||
| 1293 | ti = dm_table_get_target(t, i++); | ||
| 1294 | |||
| 1295 | if (ti->discard_zeroes_data_unsupported) | ||
| 1296 | return 0; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | return 1; | ||
| 1300 | } | ||
| 1301 | |||
| 1285 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | 1302 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, |
| 1286 | struct queue_limits *limits) | 1303 | struct queue_limits *limits) |
| 1287 | { | 1304 | { |
| @@ -1304,6 +1321,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
| 1304 | } | 1321 | } |
| 1305 | blk_queue_flush(q, flush); | 1322 | blk_queue_flush(q, flush); |
| 1306 | 1323 | ||
| 1324 | if (!dm_table_discard_zeroes_data(t)) | ||
| 1325 | q->limits.discard_zeroes_data = 0; | ||
| 1326 | |||
| 1307 | dm_table_set_integrity(t); | 1327 | dm_table_set_integrity(t); |
| 1308 | 1328 | ||
| 1309 | /* | 1329 | /* |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 5404b2295820..5c95ccb59500 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -61,6 +61,11 @@ | |||
| 61 | static void autostart_arrays(int part); | 61 | static void autostart_arrays(int part); |
| 62 | #endif | 62 | #endif |
| 63 | 63 | ||
| 64 | /* pers_list is a list of registered personalities protected | ||
| 65 | * by pers_lock. | ||
| 66 | * pers_lock does extra service to protect accesses to | ||
| 67 | * mddev->thread when the mutex cannot be held. | ||
| 68 | */ | ||
| 64 | static LIST_HEAD(pers_list); | 69 | static LIST_HEAD(pers_list); |
| 65 | static DEFINE_SPINLOCK(pers_lock); | 70 | static DEFINE_SPINLOCK(pers_lock); |
| 66 | 71 | ||
| @@ -739,7 +744,12 @@ static void mddev_unlock(mddev_t * mddev) | |||
| 739 | } else | 744 | } else |
| 740 | mutex_unlock(&mddev->reconfig_mutex); | 745 | mutex_unlock(&mddev->reconfig_mutex); |
| 741 | 746 | ||
| 747 | /* was we've dropped the mutex we need a spinlock to | ||
| 748 | * make sur the thread doesn't disappear | ||
| 749 | */ | ||
| 750 | spin_lock(&pers_lock); | ||
| 742 | md_wakeup_thread(mddev->thread); | 751 | md_wakeup_thread(mddev->thread); |
| 752 | spin_unlock(&pers_lock); | ||
| 743 | } | 753 | } |
| 744 | 754 | ||
| 745 | static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) | 755 | static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) |
| @@ -6429,11 +6439,18 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, | |||
| 6429 | return thread; | 6439 | return thread; |
| 6430 | } | 6440 | } |
| 6431 | 6441 | ||
| 6432 | void md_unregister_thread(mdk_thread_t *thread) | 6442 | void md_unregister_thread(mdk_thread_t **threadp) |
| 6433 | { | 6443 | { |
| 6444 | mdk_thread_t *thread = *threadp; | ||
| 6434 | if (!thread) | 6445 | if (!thread) |
| 6435 | return; | 6446 | return; |
| 6436 | dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); | 6447 | dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); |
| 6448 | /* Locking ensures that mddev_unlock does not wake_up a | ||
| 6449 | * non-existent thread | ||
| 6450 | */ | ||
| 6451 | spin_lock(&pers_lock); | ||
| 6452 | *threadp = NULL; | ||
| 6453 | spin_unlock(&pers_lock); | ||
| 6437 | 6454 | ||
| 6438 | kthread_stop(thread->tsk); | 6455 | kthread_stop(thread->tsk); |
| 6439 | kfree(thread); | 6456 | kfree(thread); |
| @@ -7340,8 +7357,7 @@ static void reap_sync_thread(mddev_t *mddev) | |||
| 7340 | mdk_rdev_t *rdev; | 7357 | mdk_rdev_t *rdev; |
| 7341 | 7358 | ||
| 7342 | /* resync has finished, collect result */ | 7359 | /* resync has finished, collect result */ |
| 7343 | md_unregister_thread(mddev->sync_thread); | 7360 | md_unregister_thread(&mddev->sync_thread); |
| 7344 | mddev->sync_thread = NULL; | ||
| 7345 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && | 7361 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && |
| 7346 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | 7362 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { |
| 7347 | /* success...*/ | 7363 | /* success...*/ |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 1e586bb4452e..0a309dc29b45 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -560,7 +560,7 @@ extern int register_md_personality(struct mdk_personality *p); | |||
| 560 | extern int unregister_md_personality(struct mdk_personality *p); | 560 | extern int unregister_md_personality(struct mdk_personality *p); |
| 561 | extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev), | 561 | extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev), |
| 562 | mddev_t *mddev, const char *name); | 562 | mddev_t *mddev, const char *name); |
| 563 | extern void md_unregister_thread(mdk_thread_t *thread); | 563 | extern void md_unregister_thread(mdk_thread_t **threadp); |
| 564 | extern void md_wakeup_thread(mdk_thread_t *thread); | 564 | extern void md_wakeup_thread(mdk_thread_t *thread); |
| 565 | extern void md_check_recovery(mddev_t *mddev); | 565 | extern void md_check_recovery(mddev_t *mddev); |
| 566 | extern void md_write_start(mddev_t *mddev, struct bio *bi); | 566 | extern void md_write_start(mddev_t *mddev, struct bio *bi); |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 3535c23af288..d5b5fb300171 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
| @@ -514,8 +514,7 @@ static int multipath_stop (mddev_t *mddev) | |||
| 514 | { | 514 | { |
| 515 | multipath_conf_t *conf = mddev->private; | 515 | multipath_conf_t *conf = mddev->private; |
| 516 | 516 | ||
| 517 | md_unregister_thread(mddev->thread); | 517 | md_unregister_thread(&mddev->thread); |
| 518 | mddev->thread = NULL; | ||
| 519 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 518 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 520 | mempool_destroy(conf->pool); | 519 | mempool_destroy(conf->pool); |
| 521 | kfree(conf->multipaths); | 520 | kfree(conf->multipaths); |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f4622dd8fc59..d9587dffe533 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -2562,8 +2562,7 @@ static int stop(mddev_t *mddev) | |||
| 2562 | raise_barrier(conf); | 2562 | raise_barrier(conf); |
| 2563 | lower_barrier(conf); | 2563 | lower_barrier(conf); |
| 2564 | 2564 | ||
| 2565 | md_unregister_thread(mddev->thread); | 2565 | md_unregister_thread(&mddev->thread); |
| 2566 | mddev->thread = NULL; | ||
| 2567 | if (conf->r1bio_pool) | 2566 | if (conf->r1bio_pool) |
| 2568 | mempool_destroy(conf->r1bio_pool); | 2567 | mempool_destroy(conf->r1bio_pool); |
| 2569 | kfree(conf->mirrors); | 2568 | kfree(conf->mirrors); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d7a8468ddeab..0cd9672cf9cb 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -2955,7 +2955,7 @@ static int run(mddev_t *mddev) | |||
| 2955 | return 0; | 2955 | return 0; |
| 2956 | 2956 | ||
| 2957 | out_free_conf: | 2957 | out_free_conf: |
| 2958 | md_unregister_thread(mddev->thread); | 2958 | md_unregister_thread(&mddev->thread); |
| 2959 | if (conf->r10bio_pool) | 2959 | if (conf->r10bio_pool) |
| 2960 | mempool_destroy(conf->r10bio_pool); | 2960 | mempool_destroy(conf->r10bio_pool); |
| 2961 | safe_put_page(conf->tmppage); | 2961 | safe_put_page(conf->tmppage); |
| @@ -2973,8 +2973,7 @@ static int stop(mddev_t *mddev) | |||
| 2973 | raise_barrier(conf, 0); | 2973 | raise_barrier(conf, 0); |
| 2974 | lower_barrier(conf); | 2974 | lower_barrier(conf); |
| 2975 | 2975 | ||
| 2976 | md_unregister_thread(mddev->thread); | 2976 | md_unregister_thread(&mddev->thread); |
| 2977 | mddev->thread = NULL; | ||
| 2978 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2977 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 2979 | if (conf->r10bio_pool) | 2978 | if (conf->r10bio_pool) |
| 2980 | mempool_destroy(conf->r10bio_pool); | 2979 | mempool_destroy(conf->r10bio_pool); |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 43709fa6b6df..ac5e8b57e50f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -4941,8 +4941,7 @@ static int run(mddev_t *mddev) | |||
| 4941 | 4941 | ||
| 4942 | return 0; | 4942 | return 0; |
| 4943 | abort: | 4943 | abort: |
| 4944 | md_unregister_thread(mddev->thread); | 4944 | md_unregister_thread(&mddev->thread); |
| 4945 | mddev->thread = NULL; | ||
| 4946 | if (conf) { | 4945 | if (conf) { |
| 4947 | print_raid5_conf(conf); | 4946 | print_raid5_conf(conf); |
| 4948 | free_conf(conf); | 4947 | free_conf(conf); |
| @@ -4956,8 +4955,7 @@ static int stop(mddev_t *mddev) | |||
| 4956 | { | 4955 | { |
| 4957 | raid5_conf_t *conf = mddev->private; | 4956 | raid5_conf_t *conf = mddev->private; |
| 4958 | 4957 | ||
| 4959 | md_unregister_thread(mddev->thread); | 4958 | md_unregister_thread(&mddev->thread); |
| 4960 | mddev->thread = NULL; | ||
| 4961 | if (mddev->queue) | 4959 | if (mddev->queue) |
| 4962 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4960 | mddev->queue->backing_dev_info.congested_fn = NULL; |
| 4963 | free_conf(conf); | 4961 | free_conf(conf); |
