Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −19
Original line number Diff line number Diff line
@@ -371,10 +371,15 @@ static void md_end_flush(struct bio *bio, int err)
	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;

	INIT_WORK(&mddev->flush_work, md_submit_flush_data);
	atomic_set(&mddev->flush_pending, 1);
	rcu_read_lock();
	list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
		if (rdev->raid_disk >= 0 &&
@@ -397,6 +402,8 @@ static void submit_flushes(mddev_t *mddev)
			rdev_dec_pending(rdev, mddev);
		}
	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)
@@ -404,8 +411,6 @@ static void md_submit_flush_data(struct work_struct *ws)
	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
	struct bio *bio = mddev->flush_bio;

	atomic_set(&mddev->flush_pending, 1);

	if (bio->bi_size == 0)
		/* an empty barrier - all done */
		bio_endio(bio, 0);
@@ -414,11 +419,10 @@ static void md_submit_flush_data(struct work_struct *ws)
		if (mddev->pers->make_request(mddev, bio))
			generic_make_request(bio);
	}
	if (atomic_dec_and_test(&mddev->flush_pending)) {

	mddev->flush_bio = NULL;
	wake_up(&mddev->sb_wait);
}
}

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;
	spin_unlock_irq(&mddev->write_lock);

	atomic_set(&mddev->flush_pending, 1);
	INIT_WORK(&mddev->flush_work, md_submit_flush_data);

	submit_flushes(mddev);

	if (atomic_dec_and_test(&mddev->flush_pending))
	INIT_WORK(&mddev->flush_work, submit_flushes);
	queue_work(md_wq, &mddev->flush_work);
}
EXPORT_SYMBOL(md_flush_request);
@@ -5160,7 +5159,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
				PTR_ERR(rdev));
			return PTR_ERR(rdev);
		}
		/* set save_raid_disk if appropriate */
		/* set saved_raid_disk if appropriate */
		if (!mddev->persistent) {
			if (info->state & (1<<MD_DISK_SYNC)  &&
			    info->raid_disk < mddev->raid_disks)
@@ -5170,7 +5169,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
		} else
			super_types[mddev->major_version].
				validate_super(mddev, rdev);
		if (test_bit(In_sync, &rdev->flags))
			rdev->saved_raid_disk = rdev->raid_disk;
		else
			rdev->saved_raid_disk = -1;

		clear_bit(In_sync, &rdev->flags); /* just to be sure */
		if (info->state & (1<<MD_DISK_WRITEMOSTLY))
@@ -6042,8 +6044,7 @@ static int md_thread(void * arg)
			 || kthread_should_stop(),
			 thread->timeout);

		clear_bit(THREAD_WAKEUP, &thread->flags);

		if (test_and_clear_bit(THREAD_WAKEUP, &thread->flags))
			thread->run(thread->mddev);
	}

+1 −1
Original line number Diff line number Diff line
@@ -2397,13 +2397,13 @@ static int run(mddev_t *mddev)
	return 0;

out_free_conf:
	md_unregister_thread(mddev->thread);
	if (conf->r10bio_pool)
		mempool_destroy(conf->r10bio_pool);
	safe_put_page(conf->tmppage);
	kfree(conf->mirrors);
	kfree(conf);
	mddev->private = NULL;
	md_unregister_thread(mddev->thread);
out:
	return -EIO;
}