Skip to content

Commit e319482

Browse files
author
Herton R. Krzesinski
committed
Merge: Fix outstanding device-mapper bugs from upstream 6.1 and 6.2 an dm-cache cleanup issue
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/1923 Bugzilla: https://bugzilla.redhat.com/2162536 Bugzilla: https://bugzilla.redhat.com/2163655 Tested: lvm-testsuite Upstream Status: kernel/git/torvalds/linux.git Pull in dm bugfixes from upstream and fix an existing dm-cache bug found while testing the changes. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Approved-by: Mike Snitzer <snitzer@redhat.com> Approved-by: Mikuláš Patočka <mpatocka@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents 1b9a043 + f659c4a commit e319482

File tree

9 files changed

+148
-32
lines changed

9 files changed

+148
-32
lines changed

drivers/md/dm-bufio.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
18571857
dm_io_client_destroy(c->dm_io);
18581858
bad_dm_io:
18591859
mutex_destroy(&c->lock);
1860+
if (c->no_sleep)
1861+
static_branch_dec(&no_sleep_enabled);
18601862
kfree(c);
18611863
bad_client:
18621864
return ERR_PTR(r);

drivers/md/dm-cache-background-tracker.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ EXPORT_SYMBOL_GPL(btracker_create);
6060

6161
void btracker_destroy(struct background_tracker *b)
6262
{
63+
struct bt_work *w, *tmp;
64+
65+
BUG_ON(!list_empty(&b->issued));
66+
list_for_each_entry_safe (w, tmp, &b->queued, list) {
67+
list_del(&w->list);
68+
kmem_cache_free(b->work_cache, w);
69+
}
70+
6371
kmem_cache_destroy(b->work_cache);
6472
kfree(b);
6573
}

drivers/md/dm-cache-metadata.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,13 @@ static int __create_persistent_data_objects(struct dm_cache_metadata *cmd,
551551
return r;
552552
}
553553

554-
static void __destroy_persistent_data_objects(struct dm_cache_metadata *cmd)
554+
static void __destroy_persistent_data_objects(struct dm_cache_metadata *cmd,
555+
bool destroy_bm)
555556
{
556557
dm_sm_destroy(cmd->metadata_sm);
557558
dm_tm_destroy(cmd->tm);
558-
dm_block_manager_destroy(cmd->bm);
559+
if (destroy_bm)
560+
dm_block_manager_destroy(cmd->bm);
559561
}
560562

561563
typedef unsigned long (*flags_mutator)(unsigned long);
@@ -826,7 +828,7 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev,
826828
cmd2 = lookup(bdev);
827829
if (cmd2) {
828830
mutex_unlock(&table_lock);
829-
__destroy_persistent_data_objects(cmd);
831+
__destroy_persistent_data_objects(cmd, true);
830832
kfree(cmd);
831833
return cmd2;
832834
}
@@ -874,7 +876,7 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
874876
mutex_unlock(&table_lock);
875877

876878
if (!cmd->fail_io)
877-
__destroy_persistent_data_objects(cmd);
879+
__destroy_persistent_data_objects(cmd, true);
878880
kfree(cmd);
879881
}
880882
}
@@ -1807,14 +1809,52 @@ int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result)
18071809

18081810
int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
18091811
{
1810-
int r;
1812+
int r = -EINVAL;
1813+
struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
1814+
1815+
/* fail_io is double-checked with cmd->root_lock held below */
1816+
if (unlikely(cmd->fail_io))
1817+
return r;
1818+
1819+
/*
1820+
* Replacement block manager (new_bm) is created and old_bm destroyed outside of
1821+
* cmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
1822+
* shrinker associated with the block manager's bufio client vs cmd root_lock).
1823+
* - must take shrinker_rwsem without holding cmd->root_lock
1824+
*/
1825+
new_bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
1826+
CACHE_MAX_CONCURRENT_LOCKS);
18111827

