From: Joe Thornber <ejt@redhat.com>
To: dm-devel@redhat.com
Cc: Joe Thornber <ejt@redhat.com>
Subject: [PATCH 5/8] [dm-thin] Fix a race condition between discard bios and ordinary bios.
Date: Thu, 13 Dec 2012 20:19:13 +0000 [thread overview]
Message-ID: <1355429956-22785-6-git-send-email-ejt@redhat.com> (raw)
In-Reply-To: <1355429956-22785-1-git-send-email-ejt@redhat.com>
The deferred_set entries should not be incremented until the bio
prison cells are held. Otherwise quiescing a block for discard may
end up waiting for a bio that's held in the discard bios cell.
---
drivers/md/dm-thin.c | 59 +++++++++++++++++++++++++++++++++++++-------------
1 file changed, 44 insertions(+), 15 deletions(-)
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 504f3d6..8e47f44 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -222,10 +222,28 @@ struct thin_c {
struct pool *pool;
struct dm_thin_device *td;
+
+ /*
+ * The cell structures are too big to put on the stack, so we have
+ * a couple here for use by the main mapping function.
+ */
+ spinlock_t lock;
+ struct dm_bio_prison_cell cell1, cell2;
};
/*----------------------------------------------------------------*/
+/*
+ * wake_worker() is used when new work is queued and when pool_resume is
+ * ready to continue deferred IO processing.
+ */
+static void wake_worker(struct pool *pool)
+{
+ queue_work(pool->wq, &pool->worker);
+}
+
+/*----------------------------------------------------------------*/
+
static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio,
struct dm_bio_prison_cell **result)
{
@@ -264,6 +282,19 @@ static void cell_release_no_holder(struct pool *pool,
dm_bio_prison_free_cell(pool->prison, cell);
}
+static void cell_defer_no_holder_no_free(struct thin_c *tc,
+ struct dm_bio_prison_cell *cell)
+{
+ struct pool *pool = tc->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ dm_cell_release_no_holder(pool->prison, cell, &pool->deferred_bios);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ wake_worker(pool);
+}
+
static void cell_error(struct pool *pool,
struct dm_bio_prison_cell *cell)
{
@@ -467,15 +498,6 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio,
issue(tc, bio);
}
-/*
- * wake_worker() is used when new work is queued and when pool_resume is
- * ready to continue deferred IO processing.
- */
-static void wake_worker(struct pool *pool)
-{
- queue_work(pool->wq, &pool->worker);
-}
-
/*----------------------------------------------------------------*/
/*
@@ -1429,8 +1451,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
dm_block_t block = get_bio_block(tc, bio);
struct dm_thin_device *td = tc->td;
struct dm_thin_lookup_result result;
- struct dm_bio_prison_cell *cell1, *cell2;
struct dm_cell_key key;
+ struct dm_bio_prison_cell *cell_result;
thin_hook_bio(tc, bio);
@@ -1470,19 +1492,24 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_SUBMITTED;
}
+ spin_lock(&tc->lock);
build_virtual_key(tc->td, block, &key);
- if (bio_detain(tc->pool, &key, bio, &cell1))
+ if (dm_bio_detain(tc->pool->prison, &key, bio, &tc->cell1, &cell_result)) {
+ spin_unlock(&tc->lock);
return DM_MAPIO_SUBMITTED;
+ }
build_data_key(tc->td, result.block, &key);
- if (bio_detain(tc->pool, &key, bio, &cell2)) {
- cell_defer_no_holder(tc, cell1);
+ if (dm_bio_detain(tc->pool->prison, &key, bio, &tc->cell2, &cell_result)) {
+ cell_defer_no_holder_no_free(tc, &tc->cell1);
+ spin_unlock(&tc->lock);
return DM_MAPIO_SUBMITTED;
}
inc_all_io_entry(tc->pool, bio);
- cell_defer_no_holder(tc, cell2);
- cell_defer_no_holder(tc, cell1);
+ cell_defer_no_holder_no_free(tc, &tc->cell2);
+ cell_defer_no_holder_no_free(tc, &tc->cell1);
+ spin_unlock(&tc->lock);
remap(tc, bio, result.block);
return DM_MAPIO_REMAPPED;
@@ -2638,6 +2665,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
if (r)
goto bad_thin_open;
+ spin_lock_init(&tc->lock);
+
ti->num_flush_requests = 1;
ti->flush_supported = true;
ti->per_bio_data_size = sizeof(struct dm_thin_endio_hook);
--
1.7.10.4
next prev parent reply other threads:[~2012-12-13 20:19 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-13 20:19 Another cache target Joe Thornber
2012-12-13 20:19 ` [PATCH 1/8] [persistent-data] Fix a bug in btree_del, and another bug that was compensating for it Joe Thornber
2012-12-13 20:19 ` [PATCH 2/8] [persistent-data] dm_btree_walk Joe Thornber
2012-12-13 20:19 ` [PATCH 3/8] [persistent-data] tweak an error message Joe Thornber
2012-12-13 20:19 ` [PATCH 4/8] [dm-bio-prison] Change the bio-prison interface so the memory for the cells is passed in Joe Thornber
2013-01-14 10:02 ` Alasdair G Kergon
2013-01-14 14:06 ` thornber
2013-01-14 14:22 ` Alasdair G Kergon
2013-01-21 23:32 ` Alasdair G Kergon
2013-01-22 11:31 ` thornber
2013-01-22 12:10 ` Alasdair G Kergon
2012-12-13 20:19 ` Joe Thornber [this message]
2012-12-14 15:52 ` [PATCH 5/8] [dm-thin] Fix a race condition between discard bios and ordinary bios Mike Snitzer
2013-01-22 0:03 ` Alasdair G Kergon
2013-01-24 2:35 ` Alasdair G Kergon
2013-01-24 13:23 ` thornber
2013-02-06 0:11 ` Mikulas Patocka
2013-02-07 11:20 ` thornber
2012-12-13 20:19 ` [PATCH 6/8] [persistent-data] Add a transactional array Joe Thornber
2013-01-22 21:18 ` Alasdair G Kergon
2013-01-23 12:07 ` thornber
2013-01-25 20:11 ` Alasdair G Kergon
2013-01-28 13:06 ` thornber
2013-01-28 20:25 ` Alasdair G Kergon
2013-01-28 14:57 ` thornber
2013-01-28 20:22 ` Alasdair G Kergon
2012-12-13 20:19 ` [PATCH 7/8] [persistent-data] transactional bitset Joe Thornber
2013-01-22 21:59 ` Alasdair G Kergon
2012-12-13 20:19 ` [PATCH 8/8] [dm-cache] cache target Joe Thornber
2012-12-14 0:17 ` Darrick J. Wong
2012-12-14 10:09 ` thornber
2013-02-12 15:27 ` Alasdair G Kergon
2013-02-12 16:40 ` Alasdair G Kergon
2013-02-12 17:29 ` Alasdair G Kergon
2013-02-14 13:57 ` Joe Thornber
2013-02-14 14:05 ` Joe Thornber
2013-02-14 21:06 ` Alasdair G Kergon
2012-12-13 21:57 ` Another " Mike Snitzer
2012-12-14 1:16 ` Darrick J. Wong
2012-12-14 2:19 ` Mike Snitzer
2012-12-14 2:27 ` Mike Snitzer
2012-12-14 2:42 ` Darrick J. Wong
2012-12-14 4:23 ` Mike Snitzer
2012-12-14 2:34 ` Darrick J. Wong
2012-12-14 10:24 ` thornber
2012-12-14 12:11 ` thornber
2012-12-14 21:51 ` Darrick J. Wong
2012-12-15 8:23 ` Joe Thornber
2012-12-18 1:49 ` Darrick J. Wong
2012-12-18 2:31 ` Alasdair G Kergon
2013-01-08 0:19 ` Darrick J. Wong
2013-01-08 13:55 ` thornber
2012-12-22 18:50 ` Mark Hills
2012-12-17 16:54 ` Heinz Mauelshagen
2012-12-18 15:44 ` basic cache policy module fix [was: Re: Another cache target] Mike Snitzer
2012-12-20 1:14 ` Darrick J. Wong
2012-12-20 12:57 ` Heinz Mauelshagen
2012-12-20 13:24 ` Mike Snitzer
2012-12-20 16:10 ` Darrick J. Wong
2012-12-20 17:02 ` Heinz Mauelshagen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1355429956-22785-6-git-send-email-ejt@redhat.com \
--to=ejt@redhat.com \
--cc=dm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.