Commit 025b96853fe0bdc977d88b4242ca5e1f19d9bb66

Authored by Joe Thornber
Committed by Alasdair G Kergon
1 parent 6beca5eb6e

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: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 3 changed files with 43 additions and 23 deletions Side-by-side Diff

drivers/md/dm-bio-prison.c
... ... @@ -14,13 +14,6 @@
14 14  
15 15 /*----------------------------------------------------------------*/
16 16  
17   -struct dm_bio_prison_cell {
18   - struct hlist_node list;
19   - struct dm_cell_key key;
20   - struct bio *holder;
21   - struct bio_list bios;
22   -};
23   -
24 17 struct dm_bio_prison {
25 18 spinlock_t lock;
26 19 mempool_t *cell_pool;
drivers/md/dm-bio-prison.h
... ... @@ -22,13 +22,23 @@
22 22 * subsequently unlocked the bios become available.
23 23 */
24 24 struct dm_bio_prison;
25   -struct dm_bio_prison_cell;
26 25  
27 26 /* FIXME: this needs to be more abstract */
28 27 struct dm_cell_key {
29 28 int virtual;
30 29 dm_thin_id dev;
31 30 dm_block_t block;
  31 +};
  32 +
  33 +/*
  34 + * Treat this as opaque, only in header so callers can manage allocation
  35 + * themselves.
  36 + */
  37 +struct dm_bio_prison_cell {
  38 + struct hlist_node list;
  39 + struct dm_cell_key key;
  40 + struct bio *holder;
  41 + struct bio_list bios;
32 42 };
33 43  
34 44 struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells);
drivers/md/dm-thin.c
... ... @@ -229,6 +229,17 @@
229 229  
230 230 /*----------------------------------------------------------------*/
231 231  
  232 +/*
  233 + * wake_worker() is used when new work is queued and when pool_resume is
  234 + * ready to continue deferred IO processing.
  235 + */
  236 +static void wake_worker(struct pool *pool)
  237 +{
  238 + queue_work(pool->wq, &pool->worker);
  239 +}
  240 +
  241 +/*----------------------------------------------------------------*/
  242 +
232 243 static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio,
233 244 struct dm_bio_prison_cell **cell_result)
234 245 {
... ... @@ -268,6 +279,19 @@
268 279 dm_bio_prison_free_cell(pool->prison, cell);
269 280 }
270 281  
  282 +static void cell_defer_no_holder_no_free(struct thin_c *tc,
  283 + struct dm_bio_prison_cell *cell)
  284 +{
  285 + struct pool *pool = tc->pool;
  286 + unsigned long flags;
  287 +
  288 + spin_lock_irqsave(&pool->lock, flags);
  289 + dm_cell_release_no_holder(pool->prison, cell, &pool->deferred_bios);
  290 + spin_unlock_irqrestore(&pool->lock, flags);
  291 +
  292 + wake_worker(pool);
  293 +}
  294 +
271 295 static void cell_error(struct pool *pool,
272 296 struct dm_bio_prison_cell *cell)
273 297 {
... ... @@ -477,15 +501,6 @@
477 501 issue(tc, bio);
478 502 }
479 503  
480   -/*
481   - * wake_worker() is used when new work is queued and when pool_resume is
482   - * ready to continue deferred IO processing.
483   - */
484   -static void wake_worker(struct pool *pool)
485   -{
486   - queue_work(pool->wq, &pool->worker);
487   -}
488   -
489 504 /*----------------------------------------------------------------*/
490 505  
491 506 /*
... ... @@ -601,6 +616,7 @@
601 616 list_del(&m->list);
602 617 mempool_free(m, m->tc->pool->mapping_pool);
603 618 }
  619 +
604 620 static void process_prepared_mapping(struct dm_thin_new_mapping *m)
605 621 {
606 622 struct thin_c *tc = m->tc;
... ... @@ -1438,7 +1454,8 @@
1438 1454 dm_block_t block = get_bio_block(tc, bio);
1439 1455 struct dm_thin_device *td = tc->td;
1440 1456 struct dm_thin_lookup_result result;
1441   - struct dm_bio_prison_cell *cell1, *cell2;
  1457 + struct dm_bio_prison_cell cell1, cell2;
  1458 + struct dm_bio_prison_cell *cell_result;
1442 1459 struct dm_cell_key key;
1443 1460  
1444 1461 thin_hook_bio(tc, bio);
1445 1462  
1446 1463  
... ... @@ -1480,18 +1497,18 @@
1480 1497 }
1481 1498  
1482 1499 build_virtual_key(tc->td, block, &key);
1483   - if (bio_detain(tc->pool, &key, bio, &cell1))
  1500 + if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result))
1484 1501 return DM_MAPIO_SUBMITTED;
1485 1502  
1486 1503 build_data_key(tc->td, result.block, &key);
1487   - if (bio_detain(tc->pool, &key, bio, &cell2)) {
1488   - cell_defer_no_holder(tc, cell1);
  1504 + if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) {
  1505 + cell_defer_no_holder_no_free(tc, &cell1);
1489 1506 return DM_MAPIO_SUBMITTED;
1490 1507 }
1491 1508  
1492 1509 inc_all_io_entry(tc->pool, bio);
1493   - cell_defer_no_holder(tc, cell2);
1494   - cell_defer_no_holder(tc, cell1);
  1510 + cell_defer_no_holder_no_free(tc, &cell2);
  1511 + cell_defer_no_holder_no_free(tc, &cell1);
1495 1512  
1496 1513 remap(tc, bio, result.block);
1497 1514 return DM_MAPIO_REMAPPED;