aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2016-04-12 12:14:46 -0400
committerMike Snitzer <snitzer@redhat.com>2016-04-14 17:34:49 -0400
commit9567366fefddeaea4ed1d713270535d93a3b3c76 (patch)
tree92829c59c613f72cedc01fb14685915bce060468
parent072623de1f964c7ff01c46a9101af1c822fd2873 (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.c64
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) \ 870static 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) \ 895static 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
904int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) 920int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
905{ 921{