diff options
-rw-r--r-- | Documentation/device-mapper/cache.txt | 4 | ||||
-rw-r--r-- | drivers/md/dm-cache-metadata.c | 278 | ||||
-rw-r--r-- | drivers/md/dm-cache-metadata.h | 11 | ||||
-rw-r--r-- | drivers/md/dm-cache-target.c | 38 |
4 files changed, 278 insertions, 53 deletions
diff --git a/Documentation/device-mapper/cache.txt b/Documentation/device-mapper/cache.txt index 785eab87aa71..f228604ddbcd 100644 --- a/Documentation/device-mapper/cache.txt +++ b/Documentation/device-mapper/cache.txt | |||
@@ -207,6 +207,10 @@ Optional feature arguments are: | |||
207 | block, then the cache block is invalidated. | 207 | block, then the cache block is invalidated. |
208 | To enable passthrough mode the cache must be clean. | 208 | To enable passthrough mode the cache must be clean. |
209 | 209 | ||
210 | metadata2 : use version 2 of the metadata. This stores the dirty bits | ||
211 | in a separate btree, which improves speed of shutting | ||
212 | down the cache. | ||
213 | |||
210 | A policy called 'default' is always registered. This is an alias for | 214 | A policy called 'default' is always registered. This is an alias for |
211 | the policy we currently think is giving best all round performance. | 215 | the policy we currently think is giving best all round performance. |
212 | 216 | ||
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 9364a02e1646..0610be7846dc 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * defines a range of metadata versions that this module can handle. | 25 | * defines a range of metadata versions that this module can handle. |
26 | */ | 26 | */ |
27 | #define MIN_CACHE_VERSION 1 | 27 | #define MIN_CACHE_VERSION 1 |
28 | #define MAX_CACHE_VERSION 1 | 28 | #define MAX_CACHE_VERSION 2 |
29 | 29 | ||
30 | #define CACHE_METADATA_CACHE_SIZE 64 | 30 | #define CACHE_METADATA_CACHE_SIZE 64 |
31 | 31 | ||
@@ -55,6 +55,7 @@ enum mapping_bits { | |||
55 | 55 | ||
56 | /* | 56 | /* |
57 | * The data on the cache is different from that on the origin. | 57 | * The data on the cache is different from that on the origin. |
58 | * This flag is only used by metadata format 1. | ||
58 | */ | 59 | */ |
59 | M_DIRTY = 2 | 60 | M_DIRTY = 2 |
60 | }; | 61 | }; |
@@ -93,12 +94,18 @@ struct cache_disk_superblock { | |||
93 | __le32 write_misses; | 94 | __le32 write_misses; |
94 | 95 | ||
95 | __le32 policy_version[CACHE_POLICY_VERSION_SIZE]; | 96 | __le32 policy_version[CACHE_POLICY_VERSION_SIZE]; |
97 | |||
98 | /* | ||
99 | * Metadata format 2 fields. | ||
100 | */ | ||
101 | __le64 dirty_root; | ||
96 | } __packed; | 102 | } __packed; |
97 | 103 | ||
98 | struct dm_cache_metadata { | 104 | struct dm_cache_metadata { |
99 | atomic_t ref_count; | 105 | atomic_t ref_count; |
100 | struct list_head list; | 106 | struct list_head list; |
101 | 107 | ||
108 | unsigned version; | ||
102 | struct block_device *bdev; | 109 | struct block_device *bdev; |
103 | struct dm_block_manager *bm; | 110 | struct dm_block_manager *bm; |
104 | struct dm_space_map *metadata_sm; | 111 | struct dm_space_map *metadata_sm; |
@@ -142,11 +149,18 @@ struct dm_cache_metadata { | |||
142 | bool fail_io:1; | 149 | bool fail_io:1; |
143 | 150 | ||
144 | /* | 151 | /* |
152 | * Metadata format 2 fields. | ||
153 | */ | ||
154 | dm_block_t dirty_root; | ||
155 | struct dm_disk_bitset dirty_info; | ||
156 | |||
157 | /* | ||
145 | * These structures are used when loading metadata. They're too | 158 | * These structures are used when loading metadata. They're too |
146 | * big to put on the stack. | 159 | * big to put on the stack. |
147 | */ | 160 | */ |
148 | struct dm_array_cursor mapping_cursor; | 161 | struct dm_array_cursor mapping_cursor; |
149 | struct dm_array_cursor hint_cursor; | 162 | struct dm_array_cursor hint_cursor; |
163 | struct dm_bitset_cursor dirty_cursor; | ||
150 | }; | 164 | }; |
151 | 165 | ||
152 | /*------------------------------------------------------------------- | 166 | /*------------------------------------------------------------------- |
@@ -170,6 +184,7 @@ static void sb_prepare_for_write(struct dm_block_validator *v, | |||
170 | static int check_metadata_version(struct cache_disk_superblock *disk_super) | 184 | static int check_metadata_version(struct cache_disk_superblock *disk_super) |
171 | { | 185 | { |
172 | uint32_t metadata_version = le32_to_cpu(disk_super->version); | 186 | uint32_t metadata_version = le32_to_cpu(disk_super->version); |
187 | |||
173 | if (metadata_version < MIN_CACHE_VERSION || metadata_version > MAX_CACHE_VERSION) { | 188 | if (metadata_version < MIN_CACHE_VERSION || metadata_version > MAX_CACHE_VERSION) { |
174 | DMERR("Cache metadata version %u found, but only versions between %u and %u supported.", | 189 | DMERR("Cache metadata version %u found, but only versions between %u and %u supported.", |
175 | metadata_version, MIN_CACHE_VERSION, MAX_CACHE_VERSION); | 190 | metadata_version, MIN_CACHE_VERSION, MAX_CACHE_VERSION); |
@@ -310,6 +325,11 @@ static void __copy_sm_root(struct dm_cache_metadata *cmd, | |||
310 | sizeof(cmd->metadata_space_map_root)); | 325 | sizeof(cmd->metadata_space_map_root)); |
311 | } | 326 | } |
312 | 327 | ||
328 | static bool separate_dirty_bits(struct dm_cache_metadata *cmd) | ||
329 | { | ||
330 | return cmd->version >= 2; | ||
331 | } | ||
332 | |||
313 | static int __write_initial_superblock(struct dm_cache_metadata *cmd) | 333 | static int __write_initial_superblock(struct dm_cache_metadata *cmd) |
314 | { | 334 | { |
315 | int r; | 335 | int r; |
@@ -341,7 +361,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) | |||
341 | disk_super->flags = 0; | 361 | disk_super->flags = 0; |
342 | memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); | 362 | memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); |
343 | disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); | 363 | disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); |
344 | disk_super->version = cpu_to_le32(MAX_CACHE_VERSION); | 364 | disk_super->version = cpu_to_le32(cmd->version); |
345 | memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); | 365 | memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); |
346 | memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); | 366 | memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); |
347 | disk_super->policy_hint_size = 0; | 367 | disk_super->policy_hint_size = 0; |
@@ -362,6 +382,9 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) | |||
362 | disk_super->write_hits = cpu_to_le32(0); | 382 | disk_super->write_hits = cpu_to_le32(0); |
363 | disk_super->write_misses = cpu_to_le32(0); | 383 | disk_super->write_misses = cpu_to_le32(0); |
364 | 384 | ||
385 | if (separate_dirty_bits(cmd)) | ||
386 | disk_super->dirty_root = cpu_to_le64(cmd->dirty_root); | ||
387 | |||
365 | return dm_tm_commit(cmd->tm, sblock); | 388 | return dm_tm_commit(cmd->tm, sblock); |
366 | } | 389 | } |
367 | 390 | ||
@@ -382,6 +405,13 @@ static int __format_metadata(struct dm_cache_metadata *cmd) | |||
382 | if (r < 0) | 405 | if (r < 0) |
383 | goto bad; | 406 | goto bad; |
384 | 407 | ||
408 | if (separate_dirty_bits(cmd)) { | ||
409 | dm_disk_bitset_init(cmd->tm, &cmd->dirty_info); | ||
410 | r = dm_bitset_empty(&cmd->dirty_info, &cmd->dirty_root); | ||
411 | if (r < 0) | ||
412 | goto bad; | ||
413 | } | ||
414 | |||
385 | dm_disk_bitset_init(cmd->tm, &cmd->discard_info); | 415 | dm_disk_bitset_init(cmd->tm, &cmd->discard_info); |
386 | r = dm_bitset_empty(&cmd->discard_info, &cmd->discard_root); | 416 | r = dm_bitset_empty(&cmd->discard_info, &cmd->discard_root); |
387 | if (r < 0) | 417 | if (r < 0) |
@@ -407,9 +437,10 @@ bad: | |||
407 | static int __check_incompat_features(struct cache_disk_superblock *disk_super, | 437 | static int __check_incompat_features(struct cache_disk_superblock *disk_super, |
408 | struct dm_cache_metadata *cmd) | 438 | struct dm_cache_metadata *cmd) |
409 | { | 439 | { |
410 | uint32_t features; | 440 | uint32_t incompat_flags, features; |
411 | 441 | ||
412 | features = le32_to_cpu(disk_super->incompat_flags) & ~DM_CACHE_FEATURE_INCOMPAT_SUPP; | 442 | incompat_flags = le32_to_cpu(disk_super->incompat_flags); |
443 | features = incompat_flags & ~DM_CACHE_FEATURE_INCOMPAT_SUPP; | ||
413 | if (features) { | 444 | if (features) { |
414 | DMERR("could not access metadata due to unsupported optional features (%lx).", | 445 | DMERR("could not access metadata due to unsupported optional features (%lx).", |
415 | (unsigned long)features); | 446 | (unsigned long)features); |
@@ -470,6 +501,7 @@ static int __open_metadata(struct dm_cache_metadata *cmd) | |||
470 | } | 501 | } |
471 | 502 | ||
472 | __setup_mapping_info(cmd); | 503 | __setup_mapping_info(cmd); |
504 | dm_disk_bitset_init(cmd->tm, &cmd->dirty_info); | ||
473 | dm_disk_bitset_init(cmd->tm, &cmd->discard_info); | 505 | dm_disk_bitset_init(cmd->tm, &cmd->discard_info); |
474 | sb_flags = le32_to_cpu(disk_super->flags); | 506 | sb_flags = le32_to_cpu(disk_super->flags); |
475 | cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags); | 507 | cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags); |
@@ -548,6 +580,7 @@ static unsigned long clear_clean_shutdown(unsigned long flags) | |||
548 | static void read_superblock_fields(struct dm_cache_metadata *cmd, | 580 | static void read_superblock_fields(struct dm_cache_metadata *cmd, |
549 | struct cache_disk_superblock *disk_super) | 581 | struct cache_disk_superblock *disk_super) |
550 | { | 582 | { |
583 | cmd->version = le32_to_cpu(disk_super->version); | ||
551 | cmd->flags = le32_to_cpu(disk_super->flags); | 584 | cmd->flags = le32_to_cpu(disk_super->flags); |
552 | cmd->root = le64_to_cpu(disk_super->mapping_root); | 585 | cmd->root = le64_to_cpu(disk_super->mapping_root); |
553 | cmd->hint_root = le64_to_cpu(disk_super->hint_root); | 586 | cmd->hint_root = le64_to_cpu(disk_super->hint_root); |
@@ -567,6 +600,9 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd, | |||
567 | cmd->stats.write_hits = le32_to_cpu(disk_super->write_hits); | 600 | cmd->stats.write_hits = le32_to_cpu(disk_super->write_hits); |
568 | cmd->stats.write_misses = le32_to_cpu(disk_super->write_misses); | 601 | cmd->stats.write_misses = le32_to_cpu(disk_super->write_misses); |
569 | 602 | ||
603 | if (separate_dirty_bits(cmd)) | ||
604 | cmd->dirty_root = le64_to_cpu(disk_super->dirty_root); | ||
605 | |||
570 | cmd->changed = false; | 606 | cmd->changed = false; |
571 | } | 607 | } |
572 | 608 | ||
@@ -625,6 +661,13 @@ static int __commit_transaction(struct dm_cache_metadata *cmd, | |||
625 | */ | 661 | */ |
626 | BUILD_BUG_ON(sizeof(struct cache_disk_superblock) > 512); | 662 | BUILD_BUG_ON(sizeof(struct cache_disk_superblock) > 512); |
627 | 663 | ||
664 | if (separate_dirty_bits(cmd)) { | ||
665 | r = dm_bitset_flush(&cmd->dirty_info, cmd->dirty_root, | ||
666 | &cmd->dirty_root); | ||
667 | if (r) | ||
668 | return r; | ||
669 | } | ||
670 | |||
628 | r = dm_bitset_flush(&cmd->discard_info, cmd->discard_root, | 671 | r = dm_bitset_flush(&cmd->discard_info, cmd->discard_root, |
629 | &cmd->discard_root); | 672 | &cmd->discard_root); |
630 | if (r) | 673 | if (r) |
@@ -649,6 +692,8 @@ static int __commit_transaction(struct dm_cache_metadata *cmd, | |||
649 | update_flags(disk_super, mutator); | 692 | update_flags(disk_super, mutator); |
650 | 693 | ||
651 | disk_super->mapping_root = cpu_to_le64(cmd->root); | 694 | disk_super->mapping_root = cpu_to_le64(cmd->root); |
695 | if (separate_dirty_bits(cmd)) | ||
696 | disk_super->dirty_root = cpu_to_le64(cmd->dirty_root); | ||
652 | disk_super->hint_root = cpu_to_le64(cmd->hint_root); | 697 | disk_super->hint_root = cpu_to_le64(cmd->hint_root); |
653 | disk_super->discard_root = cpu_to_le64(cmd->discard_root); | 698 | disk_super->discard_root = cpu_to_le64(cmd->discard_root); |
654 | disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size); | 699 | disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size); |
@@ -698,7 +743,8 @@ static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags) | |||
698 | static struct dm_cache_metadata *metadata_open(struct block_device *bdev, | 743 | static struct dm_cache_metadata *metadata_open(struct block_device *bdev, |
699 | sector_t data_block_size, | 744 | sector_t data_block_size, |
700 | bool may_format_device, | 745 | bool may_format_device, |
701 | size_t policy_hint_size) | 746 | size_t policy_hint_size, |
747 | unsigned metadata_version) | ||
702 | { | 748 | { |
703 | int r; | 749 | int r; |
704 | struct dm_cache_metadata *cmd; | 750 | struct dm_cache_metadata *cmd; |
@@ -709,6 +755,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev, | |||
709 | return ERR_PTR(-ENOMEM); | 755 | return ERR_PTR(-ENOMEM); |
710 | } | 756 | } |
711 | 757 | ||
758 | cmd->version = metadata_version; | ||
712 | atomic_set(&cmd->ref_count, 1); | 759 | atomic_set(&cmd->ref_count, 1); |
713 | init_rwsem(&cmd->root_lock); | 760 | init_rwsem(&cmd->root_lock); |
714 | cmd->bdev = bdev; | 761 | cmd->bdev = bdev; |
@@ -757,7 +804,8 @@ static struct dm_cache_metadata *lookup(struct block_device *bdev) | |||
757 | static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, | 804 | static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, |
758 | sector_t data_block_size, | 805 | sector_t data_block_size, |
759 | bool may_format_device, | 806 | bool may_format_device, |
760 | size_t policy_hint_size) | 807 | size_t policy_hint_size, |
808 | unsigned metadata_version) | ||
761 | { | 809 | { |
762 | struct dm_cache_metadata *cmd, *cmd2; | 810 | struct dm_cache_metadata *cmd, *cmd2; |
763 | 811 | ||
@@ -768,7 +816,8 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, | |||
768 | if (cmd) | 816 | if (cmd) |
769 | return cmd; | 817 | return cmd; |
770 | 818 | ||
771 | cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size); | 819 | cmd = metadata_open(bdev, data_block_size, may_format_device, |
820 | policy_hint_size, metadata_version); | ||
772 | if (!IS_ERR(cmd)) { | 821 | if (!IS_ERR(cmd)) { |
773 | mutex_lock(&table_lock); | 822 | mutex_lock(&table_lock); |
774 | cmd2 = lookup(bdev); | 823 | cmd2 = lookup(bdev); |
@@ -800,10 +849,11 @@ static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size) | |||
800 | struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, | 849 | struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, |
801 | sector_t data_block_size, | 850 | sector_t data_block_size, |
802 | bool may_format_device, | 851 | bool may_format_device, |
803 | size_t policy_hint_size) | 852 | size_t policy_hint_size, |
853 | unsigned metadata_version) | ||
804 | { | 854 | { |
805 | struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, | 855 | struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, may_format_device, |
806 | may_format_device, policy_hint_size); | 856 | policy_hint_size, metadata_version); |
807 | 857 | ||
808 | if (!IS_ERR(cmd) && !same_params(cmd, data_block_size)) { | 858 | if (!IS_ERR(cmd) && !same_params(cmd, data_block_size)) { |
809 | dm_cache_metadata_close(cmd); | 859 | dm_cache_metadata_close(cmd); |
@@ -829,8 +879,8 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd) | |||
829 | /* | 879 | /* |
830 | * Checks that the given cache block is either unmapped or clean. | 880 | * Checks that the given cache block is either unmapped or clean. |
831 | */ | 881 | */ |
832 | static int block_unmapped_or_clean(struct dm_cache_metadata *cmd, dm_cblock_t b, | 882 | static int block_clean_combined_dirty(struct dm_cache_metadata *cmd, dm_cblock_t b, |
833 | bool *result) | 883 | bool *result) |
834 | { | 884 | { |
835 | int r; | 885 | int r; |
836 | __le64 value; | 886 | __le64 value; |
@@ -838,10 +888,8 @@ static int block_unmapped_or_clean(struct dm_cache_metadata *cmd, dm_cblock_t b, | |||
838 | unsigned flags; | 888 | unsigned flags; |
839 | 889 | ||
840 | r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(b), &value); | 890 | r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(b), &value); |
841 | if (r) { | 891 | if (r) |
842 | DMERR("block_unmapped_or_clean failed"); | ||
843 | return r; | 892 | return r; |
844 | } | ||
845 | 893 | ||
846 | unpack_value(value, &ob, &flags); | 894 | unpack_value(value, &ob, &flags); |
847 | *result = !((flags & M_VALID) && (flags & M_DIRTY)); | 895 | *result = !((flags & M_VALID) && (flags & M_DIRTY)); |
@@ -849,17 +897,19 @@ static int block_unmapped_or_clean(struct dm_cache_metadata *cmd, dm_cblock_t b, | |||
849 | return 0; | 897 | return 0; |
850 | } | 898 | } |
851 | 899 | ||
852 | static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, | 900 | static int blocks_are_clean_combined_dirty(struct dm_cache_metadata *cmd, |
853 | dm_cblock_t begin, dm_cblock_t end, | 901 | dm_cblock_t begin, dm_cblock_t end, |
854 | bool *result) | 902 | bool *result) |
855 | { | 903 | { |
856 | int r; | 904 | int r; |
857 | *result = true; | 905 | *result = true; |
858 | 906 | ||
859 | while (begin != end) { | 907 | while (begin != end) { |
860 | r = block_unmapped_or_clean(cmd, begin, result); | 908 | r = block_clean_combined_dirty(cmd, begin, result); |
861 | if (r) | 909 | if (r) { |
910 | DMERR("block_clean_combined_dirty failed"); | ||
862 | return r; | 911 | return r; |
912 | } | ||
863 | 913 | ||
864 | if (!*result) { | 914 | if (!*result) { |
865 | DMERR("cache block %llu is dirty", | 915 | DMERR("cache block %llu is dirty", |
@@ -873,6 +923,48 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, | |||
873 | return 0; | 923 | return 0; |
874 | } | 924 | } |
875 | 925 | ||
926 | static int blocks_are_clean_separate_dirty(struct dm_cache_metadata *cmd, | ||
927 | dm_cblock_t begin, dm_cblock_t end, | ||
928 | bool *result) | ||
929 | { | ||
930 | int r; | ||
931 | bool dirty_flag; | ||
932 | *result = true; | ||
933 | |||
934 | // FIXME: use a cursor so we can benefit from preloading metadata. | ||
935 | while (begin != end) { | ||
936 | /* | ||
937 | * We assume that unmapped blocks have their dirty bit | ||
938 | * cleared. | ||
939 | */ | ||
940 | r = dm_bitset_test_bit(&cmd->dirty_info, cmd->dirty_root, | ||
941 | from_cblock(begin), &cmd->dirty_root, &dirty_flag); | ||
942 | if (r) | ||
943 | return r; | ||
944 | |||
945 | if (dirty_flag) { | ||
946 | DMERR("cache block %llu is dirty", | ||
947 | (unsigned long long) from_cblock(begin)); | ||
948 | *result = false; | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | begin = to_cblock(from_cblock(begin) + 1); | ||
953 | } | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, | ||
959 | dm_cblock_t begin, dm_cblock_t end, | ||
960 | bool *result) | ||
961 | { | ||
962 | if (separate_dirty_bits(cmd)) | ||
963 | return blocks_are_clean_separate_dirty(cmd, begin, end, result); | ||
964 | else | ||
965 | return blocks_are_clean_combined_dirty(cmd, begin, end, result); | ||
966 | } | ||
967 | |||
876 | static bool cmd_write_lock(struct dm_cache_metadata *cmd) | 968 | static bool cmd_write_lock(struct dm_cache_metadata *cmd) |
877 | { | 969 | { |
878 | down_write(&cmd->root_lock); | 970 | down_write(&cmd->root_lock); |
@@ -950,8 +1042,18 @@ int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) | |||
950 | r = dm_array_resize(&cmd->info, cmd->root, from_cblock(cmd->cache_blocks), | 1042 | r = dm_array_resize(&cmd->info, cmd->root, from_cblock(cmd->cache_blocks), |
951 | from_cblock(new_cache_size), | 1043 | from_cblock(new_cache_size), |
952 | &null_mapping, &cmd->root); | 1044 | &null_mapping, &cmd->root); |
953 | if (!r) | 1045 | if (r) |
954 | cmd->cache_blocks = new_cache_size; | 1046 | goto out; |
1047 | |||
1048 | if (separate_dirty_bits(cmd)) { | ||
1049 | r = dm_bitset_resize(&cmd->dirty_info, cmd->dirty_root, | ||
1050 | from_cblock(cmd->cache_blocks), from_cblock(new_cache_size), | ||
1051 | false, &cmd->dirty_root); | ||
1052 | if (r) | ||
1053 | goto out; | ||
1054 | } | ||
1055 | |||
1056 | cmd->cache_blocks = new_cache_size; | ||
955 | cmd->changed = true; | 1057 | cmd->changed = true; |
956 | 1058 | ||
957 | out: | 1059 | out: |
@@ -1185,11 +1287,11 @@ static bool hints_array_available(struct dm_cache_metadata *cmd, | |||
1185 | hints_array_initialized(cmd); | 1287 | hints_array_initialized(cmd); |
1186 | } | 1288 | } |
1187 | 1289 | ||
1188 | static int __load_mapping(struct dm_cache_metadata *cmd, | 1290 | static int __load_mapping_v1(struct dm_cache_metadata *cmd, |
1189 | uint64_t cb, bool hints_valid, | 1291 | uint64_t cb, bool hints_valid, |
1190 | struct dm_array_cursor *mapping_cursor, | 1292 | struct dm_array_cursor *mapping_cursor, |
1191 | struct dm_array_cursor *hint_cursor, | 1293 | struct dm_array_cursor *hint_cursor, |
1192 | load_mapping_fn fn, void *context) | 1294 | load_mapping_fn fn, void *context) |
1193 | { | 1295 | { |
1194 | int r = 0; | 1296 | int r = 0; |
1195 | 1297 | ||
@@ -1221,6 +1323,45 @@ static int __load_mapping(struct dm_cache_metadata *cmd, | |||
1221 | return r; | 1323 | return r; |
1222 | } | 1324 | } |
1223 | 1325 | ||
1326 | static int __load_mapping_v2(struct dm_cache_metadata *cmd, | ||
1327 | uint64_t cb, bool hints_valid, | ||
1328 | struct dm_array_cursor *mapping_cursor, | ||
1329 | struct dm_array_cursor *hint_cursor, | ||
1330 | struct dm_bitset_cursor *dirty_cursor, | ||
1331 | load_mapping_fn fn, void *context) | ||
1332 | { | ||
1333 | int r = 0; | ||
1334 | |||
1335 | __le64 mapping; | ||
1336 | __le32 hint = 0; | ||
1337 | |||
1338 | __le64 *mapping_value_le; | ||
1339 | __le32 *hint_value_le; | ||
1340 | |||
1341 | dm_oblock_t oblock; | ||
1342 | unsigned flags; | ||
1343 | bool dirty; | ||
1344 | |||
1345 | dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le); | ||
1346 | memcpy(&mapping, mapping_value_le, sizeof(mapping)); | ||
1347 | unpack_value(mapping, &oblock, &flags); | ||
1348 | |||
1349 | if (flags & M_VALID) { | ||
1350 | if (hints_valid) { | ||
1351 | dm_array_cursor_get_value(hint_cursor, (void **) &hint_value_le); | ||
1352 | memcpy(&hint, hint_value_le, sizeof(hint)); | ||
1353 | } | ||
1354 | |||
1355 | dirty = dm_bitset_cursor_get_value(dirty_cursor); | ||
1356 | r = fn(context, oblock, to_cblock(cb), dirty, | ||
1357 | le32_to_cpu(hint), hints_valid); | ||
1358 | if (r) | ||
1359 | DMERR("policy couldn't load cblock"); | ||
1360 | } | ||
1361 | |||
1362 | return r; | ||
1363 | } | ||
1364 | |||
1224 | static int __load_mappings(struct dm_cache_metadata *cmd, | 1365 | static int __load_mappings(struct dm_cache_metadata *cmd, |
1225 | struct dm_cache_policy *policy, | 1366 | struct dm_cache_policy *policy, |
1226 | load_mapping_fn fn, void *context) | 1367 | load_mapping_fn fn, void *context) |
@@ -1246,10 +1387,28 @@ static int __load_mappings(struct dm_cache_metadata *cmd, | |||
1246 | } | 1387 | } |
1247 | } | 1388 | } |
1248 | 1389 | ||
1390 | if (separate_dirty_bits(cmd)) { | ||
1391 | r = dm_bitset_cursor_begin(&cmd->dirty_info, cmd->dirty_root, | ||
1392 | from_cblock(cmd->cache_blocks), | ||
1393 | &cmd->dirty_cursor); | ||
1394 | if (r) { | ||
1395 | dm_array_cursor_end(&cmd->hint_cursor); | ||
1396 | dm_array_cursor_end(&cmd->mapping_cursor); | ||
1397 | return r; | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1249 | for (cb = 0; ; cb++) { | 1401 | for (cb = 0; ; cb++) { |
1250 | r = __load_mapping(cmd, cb, hints_valid, | 1402 | if (separate_dirty_bits(cmd)) |
1251 | &cmd->mapping_cursor, &cmd->hint_cursor, | 1403 | r = __load_mapping_v2(cmd, cb, hints_valid, |
1252 | fn, context); | 1404 | &cmd->mapping_cursor, |
1405 | &cmd->hint_cursor, | ||
1406 | &cmd->dirty_cursor, | ||
1407 | fn, context); | ||
1408 | else | ||
1409 | r = __load_mapping_v1(cmd, cb, hints_valid, | ||
1410 | &cmd->mapping_cursor, &cmd->hint_cursor, | ||
1411 | fn, context); | ||
1253 | if (r) | 1412 | if (r) |
1254 | goto out; | 1413 | goto out; |
1255 | 1414 | ||
@@ -1272,12 +1431,23 @@ static int __load_mappings(struct dm_cache_metadata *cmd, | |||
1272 | goto out; | 1431 | goto out; |
1273 | } | 1432 | } |
1274 | } | 1433 | } |
1434 | |||
1435 | if (separate_dirty_bits(cmd)) { | ||
1436 | r = dm_bitset_cursor_next(&cmd->dirty_cursor); | ||
1437 | if (r) { | ||
1438 | DMERR("dm_bitset_cursor_next for dirty failed"); | ||
1439 | goto out; | ||
1440 | } | ||
1441 | } | ||
1275 | } | 1442 | } |
1276 | out: | 1443 | out: |
1277 | dm_array_cursor_end(&cmd->mapping_cursor); | 1444 | dm_array_cursor_end(&cmd->mapping_cursor); |
1278 | if (hints_valid) | 1445 | if (hints_valid) |
1279 | dm_array_cursor_end(&cmd->hint_cursor); | 1446 | dm_array_cursor_end(&cmd->hint_cursor); |
1280 | 1447 | ||
1448 | if (separate_dirty_bits(cmd)) | ||
1449 | dm_bitset_cursor_end(&cmd->dirty_cursor); | ||
1450 | |||
1281 | return r; | 1451 | return r; |
1282 | } | 1452 | } |
1283 | 1453 | ||
@@ -1360,13 +1530,55 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty | |||
1360 | 1530 | ||
1361 | } | 1531 | } |
1362 | 1532 | ||
1363 | int dm_cache_set_dirty(struct dm_cache_metadata *cmd, | 1533 | static int __set_dirty_bits_v1(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits) |
1364 | dm_cblock_t cblock, bool dirty) | 1534 | { |
1535 | int r; | ||
1536 | unsigned i; | ||
1537 | for (i = 0; i < nr_bits; i++) { | ||
1538 | r = __dirty(cmd, to_cblock(i), test_bit(i, bits)); | ||
1539 | if (r) | ||
1540 | return r; | ||
1541 | } | ||
1542 | |||
1543 | return 0; | ||
1544 | } | ||
1545 | |||
1546 | static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits) | ||
1547 | { | ||
1548 | int r = 0; | ||
1549 | unsigned i; | ||
1550 | |||
1551 | /* nr_bits is really just a sanity check */ | ||
1552 | if (nr_bits != from_cblock(cmd->cache_blocks)) { | ||
1553 | DMERR("dirty bitset is wrong size"); | ||
1554 | return -EINVAL; | ||
1555 | } | ||
1556 | |||
1557 | for (i = 0; i < nr_bits; i++) { | ||
1558 | if (test_bit(i, bits)) | ||
1559 | r = dm_bitset_set_bit(&cmd->dirty_info, cmd->dirty_root, i, &cmd->dirty_root); | ||
1560 | else | ||
1561 | r = dm_bitset_clear_bit(&cmd->dirty_info, cmd->dirty_root, i, &cmd->dirty_root); | ||
1562 | |||
1563 | if (r) | ||
1564 | return r; | ||
1565 | } | ||
1566 | |||
1567 | cmd->changed = true; | ||
1568 | return dm_bitset_flush(&cmd->dirty_info, cmd->dirty_root, &cmd->dirty_root); | ||
1569 | } | ||
1570 | |||
1571 | int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd, | ||
1572 | unsigned nr_bits, | ||
1573 | unsigned long *bits) | ||
1365 | { | 1574 | { |
1366 | int r; | 1575 | int r; |
1367 | 1576 | ||
1368 | WRITE_LOCK(cmd); | 1577 | WRITE_LOCK(cmd); |
1369 | r = __dirty(cmd, cblock, dirty); | 1578 | if (separate_dirty_bits(cmd)) |
1579 | r = __set_dirty_bits_v2(cmd, nr_bits, bits); | ||
1580 | else | ||
1581 | r = __set_dirty_bits_v1(cmd, nr_bits, bits); | ||
1370 | WRITE_UNLOCK(cmd); | 1582 | WRITE_UNLOCK(cmd); |
1371 | 1583 | ||
1372 | return r; | 1584 | return r; |
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h index 8528744195e5..4f07c08cf107 100644 --- a/drivers/md/dm-cache-metadata.h +++ b/drivers/md/dm-cache-metadata.h | |||
@@ -45,18 +45,20 @@ | |||
45 | * As these various flags are defined they should be added to the | 45 | * As these various flags are defined they should be added to the |
46 | * following masks. | 46 | * following masks. |
47 | */ | 47 | */ |
48 | |||
48 | #define DM_CACHE_FEATURE_COMPAT_SUPP 0UL | 49 | #define DM_CACHE_FEATURE_COMPAT_SUPP 0UL |
49 | #define DM_CACHE_FEATURE_COMPAT_RO_SUPP 0UL | 50 | #define DM_CACHE_FEATURE_COMPAT_RO_SUPP 0UL |
50 | #define DM_CACHE_FEATURE_INCOMPAT_SUPP 0UL | 51 | #define DM_CACHE_FEATURE_INCOMPAT_SUPP 0UL |
51 | 52 | ||
52 | /* | 53 | /* |
53 | * Reopens or creates a new, empty metadata volume. | 54 | * Reopens or creates a new, empty metadata volume. Returns an ERR_PTR on |
54 | * Returns an ERR_PTR on failure. | 55 | * failure. If reopening then features must match. |
55 | */ | 56 | */ |
56 | struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, | 57 | struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, |
57 | sector_t data_block_size, | 58 | sector_t data_block_size, |
58 | bool may_format_device, | 59 | bool may_format_device, |
59 | size_t policy_hint_size); | 60 | size_t policy_hint_size, |
61 | unsigned metadata_version); | ||
60 | 62 | ||
61 | void dm_cache_metadata_close(struct dm_cache_metadata *cmd); | 63 | void dm_cache_metadata_close(struct dm_cache_metadata *cmd); |
62 | 64 | ||
@@ -91,7 +93,8 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd, | |||
91 | load_mapping_fn fn, | 93 | load_mapping_fn fn, |
92 | void *context); | 94 | void *context); |
93 | 95 | ||
94 | int dm_cache_set_dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty); | 96 | int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd, |
97 | unsigned nr_bits, unsigned long *bits); | ||
95 | 98 | ||
96 | struct dm_cache_statistics { | 99 | struct dm_cache_statistics { |
97 | uint32_t read_hits; | 100 | uint32_t read_hits; |
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 897dc72f07c9..5813d2a7eefe 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c | |||
@@ -179,6 +179,7 @@ enum cache_io_mode { | |||
179 | struct cache_features { | 179 | struct cache_features { |
180 | enum cache_metadata_mode mode; | 180 | enum cache_metadata_mode mode; |
181 | enum cache_io_mode io_mode; | 181 | enum cache_io_mode io_mode; |
182 | unsigned metadata_version; | ||
182 | }; | 183 | }; |
183 | 184 | ||
184 | struct cache_stats { | 185 | struct cache_stats { |
@@ -2541,13 +2542,14 @@ static void init_features(struct cache_features *cf) | |||
2541 | { | 2542 | { |
2542 | cf->mode = CM_WRITE; | 2543 | cf->mode = CM_WRITE; |
2543 | cf->io_mode = CM_IO_WRITEBACK; | 2544 | cf->io_mode = CM_IO_WRITEBACK; |
2545 | cf->metadata_version = 1; | ||
2544 | } | 2546 | } |
2545 | 2547 | ||
2546 | static int parse_features(struct cache_args *ca, struct dm_arg_set *as, | 2548 | static int parse_features(struct cache_args *ca, struct dm_arg_set *as, |
2547 | char **error) | 2549 | char **error) |
2548 | { | 2550 | { |
2549 | static struct dm_arg _args[] = { | 2551 | static struct dm_arg _args[] = { |
2550 | {0, 1, "Invalid number of cache feature arguments"}, | 2552 | {0, 2, "Invalid number of cache feature arguments"}, |
2551 | }; | 2553 | }; |
2552 | 2554 | ||
2553 | int r; | 2555 | int r; |
@@ -2573,6 +2575,9 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as, | |||
2573 | else if (!strcasecmp(arg, "passthrough")) | 2575 | else if (!strcasecmp(arg, "passthrough")) |
2574 | cf->io_mode = CM_IO_PASSTHROUGH; | 2576 | cf->io_mode = CM_IO_PASSTHROUGH; |
2575 | 2577 | ||
2578 | else if (!strcasecmp(arg, "metadata2")) | ||
2579 | cf->metadata_version = 2; | ||
2580 | |||
2576 | else { | 2581 | else { |
2577 | *error = "Unrecognised cache feature requested"; | 2582 | *error = "Unrecognised cache feature requested"; |
2578 | return -EINVAL; | 2583 | return -EINVAL; |
@@ -2827,7 +2832,8 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
2827 | 2832 | ||
2828 | cmd = dm_cache_metadata_open(cache->metadata_dev->bdev, | 2833 | cmd = dm_cache_metadata_open(cache->metadata_dev->bdev, |
2829 | ca->block_size, may_format, | 2834 | ca->block_size, may_format, |
2830 | dm_cache_policy_get_hint_size(cache->policy)); | 2835 | dm_cache_policy_get_hint_size(cache->policy), |
2836 | ca->features.metadata_version); | ||
2831 | if (IS_ERR(cmd)) { | 2837 | if (IS_ERR(cmd)) { |
2832 | *error = "Error creating metadata object"; | 2838 | *error = "Error creating metadata object"; |
2833 | r = PTR_ERR(cmd); | 2839 | r = PTR_ERR(cmd); |
@@ -3172,21 +3178,16 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error) | |||
3172 | 3178 | ||
3173 | static int write_dirty_bitset(struct cache *cache) | 3179 | static int write_dirty_bitset(struct cache *cache) |
3174 | { | 3180 | { |
3175 | unsigned i, r; | 3181 | int r; |
3176 | 3182 | ||
3177 | if (get_cache_mode(cache) >= CM_READ_ONLY) | 3183 | if (get_cache_mode(cache) >= CM_READ_ONLY) |
3178 | return -EINVAL; | 3184 | return -EINVAL; |
3179 | 3185 | ||
3180 | for (i = 0; i < from_cblock(cache->cache_size); i++) { | 3186 | r = dm_cache_set_dirty_bits(cache->cmd, from_cblock(cache->cache_size), cache->dirty_bitset); |
3181 | r = dm_cache_set_dirty(cache->cmd, to_cblock(i), | 3187 | if (r) |
3182 | is_dirty(cache, to_cblock(i))); | 3188 | metadata_operation_failed(cache, "dm_cache_set_dirty_bits", r); |
3183 | if (r) { | ||
3184 | metadata_operation_failed(cache, "dm_cache_set_dirty", r); | ||
3185 | return r; | ||
3186 | } | ||
3187 | } | ||
3188 | 3189 | ||
3189 | return 0; | 3190 | return r; |
3190 | } | 3191 | } |
3191 | 3192 | ||
3192 | static int write_discard_bitset(struct cache *cache) | 3193 | static int write_discard_bitset(struct cache *cache) |
@@ -3562,14 +3563,19 @@ static void cache_status(struct dm_target *ti, status_type_t type, | |||
3562 | (unsigned) atomic_read(&cache->stats.promotion), | 3563 | (unsigned) atomic_read(&cache->stats.promotion), |
3563 | (unsigned long) atomic_read(&cache->nr_dirty)); | 3564 | (unsigned long) atomic_read(&cache->nr_dirty)); |
3564 | 3565 | ||
3566 | if (cache->features.metadata_version == 2) | ||
3567 | DMEMIT("2 metadata2 "); | ||
3568 | else | ||
3569 | DMEMIT("1 "); | ||
3570 | |||
3565 | if (writethrough_mode(&cache->features)) | 3571 | if (writethrough_mode(&cache->features)) |
3566 | DMEMIT("1 writethrough "); | 3572 | DMEMIT("writethrough "); |
3567 | 3573 | ||
3568 | else if (passthrough_mode(&cache->features)) | 3574 | else if (passthrough_mode(&cache->features)) |
3569 | DMEMIT("1 passthrough "); | 3575 | DMEMIT("passthrough "); |
3570 | 3576 | ||
3571 | else if (writeback_mode(&cache->features)) | 3577 | else if (writeback_mode(&cache->features)) |
3572 | DMEMIT("1 writeback "); | 3578 | DMEMIT("writeback "); |
3573 | 3579 | ||
3574 | else { | 3580 | else { |
3575 | DMERR("%s: internal error: unknown io mode: %d", | 3581 | DMERR("%s: internal error: unknown io mode: %d", |
@@ -3817,7 +3823,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
3817 | 3823 | ||
3818 | static struct target_type cache_target = { | 3824 | static struct target_type cache_target = { |
3819 | .name = "cache", | 3825 | .name = "cache", |
3820 | .version = {1, 9, 0}, | 3826 | .version = {1, 10, 0}, |
3821 | .module = THIS_MODULE, | 3827 | .module = THIS_MODULE, |
3822 | .ctr = cache_ctr, | 3828 | .ctr = cache_ctr, |
3823 | .dtr = cache_dtr, | 3829 | .dtr = cache_dtr, |