Commit 025b9685 authored by Joe Thornber's avatar Joe Thornber Committed by Alasdair G Kergon

dm thin: remove cells from stack

This patch takes advantage of the new bio-prison interface where the
memory is now passed in rather than using a mempool in bio-prison.
This allows the map function to avoid performing potentially-blocking
allocations that could lead to deadlocks: We want to avoid the cell
allocation that is done in bio_detain.

(The potential for mempool deadlocks still remains in other functions
that use bio_detain.)
Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 6beca5eb
...@@ -14,13 +14,6 @@ ...@@ -14,13 +14,6 @@
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
struct dm_bio_prison_cell {
struct hlist_node list;
struct dm_cell_key key;
struct bio *holder;
struct bio_list bios;
};
struct dm_bio_prison { struct dm_bio_prison {
spinlock_t lock; spinlock_t lock;
mempool_t *cell_pool; mempool_t *cell_pool;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* subsequently unlocked the bios become available. * subsequently unlocked the bios become available.
*/ */
struct dm_bio_prison; struct dm_bio_prison;
struct dm_bio_prison_cell;
/* FIXME: this needs to be more abstract */ /* FIXME: this needs to be more abstract */
struct dm_cell_key { struct dm_cell_key {
...@@ -31,6 +30,17 @@ struct dm_cell_key { ...@@ -31,6 +30,17 @@ struct dm_cell_key {
dm_block_t block; dm_block_t block;
}; };
/*
* Treat this as opaque, only in header so callers can manage allocation
* themselves.
*/
struct dm_bio_prison_cell {
struct hlist_node list;
struct dm_cell_key key;
struct bio *holder;
struct bio_list bios;
};
struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells); struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells);
void dm_bio_prison_destroy(struct dm_bio_prison *prison); void dm_bio_prison_destroy(struct dm_bio_prison *prison);
......
...@@ -229,6 +229,17 @@ struct thin_c { ...@@ -229,6 +229,17 @@ struct thin_c {
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
/*
* 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, static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio,
struct dm_bio_prison_cell **cell_result) struct dm_bio_prison_cell **cell_result)
{ {
...@@ -268,6 +279,19 @@ static void cell_release_no_holder(struct pool *pool, ...@@ -268,6 +279,19 @@ static void cell_release_no_holder(struct pool *pool,
dm_bio_prison_free_cell(pool->prison, cell); 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, static void cell_error(struct pool *pool,
struct dm_bio_prison_cell *cell) struct dm_bio_prison_cell *cell)
{ {
...@@ -477,15 +501,6 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio, ...@@ -477,15 +501,6 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio,
issue(tc, 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);
}
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
/* /*
...@@ -601,6 +616,7 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m) ...@@ -601,6 +616,7 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
list_del(&m->list); list_del(&m->list);
mempool_free(m, m->tc->pool->mapping_pool); mempool_free(m, m->tc->pool->mapping_pool);
} }
static void process_prepared_mapping(struct dm_thin_new_mapping *m) static void process_prepared_mapping(struct dm_thin_new_mapping *m)
{ {
struct thin_c *tc = m->tc; struct thin_c *tc = m->tc;
...@@ -1438,7 +1454,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) ...@@ -1438,7 +1454,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
dm_block_t block = get_bio_block(tc, bio); dm_block_t block = get_bio_block(tc, bio);
struct dm_thin_device *td = tc->td; struct dm_thin_device *td = tc->td;
struct dm_thin_lookup_result result; struct dm_thin_lookup_result result;
struct dm_bio_prison_cell *cell1, *cell2; struct dm_bio_prison_cell cell1, cell2;
struct dm_bio_prison_cell *cell_result;
struct dm_cell_key key; struct dm_cell_key key;
thin_hook_bio(tc, bio); thin_hook_bio(tc, bio);
...@@ -1480,18 +1497,18 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) ...@@ -1480,18 +1497,18 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
} }
build_virtual_key(tc->td, block, &key); build_virtual_key(tc->td, block, &key);
if (bio_detain(tc->pool, &key, bio, &cell1)) if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result))
return DM_MAPIO_SUBMITTED; return DM_MAPIO_SUBMITTED;
build_data_key(tc->td, result.block, &key); build_data_key(tc->td, result.block, &key);
if (bio_detain(tc->pool, &key, bio, &cell2)) { if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) {
cell_defer_no_holder(tc, cell1); cell_defer_no_holder_no_free(tc, &cell1);
return DM_MAPIO_SUBMITTED; return DM_MAPIO_SUBMITTED;
} }
inc_all_io_entry(tc->pool, bio); inc_all_io_entry(tc->pool, bio);
cell_defer_no_holder(tc, cell2); cell_defer_no_holder_no_free(tc, &cell2);
cell_defer_no_holder(tc, cell1); cell_defer_no_holder_no_free(tc, &cell1);
remap(tc, bio, result.block); remap(tc, bio, result.block);
return DM_MAPIO_REMAPPED; return DM_MAPIO_REMAPPED;
......
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