18121828
WRITE_LOCK(cmd);
1813-
__destroy_persistent_data_objects(cmd);
1814-
r = __create_persistent_data_objects(cmd, false);
1829+
if (cmd->fail_io) {
1830+
WRITE_UNLOCK(cmd);
1831+
goto out;
1832+
}
1833+
1834+
__destroy_persistent_data_objects(cmd, false);
1835+
old_bm = cmd->bm;
1836+
if (IS_ERR(new_bm)) {
1837+
DMERR("could not create block manager during abort");
1838+
cmd->bm = NULL;
1839+
r = PTR_ERR(new_bm);
1840+
goto out_unlock;
1841+
}
1842+
1843+
cmd->bm = new_bm;
1844+
r = __open_or_format_metadata(cmd, false);
1845+
if (r) {
1846+
cmd->bm = NULL;
1847+
goto out_unlock;
1848+
}
1849+
new_bm = NULL;
1850+
out_unlock:
18151851
if (r)
18161852
cmd->fail_io = true;
18171853
WRITE_UNLOCK(cmd);
1854+
dm_block_manager_destroy(old_bm);
1855+
out:
1856+
if (new_bm && !IS_ERR(new_bm))
1857+
dm_block_manager_destroy(new_bm);
18181858

18191859
return r;
18201860
}

drivers/md/dm-cache-target.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -907,16 +907,16 @@ static void abort_transaction(struct cache *cache)
907907
if (get_cache_mode(cache) >= CM_READ_ONLY)
908908
return;
909909

910-
if (dm_cache_metadata_set_needs_check(cache->cmd)) {
911-
DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name);
912-
set_cache_mode(cache, CM_FAIL);
913-
}
914-
915910
DMERR_LIMIT("%s: aborting current metadata transaction", dev_name);
916911
if (dm_cache_metadata_abort(cache->cmd)) {
917912
DMERR("%s: failed to abort metadata transaction", dev_name);
918913
set_cache_mode(cache, CM_FAIL);
919914
}
915+
916+
if (dm_cache_metadata_set_needs_check(cache->cmd)) {
917+
DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name);
918+
set_cache_mode(cache, CM_FAIL);
919+
}
920920
}
921921

922922
static void metadata_operation_failed(struct cache *cache, const char *op, int r)
@@ -1887,6 +1887,7 @@ static void destroy(struct cache *cache)
18871887
if (cache->prison)
18881888
dm_bio_prison_destroy_v2(cache->prison);
18891889

1890+
cancel_delayed_work_sync(&cache->waker);
18901891
if (cache->wq)
18911892
destroy_workqueue(cache->wq);
18921893

drivers/md/dm-clone-target.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,7 @@ static void clone_dtr(struct dm_target *ti)
19581958

19591959
mempool_exit(&clone->hydration_pool);
19601960
dm_kcopyd_client_destroy(clone->kcopyd_client);
1961+
cancel_delayed_work_sync(&clone->waker);
19611962
destroy_workqueue(clone->wq);
19621963
hash_table_exit(clone);
19631964
dm_clone_metadata_close(clone->cmd);

