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

Commit 18adc577 authored by Joe Thornber's avatar Joe Thornber Committed by Mike Snitzer
Browse files

dm thin: fix deadlock in __requeue_bio_list



The spin lock in requeue_io() was held for too long, allowing deadlock.
Don't worry, due to other issues addressed in the following "dm thin:
fix noflush suspend IO queueing" commit, this code was never called.

Fix this by taking the spin lock for a much shorter period of time.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 3e1a0699
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -369,14 +369,18 @@ struct dm_thin_endio_hook {
	struct dm_thin_new_mapping *overwrite_mapping;
	struct dm_thin_new_mapping *overwrite_mapping;
};
};


static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
static void requeue_bio_list(struct thin_c *tc, struct bio_list *master)
{
{
	struct bio *bio;
	struct bio *bio;
	struct bio_list bios;
	struct bio_list bios;
	unsigned long flags;


	bio_list_init(&bios);
	bio_list_init(&bios);

	spin_lock_irqsave(&tc->pool->lock, flags);
	bio_list_merge(&bios, master);
	bio_list_merge(&bios, master);
	bio_list_init(master);
	bio_list_init(master);
	spin_unlock_irqrestore(&tc->pool->lock, flags);


	while ((bio = bio_list_pop(&bios))) {
	while ((bio = bio_list_pop(&bios))) {
		struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
		struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
@@ -391,12 +395,9 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
static void requeue_io(struct thin_c *tc)
static void requeue_io(struct thin_c *tc)
{
{
	struct pool *pool = tc->pool;
	struct pool *pool = tc->pool;
	unsigned long flags;


	spin_lock_irqsave(&pool->lock, flags);
	requeue_bio_list(tc, &pool->deferred_bios);
	__requeue_bio_list(tc, &pool->deferred_bios);
	requeue_bio_list(tc, &pool->retry_on_resume_list);
	__requeue_bio_list(tc, &pool->retry_on_resume_list);
	spin_unlock_irqrestore(&pool->lock, flags);
}
}


static void error_retry_list(struct pool *pool)
static void error_retry_list(struct pool *pool)