diff options
-rw-r--r-- | drivers/md/dm-bufio.c | 16 | ||||
-rw-r--r-- | drivers/md/dm-cache-background-tracker.c | 5 | ||||
-rw-r--r-- | drivers/md/dm-cache-policy-smq.c | 31 | ||||
-rw-r--r-- | drivers/md/dm-cache-target.c | 27 | ||||
-rw-r--r-- | drivers/md/dm-mpath.c | 19 | ||||
-rw-r--r-- | drivers/md/dm-rq.c | 1 | ||||
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 4 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-space-map-disk.c | 15 |
8 files changed, 66 insertions, 52 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 5db11a405129..cd8139593ccd 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -218,7 +218,7 @@ static DEFINE_SPINLOCK(param_spinlock); | |||
218 | * Buffers are freed after this timeout | 218 | * Buffers are freed after this timeout |
219 | */ | 219 | */ |
220 | static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS; | 220 | static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS; |
221 | static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; | 221 | static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; |
222 | 222 | ||
223 | static unsigned long dm_bufio_peak_allocated; | 223 | static unsigned long dm_bufio_peak_allocated; |
224 | static unsigned long dm_bufio_allocated_kmem_cache; | 224 | static unsigned long dm_bufio_allocated_kmem_cache; |
@@ -1558,10 +1558,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp) | |||
1558 | return true; | 1558 | return true; |
1559 | } | 1559 | } |
1560 | 1560 | ||
1561 | static unsigned get_retain_buffers(struct dm_bufio_client *c) | 1561 | static unsigned long get_retain_buffers(struct dm_bufio_client *c) |
1562 | { | 1562 | { |
1563 | unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); | 1563 | unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); |
1564 | return retain_bytes / c->block_size; | 1564 | return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT); |
1565 | } | 1565 | } |
1566 | 1566 | ||
1567 | static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, | 1567 | static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, |
@@ -1571,7 +1571,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, | |||
1571 | struct dm_buffer *b, *tmp; | 1571 | struct dm_buffer *b, *tmp; |
1572 | unsigned long freed = 0; | 1572 | unsigned long freed = 0; |
1573 | unsigned long count = nr_to_scan; | 1573 | unsigned long count = nr_to_scan; |
1574 | unsigned retain_target = get_retain_buffers(c); | 1574 | unsigned long retain_target = get_retain_buffers(c); |
1575 | 1575 | ||
1576 | for (l = 0; l < LIST_SIZE; l++) { | 1576 | for (l = 0; l < LIST_SIZE; l++) { |
1577 | list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { | 1577 | list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { |
@@ -1794,8 +1794,8 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz) | |||
1794 | static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) | 1794 | static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) |
1795 | { | 1795 | { |
1796 | struct dm_buffer *b, *tmp; | 1796 | struct dm_buffer *b, *tmp; |
1797 | unsigned retain_target = get_retain_buffers(c); | 1797 | unsigned long retain_target = get_retain_buffers(c); |
1798 | unsigned count; | 1798 | unsigned long count; |
1799 | LIST_HEAD(write_list); | 1799 | LIST_HEAD(write_list); |
1800 | 1800 | ||
1801 | dm_bufio_lock(c); | 1801 | dm_bufio_lock(c); |
@@ -1955,7 +1955,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache"); | |||
1955 | module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR); | 1955 | module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR); |
1956 | MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds"); | 1956 | MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds"); |
1957 | 1957 | ||
1958 | module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR); | 1958 | module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR); |
1959 | MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory"); | 1959 | MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory"); |
1960 | 1960 | ||
1961 | module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR); | 1961 | module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR); |
diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c index 9b1afdfb13f0..707233891291 100644 --- a/drivers/md/dm-cache-background-tracker.c +++ b/drivers/md/dm-cache-background-tracker.c | |||
@@ -33,6 +33,11 @@ struct background_tracker *btracker_create(unsigned max_work) | |||
33 | { | 33 | { |
34 | struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL); | 34 | struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL); |
35 | 35 | ||
36 | if (!b) { | ||
37 | DMERR("couldn't create background_tracker"); | ||
38 | return NULL; | ||
39 | } | ||
40 | |||
36 | b->max_work = max_work; | 41 | b->max_work = max_work; |
37 | atomic_set(&b->pending_promotes, 0); | 42 | atomic_set(&b->pending_promotes, 0); |
38 | atomic_set(&b->pending_writebacks, 0); | 43 | atomic_set(&b->pending_writebacks, 0); |
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index 72479bd61e11..e5eb9c9b4bc8 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c | |||
@@ -1120,8 +1120,6 @@ static bool clean_target_met(struct smq_policy *mq, bool idle) | |||
1120 | * Cache entries may not be populated. So we cannot rely on the | 1120 | * Cache entries may not be populated. So we cannot rely on the |
1121 | * size of the clean queue. | 1121 | * size of the clean queue. |
1122 | */ | 1122 | */ |
1123 | unsigned nr_clean; | ||
1124 | |||
1125 | if (idle) { | 1123 | if (idle) { |
1126 | /* | 1124 | /* |
1127 | * We'd like to clean everything. | 1125 | * We'd like to clean everything. |
@@ -1129,18 +1127,16 @@ static bool clean_target_met(struct smq_policy *mq, bool idle) | |||
1129 | return q_size(&mq->dirty) == 0u; | 1127 | return q_size(&mq->dirty) == 0u; |
1130 | } | 1128 | } |
1131 | 1129 | ||
1132 | nr_clean = from_cblock(mq->cache_size) - q_size(&mq->dirty); | 1130 | /* |
1133 | return (nr_clean + btracker_nr_writebacks_queued(mq->bg_work)) >= | 1131 | * If we're busy we don't worry about cleaning at all. |
1134 | percent_to_target(mq, CLEAN_TARGET); | 1132 | */ |
1133 | return true; | ||
1135 | } | 1134 | } |
1136 | 1135 | ||
1137 | static bool free_target_met(struct smq_policy *mq, bool idle) | 1136 | static bool free_target_met(struct smq_policy *mq) |
1138 | { | 1137 | { |
1139 | unsigned nr_free; | 1138 | unsigned nr_free; |
1140 | 1139 | ||
1141 | if (!idle) | ||
1142 | return true; | ||
1143 | |||
1144 | nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated; | 1140 | nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated; |
1145 | return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >= | 1141 | return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >= |
1146 | percent_to_target(mq, FREE_TARGET); | 1142 | percent_to_target(mq, FREE_TARGET); |
@@ -1190,9 +1186,9 @@ static void queue_demotion(struct smq_policy *mq) | |||
1190 | if (unlikely(WARN_ON_ONCE(!mq->migrations_allowed))) | 1186 | if (unlikely(WARN_ON_ONCE(!mq->migrations_allowed))) |
1191 | return; | 1187 | return; |
1192 | 1188 | ||
1193 | e = q_peek(&mq->clean, mq->clean.nr_levels, true); | 1189 | e = q_peek(&mq->clean, mq->clean.nr_levels / 2, true); |
1194 | if (!e) { | 1190 | if (!e) { |
1195 | if (!clean_target_met(mq, false)) | 1191 | if (!clean_target_met(mq, true)) |
1196 | queue_writeback(mq); | 1192 | queue_writeback(mq); |
1197 | return; | 1193 | return; |
1198 | } | 1194 | } |
@@ -1220,7 +1216,7 @@ static void queue_promotion(struct smq_policy *mq, dm_oblock_t oblock, | |||
1220 | * We always claim to be 'idle' to ensure some demotions happen | 1216 | * We always claim to be 'idle' to ensure some demotions happen |
1221 | * with continuous loads. | 1217 | * with continuous loads. |
1222 | */ | 1218 | */ |
1223 | if (!free_target_met(mq, true)) | 1219 | if (!free_target_met(mq)) |
1224 | queue_demotion(mq); | 1220 | queue_demotion(mq); |
1225 | return; | 1221 | return; |
1226 | } | 1222 | } |
@@ -1421,14 +1417,10 @@ static int smq_get_background_work(struct dm_cache_policy *p, bool idle, | |||
1421 | spin_lock_irqsave(&mq->lock, flags); | 1417 | spin_lock_irqsave(&mq->lock, flags); |
1422 | r = btracker_issue(mq->bg_work, result); | 1418 | r = btracker_issue(mq->bg_work, result); |
1423 | if (r == -ENODATA) { | 1419 | if (r == -ENODATA) { |
1424 | /* find some writeback work to do */ | 1420 | if (!clean_target_met(mq, idle)) { |
1425 | if (mq->migrations_allowed && !free_target_met(mq, idle)) | ||
1426 | queue_demotion(mq); | ||
1427 | |||
1428 | else if (!clean_target_met(mq, idle)) | ||
1429 | queue_writeback(mq); | 1421 | queue_writeback(mq); |
1430 | 1422 | r = btracker_issue(mq->bg_work, result); | |
1431 | r = btracker_issue(mq->bg_work, result); | 1423 | } |
1432 | } | 1424 | } |
1433 | spin_unlock_irqrestore(&mq->lock, flags); | 1425 | spin_unlock_irqrestore(&mq->lock, flags); |
1434 | 1426 | ||
@@ -1452,6 +1444,7 @@ static void __complete_background_work(struct smq_policy *mq, | |||
1452 | clear_pending(mq, e); | 1444 | clear_pending(mq, e); |
1453 | if (success) { | 1445 | if (success) { |
1454 | e->oblock = work->oblock; | 1446 | e->oblock = work->oblock; |
1447 | e->level = NR_CACHE_LEVELS - 1; | ||
1455 | push(mq, e); | 1448 | push(mq, e); |
1456 | // h, q, a | 1449 | // h, q, a |
1457 | } else { | 1450 | } else { |
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1db375f50a13..d682a0511381 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c | |||
@@ -94,6 +94,9 @@ static void iot_io_begin(struct io_tracker *iot, sector_t len) | |||
94 | 94 | ||
95 | static void __iot_io_end(struct io_tracker *iot, sector_t len) | 95 | static void __iot_io_end(struct io_tracker *iot, sector_t len) |
96 | { | 96 | { |
97 | if (!len) | ||
98 | return; | ||
99 | |||
97 | iot->in_flight -= len; | 100 | iot->in_flight -= len; |
98 | if (!iot->in_flight) | 101 | if (!iot->in_flight) |
99 | iot->idle_time = jiffies; | 102 | iot->idle_time = jiffies; |
@@ -474,7 +477,7 @@ struct cache { | |||
474 | spinlock_t invalidation_lock; | 477 | spinlock_t invalidation_lock; |
475 | struct list_head invalidation_requests; | 478 | struct list_head invalidation_requests; |
476 | 479 | ||
477 | struct io_tracker origin_tracker; | 480 | struct io_tracker tracker; |
478 | 481 | ||
479 | struct work_struct commit_ws; | 482 | struct work_struct commit_ws; |
480 | struct batcher committer; | 483 | struct batcher committer; |
@@ -901,8 +904,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio) | |||
901 | 904 | ||
902 | static bool accountable_bio(struct cache *cache, struct bio *bio) | 905 | static bool accountable_bio(struct cache *cache, struct bio *bio) |
903 | { | 906 | { |
904 | return ((bio->bi_bdev == cache->origin_dev->bdev) && | 907 | return bio_op(bio) != REQ_OP_DISCARD; |
905 | bio_op(bio) != REQ_OP_DISCARD); | ||
906 | } | 908 | } |
907 | 909 | ||
908 | static void accounted_begin(struct cache *cache, struct bio *bio) | 910 | static void accounted_begin(struct cache *cache, struct bio *bio) |
@@ -912,7 +914,7 @@ static void accounted_begin(struct cache *cache, struct bio *bio) | |||
912 | 914 | ||
913 | if (accountable_bio(cache, bio)) { | 915 | if (accountable_bio(cache, bio)) { |
914 | pb->len = bio_sectors(bio); | 916 | pb->len = bio_sectors(bio); |
915 | iot_io_begin(&cache->origin_tracker, pb->len); | 917 | iot_io_begin(&cache->tracker, pb->len); |
916 | } | 918 | } |
917 | } | 919 | } |
918 | 920 | ||
@@ -921,7 +923,7 @@ static void accounted_complete(struct cache *cache, struct bio *bio) | |||
921 | size_t pb_data_size = get_per_bio_data_size(cache); | 923 | size_t pb_data_size = get_per_bio_data_size(cache); |
922 | struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); | 924 | struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); |
923 | 925 | ||
924 | iot_io_end(&cache->origin_tracker, pb->len); | 926 | iot_io_end(&cache->tracker, pb->len); |
925 | } | 927 | } |
926 | 928 | ||
927 | static void accounted_request(struct cache *cache, struct bio *bio) | 929 | static void accounted_request(struct cache *cache, struct bio *bio) |
@@ -1716,20 +1718,19 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock, | |||
1716 | 1718 | ||
1717 | enum busy { | 1719 | enum busy { |
1718 | IDLE, | 1720 | IDLE, |
1719 | MODERATE, | ||
1720 | BUSY | 1721 | BUSY |
1721 | }; | 1722 | }; |
1722 | 1723 | ||
1723 | static enum busy spare_migration_bandwidth(struct cache *cache) | 1724 | static enum busy spare_migration_bandwidth(struct cache *cache) |
1724 | { | 1725 | { |
1725 | bool idle = iot_idle_for(&cache->origin_tracker, HZ); | 1726 | bool idle = iot_idle_for(&cache->tracker, HZ); |
1726 | sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) * | 1727 | sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) * |
1727 | cache->sectors_per_block; | 1728 | cache->sectors_per_block; |
1728 | 1729 | ||
1729 | if (current_volume <= cache->migration_threshold) | 1730 | if (idle && current_volume <= cache->migration_threshold) |
1730 | return idle ? IDLE : MODERATE; | 1731 | return IDLE; |
1731 | else | 1732 | else |
1732 | return idle ? MODERATE : BUSY; | 1733 | return BUSY; |
1733 | } | 1734 | } |
1734 | 1735 | ||
1735 | static void inc_hit_counter(struct cache *cache, struct bio *bio) | 1736 | static void inc_hit_counter(struct cache *cache, struct bio *bio) |
@@ -2045,8 +2046,6 @@ static void check_migrations(struct work_struct *ws) | |||
2045 | 2046 | ||
2046 | for (;;) { | 2047 | for (;;) { |
2047 | b = spare_migration_bandwidth(cache); | 2048 | b = spare_migration_bandwidth(cache); |
2048 | if (b == BUSY) | ||
2049 | break; | ||
2050 | 2049 | ||
2051 | r = policy_get_background_work(cache->policy, b == IDLE, &op); | 2050 | r = policy_get_background_work(cache->policy, b == IDLE, &op); |
2052 | if (r == -ENODATA) | 2051 | if (r == -ENODATA) |
@@ -2717,7 +2716,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
2717 | 2716 | ||
2718 | batcher_init(&cache->committer, commit_op, cache, | 2717 | batcher_init(&cache->committer, commit_op, cache, |
2719 | issue_op, cache, cache->wq); | 2718 | issue_op, cache, cache->wq); |
2720 | iot_init(&cache->origin_tracker); | 2719 | iot_init(&cache->tracker); |
2721 | 2720 | ||
2722 | init_rwsem(&cache->background_work_lock); | 2721 | init_rwsem(&cache->background_work_lock); |
2723 | prevent_background_work(cache); | 2722 | prevent_background_work(cache); |
@@ -2941,7 +2940,7 @@ static void cache_postsuspend(struct dm_target *ti) | |||
2941 | 2940 | ||
2942 | cancel_delayed_work(&cache->waker); | 2941 | cancel_delayed_work(&cache->waker); |
2943 | flush_workqueue(cache->wq); | 2942 | flush_workqueue(cache->wq); |
2944 | WARN_ON(cache->origin_tracker.in_flight); | 2943 | WARN_ON(cache->tracker.in_flight); |
2945 | 2944 | ||
2946 | /* | 2945 | /* |
2947 | * If it's a flush suspend there won't be any deferred bios, so this | 2946 | * If it's a flush suspend there won't be any deferred bios, so this |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 926a6bcb32c8..3df056b73b66 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -447,7 +447,7 @@ failed: | |||
447 | * it has been invoked. | 447 | * it has been invoked. |
448 | */ | 448 | */ |
449 | #define dm_report_EIO(m) \ | 449 | #define dm_report_EIO(m) \ |
450 | ({ \ | 450 | do { \ |
451 | struct mapped_device *md = dm_table_get_md((m)->ti->table); \ | 451 | struct mapped_device *md = dm_table_get_md((m)->ti->table); \ |
452 | \ | 452 | \ |
453 | pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \ | 453 | pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \ |
@@ -455,8 +455,7 @@ failed: | |||
455 | test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags), \ | 455 | test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags), \ |
456 | test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags), \ | 456 | test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags), \ |
457 | dm_noflush_suspending((m)->ti)); \ | 457 | dm_noflush_suspending((m)->ti)); \ |
458 | -EIO; \ | 458 | } while (0) |
459 | }) | ||
460 | 459 | ||
461 | /* | 460 | /* |
462 | * Map cloned requests (request-based multipath) | 461 | * Map cloned requests (request-based multipath) |
@@ -481,7 +480,8 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq, | |||
481 | if (!pgpath) { | 480 | if (!pgpath) { |
482 | if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) | 481 | if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) |
483 | return DM_MAPIO_DELAY_REQUEUE; | 482 | return DM_MAPIO_DELAY_REQUEUE; |
484 | return dm_report_EIO(m); /* Failed */ | 483 | dm_report_EIO(m); /* Failed */ |
484 | return DM_MAPIO_KILL; | ||
485 | } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) || | 485 | } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) || |
486 | test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) { | 486 | test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) { |
487 | if (pg_init_all_paths(m)) | 487 | if (pg_init_all_paths(m)) |
@@ -558,7 +558,8 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m | |||
558 | if (!pgpath) { | 558 | if (!pgpath) { |
559 | if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) | 559 | if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) |
560 | return DM_MAPIO_REQUEUE; | 560 | return DM_MAPIO_REQUEUE; |
561 | return dm_report_EIO(m); | 561 | dm_report_EIO(m); |
562 | return -EIO; | ||
562 | } | 563 | } |
563 | 564 | ||
564 | mpio->pgpath = pgpath; | 565 | mpio->pgpath = pgpath; |
@@ -1493,7 +1494,7 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone, | |||
1493 | if (atomic_read(&m->nr_valid_paths) == 0 && | 1494 | if (atomic_read(&m->nr_valid_paths) == 0 && |
1494 | !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { | 1495 | !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { |
1495 | if (error == -EIO) | 1496 | if (error == -EIO) |
1496 | error = dm_report_EIO(m); | 1497 | dm_report_EIO(m); |
1497 | /* complete with the original error */ | 1498 | /* complete with the original error */ |
1498 | r = DM_ENDIO_DONE; | 1499 | r = DM_ENDIO_DONE; |
1499 | } | 1500 | } |
@@ -1524,8 +1525,10 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone, | |||
1524 | fail_path(mpio->pgpath); | 1525 | fail_path(mpio->pgpath); |
1525 | 1526 | ||
1526 | if (atomic_read(&m->nr_valid_paths) == 0 && | 1527 | if (atomic_read(&m->nr_valid_paths) == 0 && |
1527 | !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) | 1528 | !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { |
1528 | return dm_report_EIO(m); | 1529 | dm_report_EIO(m); |
1530 | return -EIO; | ||
1531 | } | ||
1529 | 1532 | ||
1530 | /* Queue for the daemon to resubmit */ | 1533 | /* Queue for the daemon to resubmit */ |
1531 | dm_bio_restore(get_bio_details_from_bio(clone), clone); | 1534 | dm_bio_restore(get_bio_details_from_bio(clone), clone); |
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 2af27026aa2e..b639fa7246ee 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c | |||
@@ -507,6 +507,7 @@ static int map_request(struct dm_rq_target_io *tio) | |||
507 | case DM_MAPIO_KILL: | 507 | case DM_MAPIO_KILL: |
508 | /* The target wants to complete the I/O */ | 508 | /* The target wants to complete the I/O */ |
509 | dm_kill_unmapped_request(rq, -EIO); | 509 | dm_kill_unmapped_request(rq, -EIO); |
510 | break; | ||
510 | default: | 511 | default: |
511 | DMWARN("unimplemented target map return value: %d", r); | 512 | DMWARN("unimplemented target map return value: %d", r); |
512 | BUG(); | 513 | BUG(); |
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 0f0251d0d337..d31d18d9727c 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -484,11 +484,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd) | |||
484 | if (r < 0) | 484 | if (r < 0) |
485 | return r; | 485 | return r; |
486 | 486 | ||
487 | r = save_sm_roots(pmd); | 487 | r = dm_tm_pre_commit(pmd->tm); |
488 | if (r < 0) | 488 | if (r < 0) |
489 | return r; | 489 | return r; |
490 | 490 | ||
491 | r = dm_tm_pre_commit(pmd->tm); | 491 | r = save_sm_roots(pmd); |
492 | if (r < 0) | 492 | if (r < 0) |
493 | return r; | 493 | return r; |
494 | 494 | ||
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index ebb280a14325..32adf6b4a9c7 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c | |||
@@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b) | |||
142 | 142 | ||
143 | static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b) | 143 | static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b) |
144 | { | 144 | { |
145 | int r; | ||
146 | uint32_t old_count; | ||
145 | enum allocation_event ev; | 147 | enum allocation_event ev; |
146 | struct sm_disk *smd = container_of(sm, struct sm_disk, sm); | 148 | struct sm_disk *smd = container_of(sm, struct sm_disk, sm); |
147 | 149 | ||
148 | return sm_ll_dec(&smd->ll, b, &ev); | 150 | r = sm_ll_dec(&smd->ll, b, &ev); |
151 | if (!r && (ev == SM_FREE)) { | ||
152 | /* | ||
153 | * It's only free if it's also free in the last | ||
154 | * transaction. | ||
155 | */ | ||
156 | r = sm_ll_lookup(&smd->old_ll, b, &old_count); | ||
157 | if (!r && !old_count) | ||
158 | smd->nr_allocated_this_transaction--; | ||
159 | } | ||
160 | |||
161 | return r; | ||
149 | } | 162 | } |
150 | 163 | ||
151 | static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) | 164 | static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) |