diff options
| -rw-r--r-- | drivers/md/dm-bio-prison.c | 7 | ||||
| -rw-r--r-- | drivers/md/dm-bio-prison.h | 12 | ||||
| -rw-r--r-- | drivers/md/dm-thin.c | 47 |
3 files changed, 43 insertions, 23 deletions
diff --git a/drivers/md/dm-bio-prison.c b/drivers/md/dm-bio-prison.c index ca5771d3ffd7..144067c95aba 100644 --- a/drivers/md/dm-bio-prison.c +++ b/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 | struct dm_bio_prison { | 17 | struct dm_bio_prison { |
| 25 | spinlock_t lock; | 18 | spinlock_t lock; |
| 26 | mempool_t *cell_pool; | 19 | mempool_t *cell_pool; |
diff --git a/drivers/md/dm-bio-prison.h b/drivers/md/dm-bio-prison.h index 11af2182101b..981a02d3a055 100644 --- a/drivers/md/dm-bio-prison.h +++ b/drivers/md/dm-bio-prison.h | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | * subsequently unlocked the bios become available. | 22 | * subsequently unlocked the bios become available. |
| 23 | */ | 23 | */ |
| 24 | struct dm_bio_prison; | 24 | struct dm_bio_prison; |
| 25 | struct dm_bio_prison_cell; | ||
| 26 | 25 | ||
| 27 | /* FIXME: this needs to be more abstract */ | 26 | /* FIXME: this needs to be more abstract */ |
| 28 | struct dm_cell_key { | 27 | struct dm_cell_key { |
| @@ -31,6 +30,17 @@ struct dm_cell_key { | |||
| 31 | dm_block_t block; | 30 | dm_block_t block; |
| 32 | }; | 31 | }; |
| 33 | 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; | ||
| 42 | }; | ||
| 43 | |||
| 34 | struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells); | 44 | struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells); |
| 35 | void dm_bio_prison_destroy(struct dm_bio_prison *prison); | 45 | void dm_bio_prison_destroy(struct dm_bio_prison *prison); |
| 36 | 46 | ||
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 5304e3a29a14..009339d62828 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -229,6 +229,17 @@ struct thin_c { | |||
| 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 | static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio, | 243 | static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio, |
| 233 | struct dm_bio_prison_cell **cell_result) | 244 | struct dm_bio_prison_cell **cell_result) |
| 234 | { | 245 | { |
| @@ -268,6 +279,19 @@ static void cell_release_no_holder(struct pool *pool, | |||
| 268 | dm_bio_prison_free_cell(pool->prison, cell); | 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 | static void cell_error(struct pool *pool, | 295 | static void cell_error(struct pool *pool, |
| 272 | struct dm_bio_prison_cell *cell) | 296 | struct dm_bio_prison_cell *cell) |
| 273 | { | 297 | { |
| @@ -477,15 +501,6 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio, | |||
| 477 | issue(tc, bio); | 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 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m) | |||
| 601 | list_del(&m->list); | 616 | list_del(&m->list); |
| 602 | mempool_free(m, m->tc->pool->mapping_pool); | 617 | mempool_free(m, m->tc->pool->mapping_pool); |
| 603 | } | 618 | } |
| 619 | |||
| 604 | static void process_prepared_mapping(struct dm_thin_new_mapping *m) | 620 | static void process_prepared_mapping(struct dm_thin_new_mapping *m) |
| 605 | { | 621 | { |
| 606 | struct thin_c *tc = m->tc; | 622 | struct thin_c *tc = m->tc; |
| @@ -1438,7 +1454,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
| 1438 | dm_block_t block = get_bio_block(tc, bio); | 1454 | dm_block_t block = get_bio_block(tc, bio); |
| 1439 | struct dm_thin_device *td = tc->td; | 1455 | struct dm_thin_device *td = tc->td; |
| 1440 | struct dm_thin_lookup_result result; | 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 | struct dm_cell_key key; | 1459 | struct dm_cell_key key; |
| 1443 | 1460 | ||
| 1444 | thin_hook_bio(tc, bio); | 1461 | thin_hook_bio(tc, bio); |
| @@ -1480,18 +1497,18 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
| 1480 | } | 1497 | } |
| 1481 | 1498 | ||
| 1482 | build_virtual_key(tc->td, block, &key); | 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 | return DM_MAPIO_SUBMITTED; | 1501 | return DM_MAPIO_SUBMITTED; |
| 1485 | 1502 | ||
| 1486 | build_data_key(tc->td, result.block, &key); | 1503 | build_data_key(tc->td, result.block, &key); |
| 1487 | if (bio_detain(tc->pool, &key, bio, &cell2)) { | 1504 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) { |
| 1488 | cell_defer_no_holder(tc, cell1); | 1505 | cell_defer_no_holder_no_free(tc, &cell1); |
| 1489 | return DM_MAPIO_SUBMITTED; | 1506 | return DM_MAPIO_SUBMITTED; |
| 1490 | } | 1507 | } |
| 1491 | 1508 | ||
| 1492 | inc_all_io_entry(tc->pool, bio); | 1509 | inc_all_io_entry(tc->pool, bio); |
| 1493 | cell_defer_no_holder(tc, cell2); | 1510 | cell_defer_no_holder_no_free(tc, &cell2); |
| 1494 | cell_defer_no_holder(tc, cell1); | 1511 | cell_defer_no_holder_no_free(tc, &cell1); |
| 1495 | 1512 | ||
| 1496 | remap(tc, bio, result.block); | 1513 | remap(tc, bio, result.block); |
| 1497 | return DM_MAPIO_REMAPPED; | 1514 | return DM_MAPIO_REMAPPED; |
