Commit 6d5e93c2 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3d0b6087 589a594b
...@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err) ...@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err)
bio_put(bio); bio_put(bio);
} }
static void submit_flushes(mddev_t *mddev) static void md_submit_flush_data(struct work_struct *ws);
static void submit_flushes(struct work_struct *ws)
{ {
mddev_t *mddev = container_of(ws, mddev_t, flush_work);
mdk_rdev_t *rdev; mdk_rdev_t *rdev;
INIT_WORK(&mddev->flush_work, md_submit_flush_data);
atomic_set(&mddev->flush_pending, 1);
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(rdev, &mddev->disks, same_set) list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 && if (rdev->raid_disk >= 0 &&
...@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev) ...@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev)
rdev_dec_pending(rdev, mddev); rdev_dec_pending(rdev, mddev);
} }
rcu_read_unlock(); rcu_read_unlock();
if (atomic_dec_and_test(&mddev->flush_pending))
queue_work(md_wq, &mddev->flush_work);
} }
static void md_submit_flush_data(struct work_struct *ws) 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,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws)
mddev_t *mddev = container_of(ws, mddev_t, flush_work); mddev_t *mddev = container_of(ws, mddev_t, flush_work);
struct bio *bio = mddev->flush_bio; struct bio *bio = mddev->flush_bio;
atomic_set(&mddev->flush_pending, 1);
if (bio->bi_size == 0) if (bio->bi_size == 0)
/* an empty barrier - all done */ /* an empty barrier - all done */
bio_endio(bio, 0); bio_endio(bio, 0);
...@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws) ...@@ -414,10 +419,9 @@ static void md_submit_flush_data(struct work_struct *ws)
if (mddev->pers->make_request(mddev, bio)) if (mddev->pers->make_request(mddev, bio))
generic_make_request(bio); generic_make_request(bio);
} }
if (atomic_dec_and_test(&mddev->flush_pending)) {
mddev->flush_bio = NULL; mddev->flush_bio = NULL;
wake_up(&mddev->sb_wait); wake_up(&mddev->sb_wait);
}
} }
void md_flush_request(mddev_t *mddev, struct bio *bio) void md_flush_request(mddev_t *mddev, struct bio *bio)
...@@ -429,12 +433,7 @@ void md_flush_request(mddev_t *mddev, struct bio *bio) ...@@ -429,12 +433,7 @@ void md_flush_request(mddev_t *mddev, struct bio *bio)
mddev->flush_bio = bio; mddev->flush_bio = bio;
spin_unlock_irq(&mddev->write_lock); spin_unlock_irq(&mddev->write_lock);
atomic_set(&mddev->flush_pending, 1); INIT_WORK(&mddev->flush_work, submit_flushes);
INIT_WORK(&mddev->flush_work, md_submit_flush_data);
submit_flushes(mddev);
if (atomic_dec_and_test(&mddev->flush_pending))
queue_work(md_wq, &mddev->flush_work); queue_work(md_wq, &mddev->flush_work);
} }
EXPORT_SYMBOL(md_flush_request); EXPORT_SYMBOL(md_flush_request);
...@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) ...@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
PTR_ERR(rdev)); PTR_ERR(rdev));
return PTR_ERR(rdev); return PTR_ERR(rdev);
} }
/* set save_raid_disk if appropriate */ /* set saved_raid_disk if appropriate */
if (!mddev->persistent) { if (!mddev->persistent) {
if (info->state & (1<<MD_DISK_SYNC) && if (info->state & (1<<MD_DISK_SYNC) &&
info->raid_disk < mddev->raid_disks) info->raid_disk < mddev->raid_disks)
...@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) ...@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
} else } else
super_types[mddev->major_version]. super_types[mddev->major_version].
validate_super(mddev, rdev); validate_super(mddev, rdev);
if (test_bit(In_sync, &rdev->flags))
rdev->saved_raid_disk = rdev->raid_disk; rdev->saved_raid_disk = rdev->raid_disk;
else
rdev->saved_raid_disk = -1;
clear_bit(In_sync, &rdev->flags); /* just to be sure */ clear_bit(In_sync, &rdev->flags); /* just to be sure */
if (info->state & (1<<MD_DISK_WRITEMOSTLY)) if (info->state & (1<<MD_DISK_WRITEMOSTLY))
...@@ -6042,8 +6044,7 @@ static int md_thread(void * arg) ...@@ -6042,8 +6044,7 @@ static int md_thread(void * arg)
|| kthread_should_stop(), || kthread_should_stop(),
thread->timeout); thread->timeout);
clear_bit(THREAD_WAKEUP, &thread->flags); if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
thread->run(thread->mddev); thread->run(thread->mddev);
} }
......
...@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev) ...@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev)
return 0; return 0;
out_free_conf: out_free_conf:
md_unregister_thread(mddev->thread);
if (conf->r10bio_pool) if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool); mempool_destroy(conf->r10bio_pool);
safe_put_page(conf->tmppage); safe_put_page(conf->tmppage);
kfree(conf->mirrors); kfree(conf->mirrors);
kfree(conf); kfree(conf);
mddev->private = NULL; mddev->private = NULL;
md_unregister_thread(mddev->thread);
out: out:
return -EIO; return -EIO;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment