diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-14 21:49:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-14 21:49:40 -0500 |
commit | 6d5e93c2aa1248b25f9de0eaca1dca038e31d79d (patch) | |
tree | f1d96e347d0662182d118cb3e2f2180c91146afd /drivers | |
parent | 3d0b6087f3f2c88caef25e1455ff8db0816d4e11 (diff) | |
parent | 589a594be1fb8815b3f18e517be696c48664f728 (diff) |
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md:
md: protect against NULL reference when waiting to start a raid10.
md: fix bug with re-adding of partially recovered device.
md: fix possible deadlock in handling flush requests.
md: move code in to submit_flushes.
md: remove handling of flush_pending in md_submit_flush_data
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/md.c | 39 | ||||
-rw-r--r-- | drivers/md/raid10.c | 2 |
2 files changed, 21 insertions, 20 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 84c46a161927..e71c5fa527f5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err) | |||
371 | bio_put(bio); | 371 | bio_put(bio); |
372 | } | 372 | } |
373 | 373 | ||
374 | static void submit_flushes(mddev_t *mddev) | 374 | static void md_submit_flush_data(struct work_struct *ws); |
375 | |||
376 | static void submit_flushes(struct work_struct *ws) | ||
375 | { | 377 | { |
378 | mddev_t *mddev = container_of(ws, mddev_t, flush_work); | ||
376 | mdk_rdev_t *rdev; | 379 | mdk_rdev_t *rdev; |
377 | 380 | ||
381 | INIT_WORK(&mddev->flush_work, md_submit_flush_data); | ||
382 | atomic_set(&mddev->flush_pending, 1); | ||
378 | rcu_read_lock(); | 383 | rcu_read_lock(); |
379 | list_for_each_entry_rcu(rdev, &mddev->disks, same_set) | 384 | list_for_each_entry_rcu(rdev, &mddev->disks, same_set) |
380 | if (rdev->raid_disk >= 0 && | 385 | if (rdev->raid_disk >= 0 && |
@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev) | |||
397 | rdev_dec_pending(rdev, mddev); | 402 | rdev_dec_pending(rdev, mddev); |
398 | } | 403 | } |
399 | rcu_read_unlock(); | 404 | rcu_read_unlock(); |
405 | if (atomic_dec_and_test(&mddev->flush_pending)) | ||
406 | queue_work(md_wq, &mddev->flush_work); | ||
400 | } | 407 | } |
401 | 408 | ||
402 | static void md_submit_flush_data(struct work_struct *ws) | 409 | static void md_submit_flush_data(struct work_struct *ws) |
@@ -404,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws) | |||
404 | mddev_t *mddev = container_of(ws, mddev_t, flush_work); | 411 | mddev_t *mddev = container_of(ws, mddev_t, flush_work); |
405 | struct bio *bio = mddev->flush_bio; | 412 | struct bio *bio = mddev->flush_bio; |
406 | 413 | ||
407 | atomic_set(&mddev->flush_pending, 1); | ||
408 | |||
409 | if (bio->bi_size == 0) | 414 | if (bio->bi_size == 0) |
410 | /* an empty barrier - all done */ | 415 | /* an empty barrier - all done */ |
411 | bio_endio(bio, 0); | 416 | bio_endio(bio, 0); |
@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws) | |||
414 | if (mddev->pers->make_request(mddev, bio)) | 419 | if (mddev->pers->make_request(mddev, bio)) |
415 | generic_make_request(bio); | 420 | generic_make_request(bio); |
416 | } | 421 | } |
417 | if (atomic_dec_and_test(&mddev->flush_pending)) { | 422 | |
418 | mddev->flush_bio = NULL; | 423 | mddev->flush_bio = NULL; |
419 | wake_up(&mddev->sb_wait); | 424 | wake_up(&mddev->sb_wait); |
420 | } | ||
421 | } | 425 | } |
422 | 426 | ||
423 | void md_flush_request(mddev_t *mddev, struct bio *bio) | 427 | void md_flush_request(mddev_t *mddev, struct bio *bio) |
@@ -429,13 +433,8 @@ void md_flush_request(mddev_t *mddev, struct bio *bio) | |||
429 | mddev->flush_bio = bio; | 433 | mddev->flush_bio = bio; |
430 | spin_unlock_irq(&mddev->write_lock); | 434 | spin_unlock_irq(&mddev->write_lock); |
431 | 435 | ||
432 | atomic_set(&mddev->flush_pending, 1); | 436 | INIT_WORK(&mddev->flush_work, submit_flushes); |
433 | INIT_WORK(&mddev->flush_work, md_submit_flush_data); | 437 | queue_work(md_wq, &mddev->flush_work); |
434 | |||
435 | submit_flushes(mddev); | ||
436 | |||
437 | if (atomic_dec_and_test(&mddev->flush_pending)) | ||
438 | queue_work(md_wq, &mddev->flush_work); | ||
439 | } | 438 | } |
440 | EXPORT_SYMBOL(md_flush_request); | 439 | EXPORT_SYMBOL(md_flush_request); |
441 | 440 | ||
@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
5160 | PTR_ERR(rdev)); | 5159 | PTR_ERR(rdev)); |
5161 | return PTR_ERR(rdev); | 5160 | return PTR_ERR(rdev); |
5162 | } | 5161 | } |
5163 | /* set save_raid_disk if appropriate */ | 5162 | /* set saved_raid_disk if appropriate */ |
5164 | if (!mddev->persistent) { | 5163 | if (!mddev->persistent) { |
5165 | if (info->state & (1<<MD_DISK_SYNC) && | 5164 | if (info->state & (1<<MD_DISK_SYNC) && |
5166 | info->raid_disk < mddev->raid_disks) | 5165 | info->raid_disk < mddev->raid_disks) |
@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
5170 | } else | 5169 | } else |
5171 | super_types[mddev->major_version]. | 5170 | super_types[mddev->major_version]. |
5172 | validate_super(mddev, rdev); | 5171 | validate_super(mddev, rdev); |
5173 | rdev->saved_raid_disk = rdev->raid_disk; | 5172 | if (test_bit(In_sync, &rdev->flags)) |
5173 | rdev->saved_raid_disk = rdev->raid_disk; | ||
5174 | else | ||
5175 | rdev->saved_raid_disk = -1; | ||
5174 | 5176 | ||
5175 | clear_bit(In_sync, &rdev->flags); /* just to be sure */ | 5177 | clear_bit(In_sync, &rdev->flags); /* just to be sure */ |
5176 | if (info->state & (1<<MD_DISK_WRITEMOSTLY)) | 5178 | if (info->state & (1<<MD_DISK_WRITEMOSTLY)) |
@@ -6042,9 +6044,8 @@ static int md_thread(void * arg) | |||
6042 | || kthread_should_stop(), | 6044 | || kthread_should_stop(), |
6043 | thread->timeout); | 6045 | thread->timeout); |
6044 | 6046 | ||
6045 | clear_bit(THREAD_WAKEUP, &thread->flags); | 6047 | if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags)) |
6046 | 6048 | thread->run(thread->mddev); | |
6047 | thread->run(thread->mddev); | ||
6048 | } | 6049 | } |
6049 | 6050 | ||
6050 | return 0; | 6051 | return 0; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c67aa54694ae..0641674827f0 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev) | |||
2397 | return 0; | 2397 | return 0; |
2398 | 2398 | ||
2399 | out_free_conf: | 2399 | out_free_conf: |
2400 | md_unregister_thread(mddev->thread); | ||
2400 | if (conf->r10bio_pool) | 2401 | if (conf->r10bio_pool) |
2401 | mempool_destroy(conf->r10bio_pool); | 2402 | mempool_destroy(conf->r10bio_pool); |
2402 | safe_put_page(conf->tmppage); | 2403 | safe_put_page(conf->tmppage); |
2403 | kfree(conf->mirrors); | 2404 | kfree(conf->mirrors); |
2404 | kfree(conf); | 2405 | kfree(conf); |
2405 | mddev->private = NULL; | 2406 | mddev->private = NULL; |
2406 | md_unregister_thread(mddev->thread); | ||
2407 | out: | 2407 | out: |
2408 | return -EIO; | 2408 | return -EIO; |
2409 | } | 2409 | } |