diff options
author | Mike Snitzer <snitzer@redhat.com> | 2016-04-12 12:14:46 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-04-14 17:34:49 -0400 |
commit | 9567366fefddeaea4ed1d713270535d93a3b3c76 (patch) | |
tree | 92829c59c613f72cedc01fb14685915bce060468 | |
parent | 072623de1f964c7ff01c46a9101af1c822fd2873 (diff) |
dm cache metadata: fix READ_LOCK macros and cleanup WRITE_LOCK macros
The READ_LOCK macro was incorrectly returning -EINVAL if
dm_bm_is_read_only() was true -- it will always be true once the cache
metadata transitions to read-only by dm_cache_metadata_set_read_only().
Wrap READ_LOCK and WRITE_LOCK multi-statement macros in do {} while(0).
Also, all accesses of the 'cmd' argument passed to these related macros
are now encapsulated in parenthesis.
A follow-up patch can be developed to eliminate the use of macros in
favor of pure C code. Avoiding that now given that this needs to apply
to stable@.
Reported-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Fixes: d14fcf3dd79 ("dm cache: make sure every metadata function checks fail_io")
Cc: stable@vger.kernel.org
-rw-r--r-- | drivers/md/dm-cache-metadata.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 27f2ef300f8b..65ce6985f87a 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c | |||
@@ -867,39 +867,55 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, | |||
867 | return 0; | 867 | return 0; |
868 | } | 868 | } |
869 | 869 | ||
870 | #define WRITE_LOCK(cmd) \ | 870 | static bool cmd_write_lock(struct dm_cache_metadata *cmd) |
871 | down_write(&cmd->root_lock); \ | 871 | { |
872 | if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ | 872 | down_write(&cmd->root_lock); |
873 | up_write(&cmd->root_lock); \ | 873 | if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { |
874 | return -EINVAL; \ | 874 | up_write(&cmd->root_lock); |
875 | return false; | ||
875 | } | 876 | } |
877 | return true; | ||
878 | } | ||
876 | 879 | ||
877 | #define WRITE_LOCK_VOID(cmd) \ | 880 | #define WRITE_LOCK(cmd) \ |
878 | down_write(&cmd->root_lock); \ | 881 | do { \ |
879 | if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ | 882 | if (!cmd_write_lock((cmd))) \ |
880 | up_write(&cmd->root_lock); \ | 883 | return -EINVAL; \ |
881 | return; \ | 884 | } while(0) |
882 | } | 885 | |
886 | #define WRITE_LOCK_VOID(cmd) \ | ||
887 | do { \ | ||
888 | if (!cmd_write_lock((cmd))) \ | ||
889 | return; \ | ||
890 | } while(0) | ||
883 | 891 | ||
884 | #define WRITE_UNLOCK(cmd) \ | 892 | #define WRITE_UNLOCK(cmd) \ |
885 | up_write(&cmd->root_lock) | 893 | up_write(&(cmd)->root_lock) |
886 | 894 | ||
887 | #define READ_LOCK(cmd) \ | 895 | static bool cmd_read_lock(struct dm_cache_metadata *cmd) |
888 | down_read(&cmd->root_lock); \ | 896 | { |
889 | if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ | 897 | down_write(&cmd->root_lock); |
890 | up_read(&cmd->root_lock); \ | 898 | if (cmd->fail_io) { |
891 | return -EINVAL; \ | 899 | up_write(&cmd->root_lock); |
900 | return false; | ||
892 | } | 901 | } |
902 | return true; | ||
903 | } | ||
893 | 904 | ||
894 | #define READ_LOCK_VOID(cmd) \ | 905 | #define READ_LOCK(cmd) \ |
895 | down_read(&cmd->root_lock); \ | 906 | do { \ |
896 | if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ | 907 | if (!cmd_read_lock((cmd))) \ |
897 | up_read(&cmd->root_lock); \ | 908 | return -EINVAL; \ |
898 | return; \ | 909 | } while(0) |
899 | } | 910 | |
911 | #define READ_LOCK_VOID(cmd) \ | ||
912 | do { \ | ||
913 | if (!cmd_read_lock((cmd))) \ | ||
914 | return; \ | ||
915 | } while(0) | ||
900 | 916 | ||
901 | #define READ_UNLOCK(cmd) \ | 917 | #define READ_UNLOCK(cmd) \ |
902 | up_read(&cmd->root_lock) | 918 | up_read(&(cmd)->root_lock) |
903 | 919 | ||
904 | int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) | 920 | int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) |
905 | { | 921 | { |