drivers/md/dm-integrity.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ struct dm_integrity_c {
261261

262262
struct completion crypto_backoff;
263263

264+
bool wrote_to_journal;
264265
bool journal_uptodate;
265266
bool just_formatted;
266267
bool recalculate_flag;
@@ -2373,6 +2374,8 @@ static void integrity_commit(struct work_struct *w)
23732374
if (!commit_sections)
23742375
goto release_flush_bios;
23752376

2377+
ic->wrote_to_journal = true;
2378+
23762379
i = commit_start;
23772380
for (n = 0; n < commit_sections; n++) {
23782381
for (j = 0; j < ic->journal_section_entries; j++) {
@@ -2589,10 +2592,6 @@ static void integrity_writer(struct work_struct *w)
25892592

25902593
unsigned prev_free_sectors;
25912594

2592-
/* the following test is not needed, but it tests the replay code */
2593-
if (unlikely(dm_post_suspending(ic->ti)) && !ic->meta_dev)
2594-
return;
2595-
25962595
spin_lock_irq(&ic->endio_wait.lock);
25972596
write_start = ic->committed_section;
25982597
write_sections = ic->n_committed_sections;
@@ -3098,10 +3097,17 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
30983097
drain_workqueue(ic->commit_wq);
30993098

31003099
if (ic->mode == 'J') {
3101-
if (ic->meta_dev)
3102-
queue_work(ic->writer_wq, &ic->writer_work);
3100+
queue_work(ic->writer_wq, &ic->writer_work);
31033101
drain_workqueue(ic->writer_wq);
31043102
dm_integrity_flush_buffers(ic, true);
3103+
if (ic->wrote_to_journal) {
3104+
init_journal(ic, ic->free_section,
3105+
ic->journal_sections - ic->free_section, ic->commit_seq);
3106+
if (ic->free_section) {
3107+
init_journal(ic, 0, ic->free_section,
3108+
next_commit_seq(ic->commit_seq));
3109+
}
3110+
}
31053111
}
31063112

31073113
if (ic->mode == 'B') {
@@ -3129,6 +3135,8 @@ static void dm_integrity_resume(struct dm_target *ti)
31293135

31303136
DEBUG_print("resume\n");
31313137

3138+
ic->wrote_to_journal = false;
3139+
31323140
if (ic->provided_data_sectors != old_provided_data_sectors) {
31333141
if (ic->provided_data_sectors > old_provided_data_sectors &&
31343142
ic->mode == 'B' &&
@@ -4547,6 +4555,8 @@ static void dm_integrity_dtr(struct dm_target *ti)
45474555
BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
45484556
BUG_ON(!list_empty(&ic->wait_list));
45494557

4558+
if (ic->mode == 'B')
4559+
cancel_delayed_work_sync(&ic->bitmap_flush_work);
45504560
if (ic->metadata_wq)
45514561
destroy_workqueue(ic->metadata_wq);
45524562
if (ic->wait_wq)

drivers/md/dm-ioctl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ static void list_version_get_needed(struct target_type *tt, void *needed_param)
655655
size_t *needed = needed_param;
656656

657657
*needed += sizeof(struct dm_target_versions);
658-
*needed += strlen(tt->name);
658+
*needed += strlen(tt->name) + 1;
659659
*needed += ALIGN_MASK;
660660
}
661661

@@ -720,7 +720,7 @@ static int __list_versions(struct dm_ioctl *param, size_t param_size, const char
720720
iter_info.old_vers = NULL;
721721
iter_info.vers = vers;
722722
iter_info.flags = 0;
723-
iter_info.end = (char *)vers+len;
723+
iter_info.end = (char *)vers + needed;
724724

725725
/*
726726
* Now loop through filling out the names & versions.

drivers/md/dm-thin-metadata.c

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,15 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
724724
goto bad_cleanup_data_sm;
725725
}
726726

727+
/*
728+
* For pool metadata opening process, root setting is redundant
729+
* because it will be set again in __begin_transaction(). But dm
730+
* pool aborting process really needs to get last transaction's
731+
* root to avoid accessing broken btree.
732+
*/
733+
pmd->root = le64_to_cpu(disk_super->data_mapping_root);
734+
pmd->details_root = le64_to_cpu(disk_super->device_details_root);
735+
727736
__setup_btree_details(pmd);
728737
dm_bm_unlock(sblock);
729738

@@ -776,13 +785,15 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
776785
return r;
777786
}
778787

779-
static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd)
788+
static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd,
789+
bool destroy_bm)
780790
{
781791
dm_sm_destroy(pmd->data_sm);
782792
dm_sm_destroy(pmd->metadata_sm);
783793
dm_tm_destroy(pmd->nb_tm);
784794
dm_tm_destroy(pmd->tm);
785-
dm_block_manager_destroy(pmd->bm);
795+
if (destroy_bm)
796+
dm_block_manager_destroy(pmd->bm);
786797
}
787798

788799
static int __begin_transaction(struct dm_pool_metadata *pmd)
@@ -989,7 +1000,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
9891000
}
9901001
pmd_write_unlock(pmd);
9911002
if (!pmd->fail_io)
992-
__destroy_persistent_data_objects(pmd);
1003+
__destroy_persistent_data_objects(pmd, true);
9931004

9941005
kfree(pmd);
9951006
return 0;
@@ -1860,19 +1871,52 @@ static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd)
18601871
int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
18611872
{
18621873
int r = -EINVAL;
1874+
struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
1875+
1876+
/* fail_io is double-checked with pmd->root_lock held below */
1877+
if (unlikely(pmd->fail_io))
1878+
return r;
1879+
1880+
/*
1881+
* Replacement block manager (new_bm) is created and old_bm destroyed outside of
1882+
* pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
1883+
* shrinker associated with the block manager's bufio client vs pmd root_lock).
1884+
* - must take shrinker_rwsem without holding pmd->root_lock
1885+
*/
1886+
new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
1887+
THIN_MAX_CONCURRENT_LOCKS);
18631888

18641889
pmd_write_lock(pmd);
1865-
if (pmd->fail_io)
1890+
if (pmd->fail_io) {
1891+
pmd_write_unlock(pmd);
18661892
goto out;
1893+
}
18671894

18681895
__set_abort_with_changes_flags(pmd);
1869-
__destroy_persistent_data_objects(pmd);
1870-
r = __create_persistent_data_objects(pmd, false);
1896+
__destroy_persistent_data_objects(pmd, false);
1897+
old_bm = pmd->bm;
1898+
if (IS_ERR(new_bm)) {
1899+
DMERR("could not create block manager during abort");
1900+
pmd->bm = NULL;
1901+
r = PTR_ERR(new_bm);
1902+
goto out_unlock;
1903+
}
1904+
1905+
pmd->bm = new_bm;
1906+
r = __open_or_format_metadata(pmd, false);
1907+
if (r) {
1908+
pmd->bm = NULL;
1909+
goto out_unlock;
1910+
}
1911+
new_bm = NULL;
1912+
out_unlock:
18711913
if (r)
18721914
pmd->fail_io = true;
1873-
1874-
out:
18751915
pmd_write_unlock(pmd);
1916+
dm_block_manager_destroy(old_bm);
1917+
out:
1918+
if (new_bm && !IS_ERR(new_bm))
1919+
dm_block_manager_destroy(new_bm);
18761920

18771921
return r;
18781922
}

