.. | .. |
---|
701 | 701 | goto bad_cleanup_data_sm; |
---|
702 | 702 | } |
---|
703 | 703 | |
---|
| 704 | + /* |
---|
| 705 | + * For pool metadata opening process, root setting is redundant |
---|
| 706 | + * because it will be set again in __begin_transaction(). But dm |
---|
| 707 | + * pool aborting process really needs to get last transaction's |
---|
| 708 | + * root to avoid accessing broken btree. |
---|
| 709 | + */ |
---|
| 710 | + pmd->root = le64_to_cpu(disk_super->data_mapping_root); |
---|
| 711 | + pmd->details_root = le64_to_cpu(disk_super->device_details_root); |
---|
| 712 | + |
---|
704 | 713 | __setup_btree_details(pmd); |
---|
705 | 714 | dm_bm_unlock(sblock); |
---|
706 | 715 | |
---|
.. | .. |
---|
753 | 762 | return r; |
---|
754 | 763 | } |
---|
755 | 764 | |
---|
756 | | -static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd) |
---|
| 765 | +static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd, |
---|
| 766 | + bool destroy_bm) |
---|
757 | 767 | { |
---|
758 | 768 | dm_sm_destroy(pmd->data_sm); |
---|
759 | 769 | dm_sm_destroy(pmd->metadata_sm); |
---|
760 | 770 | dm_tm_destroy(pmd->nb_tm); |
---|
761 | 771 | dm_tm_destroy(pmd->tm); |
---|
762 | | - dm_block_manager_destroy(pmd->bm); |
---|
| 772 | + if (destroy_bm) |
---|
| 773 | + dm_block_manager_destroy(pmd->bm); |
---|
763 | 774 | } |
---|
764 | 775 | |
---|
765 | 776 | static int __begin_transaction(struct dm_pool_metadata *pmd) |
---|
.. | .. |
---|
966 | 977 | } |
---|
967 | 978 | pmd_write_unlock(pmd); |
---|
968 | 979 | if (!pmd->fail_io) |
---|
969 | | - __destroy_persistent_data_objects(pmd); |
---|
| 980 | + __destroy_persistent_data_objects(pmd, true); |
---|
970 | 981 | |
---|
971 | 982 | kfree(pmd); |
---|
972 | 983 | return 0; |
---|
.. | .. |
---|
1873 | 1884 | int dm_pool_abort_metadata(struct dm_pool_metadata *pmd) |
---|
1874 | 1885 | { |
---|
1875 | 1886 | int r = -EINVAL; |
---|
| 1887 | + struct dm_block_manager *old_bm = NULL, *new_bm = NULL; |
---|
| 1888 | + |
---|
| 1889 | + /* fail_io is double-checked with pmd->root_lock held below */ |
---|
| 1890 | + if (unlikely(pmd->fail_io)) |
---|
| 1891 | + return r; |
---|
| 1892 | + |
---|
| 1893 | + /* |
---|
| 1894 | + * Replacement block manager (new_bm) is created and old_bm destroyed outside of |
---|
| 1895 | + * pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of |
---|
| 1896 | + * shrinker associated with the block manager's bufio client vs pmd root_lock). |
---|
| 1897 | + * - must take shrinker_rwsem without holding pmd->root_lock |
---|
| 1898 | + */ |
---|
| 1899 | + new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT, |
---|
| 1900 | + THIN_MAX_CONCURRENT_LOCKS); |
---|
1876 | 1901 | |
---|
1877 | 1902 | pmd_write_lock(pmd); |
---|
1878 | | - if (pmd->fail_io) |
---|
| 1903 | + if (pmd->fail_io) { |
---|
| 1904 | + pmd_write_unlock(pmd); |
---|
1879 | 1905 | goto out; |
---|
| 1906 | + } |
---|
1880 | 1907 | |
---|
1881 | 1908 | __set_abort_with_changes_flags(pmd); |
---|
1882 | | - __destroy_persistent_data_objects(pmd); |
---|
1883 | | - r = __create_persistent_data_objects(pmd, false); |
---|
| 1909 | + __destroy_persistent_data_objects(pmd, false); |
---|
| 1910 | + old_bm = pmd->bm; |
---|
| 1911 | + if (IS_ERR(new_bm)) { |
---|
| 1912 | + DMERR("could not create block manager during abort"); |
---|
| 1913 | + pmd->bm = NULL; |
---|
| 1914 | + r = PTR_ERR(new_bm); |
---|
| 1915 | + goto out_unlock; |
---|
| 1916 | + } |
---|
| 1917 | + |
---|
| 1918 | + pmd->bm = new_bm; |
---|
| 1919 | + r = __open_or_format_metadata(pmd, false); |
---|
| 1920 | + if (r) { |
---|
| 1921 | + pmd->bm = NULL; |
---|
| 1922 | + goto out_unlock; |
---|
| 1923 | + } |
---|
| 1924 | + new_bm = NULL; |
---|
| 1925 | +out_unlock: |
---|
1884 | 1926 | if (r) |
---|
1885 | 1927 | pmd->fail_io = true; |
---|
1886 | | - |
---|
1887 | | -out: |
---|
1888 | 1928 | pmd_write_unlock(pmd); |
---|
| 1929 | + dm_block_manager_destroy(old_bm); |
---|
| 1930 | +out: |
---|
| 1931 | + if (new_bm && !IS_ERR(new_bm)) |
---|
| 1932 | + dm_block_manager_destroy(new_bm); |
---|
1889 | 1933 | |
---|
1890 | 1934 | return r; |
---|
1891 | 1935 | } |
---|