hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/md/dm-cache-metadata.c
....@@ -551,11 +551,13 @@
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 @@
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 @@
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 }
....@@ -1808,14 +1810,52 @@
18081810
18091811 int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
18101812 {
1811
- int r;
1813
+ int r = -EINVAL;
1814
+ struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
1815
+
1816
+ /* fail_io is double-checked with cmd->root_lock held below */
1817
+ if (unlikely(cmd->fail_io))
1818
+ return r;
1819
+
1820
+ /*
1821
+ * Replacement block manager (new_bm) is created and old_bm destroyed outside of
1822
+ * cmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
1823
+ * shrinker associated with the block manager's bufio client vs cmd root_lock).
1824
+ * - must take shrinker_rwsem without holding cmd->root_lock
1825
+ */
1826
+ new_bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
1827
+ CACHE_MAX_CONCURRENT_LOCKS);
18121828
18131829 WRITE_LOCK(cmd);
1814
- __destroy_persistent_data_objects(cmd);
1815
- r = __create_persistent_data_objects(cmd, false);
1830
+ if (cmd->fail_io) {
1831
+ WRITE_UNLOCK(cmd);
1832
+ goto out;
1833
+ }
1834
+
1835
+ __destroy_persistent_data_objects(cmd, false);
1836
+ old_bm = cmd->bm;
1837
+ if (IS_ERR(new_bm)) {
1838
+ DMERR("could not create block manager during abort");
1839
+ cmd->bm = NULL;
1840
+ r = PTR_ERR(new_bm);
1841
+ goto out_unlock;
1842
+ }
1843
+
1844
+ cmd->bm = new_bm;
1845
+ r = __open_or_format_metadata(cmd, false);
1846
+ if (r) {
1847
+ cmd->bm = NULL;
1848
+ goto out_unlock;
1849
+ }
1850
+ new_bm = NULL;
1851
+out_unlock:
18161852 if (r)
18171853 cmd->fail_io = true;
18181854 WRITE_UNLOCK(cmd);
1855
+ dm_block_manager_destroy(old_bm);
1856
+out:
1857
+ if (new_bm && !IS_ERR(new_bm))
1858
+ dm_block_manager_destroy(new_bm);
18191859
18201860 return r;
18211861 }