drivers/md/dm-thin.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,6 +2889,8 @@ static void __pool_destroy(struct pool *pool)
28892889
dm_bio_prison_destroy(pool->prison);
28902890
dm_kcopyd_client_destroy(pool->copier);
28912891

2892+
cancel_delayed_work_sync(&pool->waker);
2893+
cancel_delayed_work_sync(&pool->no_space_timeout);
28922894
if (pool->wq)
28932895
destroy_workqueue(pool->wq);
28942896

@@ -3540,20 +3542,28 @@ static int pool_preresume(struct dm_target *ti)
35403542
*/
35413543
r = bind_control_target(pool, ti);
35423544
if (r)
3543-
return r;
3545+
goto out;
35443546

35453547
r = maybe_resize_data_dev(ti, &need_commit1);
35463548
if (r)
3547-
return r;
3549+
goto out;
35483550

35493551
r = maybe_resize_metadata_dev(ti, &need_commit2);
35503552
if (r)
3551-
return r;
3553+
goto out;
35523554

35533555
if (need_commit1 || need_commit2)
35543556
(void) commit(pool);
3557+
out:
3558+
/*
3559+
* When a thin-pool is PM_FAIL, it cannot be rebuilt if
3560+
* bio is in deferred list. Therefore need to return 0
3561+
* to allow pool_resume() to flush IO.
3562+
*/
3563+
if (r && get_pool_mode(pool) == PM_FAIL)
3564+
r = 0;
35553565

3556-
return 0;
3566+
return r;
35573567
}
35583568

35593569
static void pool_suspend_active_thins(struct pool *pool)

0 commit comments

Comments
 (0)